Tagged swarmtv 0.9.2, added: static library, libtool archive, and buildfixes for centos 5.6. Fixed buildscripts, source builds using debian pbuilder now.

ranzbak [2011-05-11 17:47]
Tagged swarmtv 0.9.2, added: static library, libtool archive, and buildfixes for centos 5.6. Fixed buildscripts, source builds using debian pbuilder now.

git-svn-id: https://old.setv.nl/svn/swarmtv@316 88541080-9ad6-de11-9093-5254007c1f44
Filename
tags/swarmtv-0.9.2/CMakeLists.txt
tags/swarmtv-0.9.2/cmake_modules/CMakeMacroLibtoolFile.cmake
tags/swarmtv-0.9.2/cmake_modules/FindDBus.cmake
tags/swarmtv-0.9.2/cmake_modules/FindDbusGlib.cmake
tags/swarmtv-0.9.2/cmake_modules/FindESMTP.cmake
tags/swarmtv-0.9.2/cmake_modules/FindGLIB2.cmake
tags/swarmtv-0.9.2/cmake_modules/FindPCRE.cmake
tags/swarmtv-0.9.2/cmake_modules/FindSqlite.cmake
tags/swarmtv-0.9.2/cmake_modules/UsePkgConfig.cmake
tags/swarmtv-0.9.2/cmake_uninstall.cmake.in
tags/swarmtv-0.9.2/examples.bat
tags/swarmtv-0.9.2/examples.sh
tags/swarmtv-0.9.2/libswarmtv/CMakeLists.txt
tags/swarmtv-0.9.2/libswarmtv/baretitle.c
tags/swarmtv-0.9.2/libswarmtv/baretitle.h
tags/swarmtv-0.9.2/libswarmtv/callback.c
tags/swarmtv-0.9.2/libswarmtv/callback.h
tags/swarmtv-0.9.2/libswarmtv/config.c
tags/swarmtv-0.9.2/libswarmtv/config.h
tags/swarmtv-0.9.2/libswarmtv/createpc.sh
tags/swarmtv-0.9.2/libswarmtv/curlfile.c
tags/swarmtv-0.9.2/libswarmtv/curlfile.h
tags/swarmtv-0.9.2/libswarmtv/database.c
tags/swarmtv-0.9.2/libswarmtv/database.h
tags/swarmtv-0.9.2/libswarmtv/databaseimpl.c
tags/swarmtv-0.9.2/libswarmtv/databaseimpl.h
tags/swarmtv-0.9.2/libswarmtv/filehandler/CMakeLists.txt
tags/swarmtv-0.9.2/libswarmtv/filehandler/filehandler.c
tags/swarmtv-0.9.2/libswarmtv/filehandler/filehandler.h
tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/CMakeLists.txt
tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/findnzb.c
tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/findnzb.h
tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/nzbparse.c
tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/nzbparse.h
tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/CMakeLists.txt
tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/findtorrent.c
tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/findtorrent.h
tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/tbl.c
tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/tbl.h
tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/torrentparse.c
tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/torrentparse.h
tags/swarmtv-0.9.2/libswarmtv/filesystem.c
tags/swarmtv-0.9.2/libswarmtv/filesystem.h
tags/swarmtv-0.9.2/libswarmtv/filter.c
tags/swarmtv-0.9.2/libswarmtv/filter.h
tags/swarmtv-0.9.2/libswarmtv/lastdownloaded.c
tags/swarmtv-0.9.2/libswarmtv/lastdownloaded.h
tags/swarmtv-0.9.2/libswarmtv/libswarmtv.pc.template
tags/swarmtv-0.9.2/libswarmtv/libswarmtv.pro
tags/swarmtv-0.9.2/libswarmtv/logfile.c
tags/swarmtv-0.9.2/libswarmtv/logfile.h
tags/swarmtv-0.9.2/libswarmtv/regexp.c
tags/swarmtv-0.9.2/libswarmtv/regexp.h
tags/swarmtv-0.9.2/libswarmtv/runloop.c
tags/swarmtv-0.9.2/libswarmtv/runloop.h
tags/swarmtv-0.9.2/libswarmtv/sandboxdb.c
tags/swarmtv-0.9.2/libswarmtv/sandboxdb.h
tags/swarmtv-0.9.2/libswarmtv/setup.c
tags/swarmtv-0.9.2/libswarmtv/setup.h
tags/swarmtv-0.9.2/libswarmtv/simplefilter.c
tags/swarmtv-0.9.2/libswarmtv/simplefilter.h
tags/swarmtv-0.9.2/libswarmtv/source.c
tags/swarmtv-0.9.2/libswarmtv/source.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/CMakeLists.txt
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/CMakeLists.txt
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/defaultrss.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/defaultrss.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdate.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdate.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdescription.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdescription.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsscategory.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsscategory.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsslink.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsslink.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssparse.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssparse.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsspubdate.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsspubdate.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseasonepisode.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseasonepisode.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseedspeers.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseedspeers.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsssize.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsssize.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsstitle.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsstitle.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/CMakeLists.txt
tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/parsedate.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/parsedate.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/splittext.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/splittext.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitparse.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitparse.h
tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitter.c
tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitter.h
tags/swarmtv-0.9.2/libswarmtv/stats.c
tags/swarmtv-0.9.2/libswarmtv/stats.h
tags/swarmtv-0.9.2/libswarmtv/swarmtv.h
tags/swarmtv-0.9.2/libswarmtv/testfilter.c
tags/swarmtv-0.9.2/libswarmtv/testfilter.h
tags/swarmtv-0.9.2/libswarmtv/torrentdb.c
tags/swarmtv-0.9.2/libswarmtv/torrentdb.h
tags/swarmtv-0.9.2/libswarmtv/torrentdownload.c
tags/swarmtv-0.9.2/libswarmtv/torrentdownload.h
tags/swarmtv-0.9.2/libswarmtv/types.h
tags/swarmtv-0.9.2/libswarmtv/workarounds.c
tags/swarmtv-0.9.2/libswarmtv/workarounds.h
tags/swarmtv-0.9.2/license.txt
tags/swarmtv-0.9.2/readme.txt
tags/swarmtv-0.9.2/realclean.sh
tags/swarmtv-0.9.2/shellfront/CMakeLists.txt
tags/swarmtv-0.9.2/shellfront/daemonize.c
tags/swarmtv-0.9.2/shellfront/daemonize.h
tags/swarmtv-0.9.2/shellfront/dbus.c
tags/swarmtv-0.9.2/shellfront/dbus.h
tags/swarmtv-0.9.2/shellfront/frontfuncts.c
tags/swarmtv-0.9.2/shellfront/frontfuncts.h
tags/swarmtv-0.9.2/shellfront/handleopts.c
tags/swarmtv-0.9.2/shellfront/handleopts.h
tags/swarmtv-0.9.2/shellfront/mailmsg.c
tags/swarmtv-0.9.2/shellfront/mailmsg.h
tags/swarmtv-0.9.2/shellfront/man/swarmtv.1
tags/swarmtv-0.9.2/shellfront/present.c
tags/swarmtv-0.9.2/shellfront/present.h
tags/swarmtv-0.9.2/shellfront/runloop.c
tags/swarmtv-0.9.2/shellfront/runloop.h
tags/swarmtv-0.9.2/shellfront/shellfront.pro
tags/swarmtv-0.9.2/shellfront/simplewizard.c
tags/swarmtv-0.9.2/shellfront/simplewizard.h
tags/swarmtv-0.9.2/shellfront/swarmtv.c
tags/swarmtv-0.9.2/shellfront/xmlencode.c
tags/swarmtv-0.9.2/shellfront/xmlencode.h
tags/swarmtv-0.9.2/swarmtv.pro
tags/swarmtv-0.9.2/winservice/CMakeLists.txt
tags/swarmtv-0.9.2/winservice/swarmtvservice.c
tags/swarmtv-0.9.2/winservice/winservice.pro
diff --git a/tags/swarmtv-0.9.2/CMakeLists.txt b/tags/swarmtv-0.9.2/CMakeLists.txt
new file mode 100644
index 0000000..4000a65
--- /dev/null
+++ b/tags/swarmtv-0.9.2/CMakeLists.txt
@@ -0,0 +1,104 @@
+# The name of our project is "HELLO". CMakeLists files in this project can
+# refer to the root source directory of the project as ${HELLO_SOURCE_DIR} and
+# to the root binary directory of the project as ${HELLO_BINARY_DIR}.
+cmake_minimum_required(VERSION 2.6)
+project (swarmtv C)
+
+# Include libtool macro to enable install files
+INCLUDE( cmake_modules/CMakeMacroLibtoolFile.cmake )
+
+# Handle build switches
+IF(NOT DEFINED ESMTP_ENABLE)
+	SET(ESMTP_ENABLE TRUE)
+ENDIF()
+
+IF(NOT DEFINED SHELL_ENABLE)
+  SET(SHELL_ENABLE TRUE)
+ENDIF()
+
+IF(NOT DEFINED DEBUG_ENABLE)
+  SET(DEBUG_ENABLE TRUE)
+ENDIF()
+
+# When the SHELL FRONTEND is disabled, no Dbus Glib intergration is possible.
+IF(SHELL_ENABLE)
+  IF(NOT DEFINED DBUS_GLIB_ENABLE)
+    SET(DBUS_GLIB_ENABLE TRUE)
+  ENDIF()
+ELSE()
+  SET(DBUS_GLIB_ENABLE FALSE)
+ENDIF()
+
+# Print options
+MESSAGE("## OPTIONS ##")
+MESSAGE("DEBUG_ENABLE = ${DEBUG_ENABLE}")
+MESSAGE("ESMTP_ENABLE = ${ESMTP_ENABLE}")
+MESSAGE("SHELL_ENABLE = ${SHELL_ENABLE}")
+MESSAGE("DBUS_GLIB_ENABLE = ${DBUS_GLIB_ENABLE}")
+
+
+# Detect Libraries
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} /usr/share/apps/cmake/modules ${CMAKE_SOURCE_DIR}/cmake_modules)
+
+# When DBUS_GLIB is enabled, check the library
+IF(DBUS_GLIB_ENABLE)
+  FIND_PACKAGE(GLIB2 REQUIRED)
+  FIND_PACKAGE(DbusGlib REQUIRED)
+ENDIF()
+
+# Other libs
+FIND_PACKAGE(LibXml2 REQUIRED)
+FIND_PACKAGE(Sqlite REQUIRED)
+FIND_PACKAGE(PCRE REQUIRED)
+FIND_PACKAGE(CURL REQUIRED)
+
+# When ESMTP is enabled, check the library
+IF(ESMTP_ENABLE)
+	FIND_PACKAGE(ESMTP)
+	IF(ESMTP_FOUND)
+		ADD_DEFINITIONS(-DRSST_ESMTP_ENABLE="\\"1\\"")
+	ELSEIF()
+		MESSAGE("ESMTP NOT FOUND")
+	ENDIF()
+ELSEIF()
+	SET(ESMTP_FOUND FALSE)
+ENDIF()
+
+SET(RSSTORRENT_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+# Building libray and shell frontend
+add_subdirectory (libswarmtv)
+
+IF(SHELL_ENABLE)
+	add_subdirectory (shellfront)
+ENDIF()
+
+if (WIN32)
+	add_subdirectory (winservice)
+endif (WIN32)
+
+
+# Implement uninstall
+CONFIGURE_FILE(
+    "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
+    "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+    IMMEDIATE @ONLY)
+
+ADD_CUSTOM_TARGET(uninstall
+    "${CMAKE_COMMAND}" -P
+    "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+
+ADD_CUSTOM_TARGET(realclean
+		make clean
+    COMMAND ./realclean.sh
+    )
+
+# Make database and add examples script
+ADD_CUSTOM_COMMAND(
+    OUTPUT examplescript
+    COMMAND ${rsstorrent_SOURCE_DIR}/examples.sh
+    )
+
+ADD_CUSTOM_TARGET( examples DEPENDS examplescript)
+
+
diff --git a/tags/swarmtv-0.9.2/cmake_modules/CMakeMacroLibtoolFile.cmake b/tags/swarmtv-0.9.2/cmake_modules/CMakeMacroLibtoolFile.cmake
new file mode 100644
index 0000000..324f3ae
--- /dev/null
+++ b/tags/swarmtv-0.9.2/cmake_modules/CMakeMacroLibtoolFile.cmake
@@ -0,0 +1,49 @@
+MACRO(GET_TARGET_PROPERTY_WITH_DEFAULT _variable _target _property _default_value)
+ GET_TARGET_PROPERTY (${_variable} ${_target} ${_property})
+ IF (${_variable} MATCHES NOTFOUND)
+   SET (${_variable} ${_default_value})
+ ENDIF (${_variable} MATCHES NOTFOUND)
+ENDMACRO (GET_TARGET_PROPERTY_WITH_DEFAULT)
+
+MACRO(CREATE_LIBTOOL_FILE _target _install_DIR)
+ GET_TARGET_PROPERTY(_target_location ${_target} LOCATION)
+ GET_TARGET_PROPERTY_WITH_DEFAULT(_target_static_lib ${_target} STATIC_LIB "")
+ GET_TARGET_PROPERTY_WITH_DEFAULT(_target_dependency_libs ${_target} LT_DEPENDENCY_LIBS "")
+ GET_TARGET_PROPERTY_WITH_DEFAULT(_target_current ${_target} LT_VERSION_CURRENT 0)
+ GET_TARGET_PROPERTY_WITH_DEFAULT(_target_age ${_target} LT_VERSION_AGE 0)
+ GET_TARGET_PROPERTY_WITH_DEFAULT(_target_revision ${_target} LT_VERSION_REVISION 0)
+ GET_TARGET_PROPERTY_WITH_DEFAULT(_target_installed ${_target} LT_INSTALLED yes)
+ GET_TARGET_PROPERTY_WITH_DEFAULT(_target_shouldnotlink ${_target} LT_SHOULDNOTLINK yes)
+ GET_TARGET_PROPERTY_WITH_DEFAULT(_target_dlopen ${_target} LT_DLOPEN "")
+ GET_TARGET_PROPERTY_WITH_DEFAULT(_target_dlpreopen ${_target} LT_DLPREOPEN "")
+ GET_FILENAME_COMPONENT(_laname ${_target_location} NAME_WE)
+ GET_FILENAME_COMPONENT(_soname ${_target_location} NAME)
+ SET(_laname ${PROJECT_BINARY_DIR}/${_laname}.la)
+ FILE(WRITE ${_laname} "# ${_laname} - a libtool library file\n")
+ FILE(WRITE ${_laname} "# Generated by CMake ${CMAKE_VERSION} (like GNU libtool)\n")
+ FILE(WRITE ${_laname} "\n# Please DO NOT delete this file!\n# It is necessary for linking the library with libtool.\n\n" )
+ FILE(APPEND ${_laname} "# The name that we can dlopen(3).\n")
+ FILE(APPEND ${_laname} "dlname='${_soname}'\n\n")
+ FILE(APPEND ${_laname} "# Names of this library.\n")
+ FILE(APPEND ${_laname} "library_names='${_soname}.${_target_current}.${_target_age}.${_target_revision} ${_soname}.${_target_current} ${_soname}'\n\n")
+ FILE(APPEND ${_laname} "# The name of the static archive.\n")
+ FILE(APPEND ${_laname} "old_library='${_target_static_lib}'\n\n")
+ FILE(APPEND ${_laname} "# Libraries that this one depends upon.\n")
+ FILE(APPEND ${_laname} "dependency_libs='${_target_dependency_libs}'\n\n")
+ FILE(APPEND ${_laname} "# Names of additional weak libraries provided by this library\n")
+ FILE(APPEND ${_laname} "weak_library_names=\n\n")
+ FILE(APPEND ${_laname} "# Version information for ${_laname}.\n")
+ FILE(APPEND ${_laname} "current=${_target_current}\n")
+ FILE(APPEND ${_laname} "age=${_target_age}\n")
+ FILE(APPEND ${_laname} "revision=${_target_revision}\n\n")
+ FILE(APPEND ${_laname} "# Is this an already installed library?\n")
+ FILE(APPEND ${_laname} "installed=${_target_installed}\n\n")
+ FILE(APPEND ${_laname} "# Should we warn about portability when linking against -modules?\n")
+ FILE(APPEND ${_laname} "shouldnotlink=${_target_shouldnotlink}\n\n")
+ FILE(APPEND ${_laname} "# Files to dlopen/dlpreopen\n")
+ FILE(APPEND ${_laname} "dlopen='${_target_dlopen}'\n")
+ FILE(APPEND ${_laname} "dlpreopen='${_target_dlpreopen}'\n\n")
+ FILE(APPEND ${_laname} "# Directory that this library needs to be installed in:\n")
+ FILE(APPEND ${_laname} "libdir='${CMAKE_INSTALL_PREFIX}${_install_DIR}'\n")
+ INSTALL( FILES ${_laname} DESTINATION ${CMAKE_INSTALL_PREFIX}${_install_DIR})
+ENDMACRO(CREATE_LIBTOOL_FILE)
diff --git a/tags/swarmtv-0.9.2/cmake_modules/FindDBus.cmake b/tags/swarmtv-0.9.2/cmake_modules/FindDBus.cmake
new file mode 100644
index 0000000..f227cc2
--- /dev/null
+++ b/tags/swarmtv-0.9.2/cmake_modules/FindDBus.cmake
@@ -0,0 +1,72 @@
+# - Try to find the low-level D-Bus library
+# Once done this will define
+#
+#  DBUS_FOUND - system has D-Bus
+#  DBUS_INCLUDE_DIR - the D-Bus include directory
+#  DBUS_ARCH_INCLUDE_DIR - the D-Bus architecture-specific include directory
+#  DBUS_LIBRARIES - the libraries needed to use D-Bus
+
+# Copyright (c) 2008, Kevin Kofler, <kevin.kofler@chello.at>
+# modeled after FindLibArt.cmake:
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+if (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
+
+  # in cache already
+  SET(DBUS_FOUND TRUE)
+
+else (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
+
+  IF (NOT WIN32)
+    FIND_PACKAGE(PkgConfig)
+    IF (PKG_CONFIG_FOUND)
+      # use pkg-config to get the directories and then use these values
+      # in the FIND_PATH() and FIND_LIBRARY() calls
+      pkg_check_modules(_DBUS_PC QUIET dbus-1)
+    ENDIF (PKG_CONFIG_FOUND)
+  ENDIF (NOT WIN32)
+
+  FIND_PATH(DBUS_INCLUDE_DIR dbus/dbus.h
+    ${_DBUS_PC_INCLUDE_DIRS}
+    /usr/include
+    /usr/include/dbus-1.0
+    /usr/local/include
+  )
+
+  FIND_PATH(DBUS_ARCH_INCLUDE_DIR dbus/dbus-arch-deps.h
+    ${_DBUS_PC_INCLUDE_DIRS}
+    /usr/lib${LIB_SUFFIX}/include
+    /usr/lib${LIB_SUFFIX}/dbus-1.0/include
+    /usr/lib64/include
+    /usr/lib64/dbus-1.0/include
+    /usr/lib/include
+    /usr/lib/dbus-1.0/include
+  )
+
+  FIND_LIBRARY(DBUS_LIBRARIES NAMES dbus-1 dbus
+    PATHS
+     ${_DBUS_PC_LIBDIR}
+  )
+
+
+  if (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
+     set(DBUS_FOUND TRUE)
+  endif (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
+
+
+  if (DBUS_FOUND)
+     if (NOT DBus_FIND_QUIETLY)
+        message(STATUS "Found D-Bus: ${DBUS_LIBRARIES}")
+     endif (NOT DBus_FIND_QUIETLY)
+  else (DBUS_FOUND)
+     if (DBus_FIND_REQUIRED)
+        message(FATAL_ERROR "Could NOT find D-Bus")
+     endif (DBus_FIND_REQUIRED)
+  endif (DBUS_FOUND)
+
+  MARK_AS_ADVANCED(DBUS_INCLUDE_DIR DBUS_ARCH_INCLUDE_DIR DBUS_LIBRARIES)
+
+endif (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
diff --git a/tags/swarmtv-0.9.2/cmake_modules/FindDbusGlib.cmake b/tags/swarmtv-0.9.2/cmake_modules/FindDbusGlib.cmake
new file mode 100644
index 0000000..a516e48
--- /dev/null
+++ b/tags/swarmtv-0.9.2/cmake_modules/FindDbusGlib.cmake
@@ -0,0 +1,134 @@
+###################################################################
+#
+#  Copyright (c) 2006 Frederic Heem, <frederic.heem@telsey.it>
+#  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in
+#   the documentation and/or other materials provided with the
+#   distribution.
+#
+# * Neither the name of the Telsey nor the names of its
+#   contributors may be used to endorse or promote products derived
+#   from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+###################################################################
+# - Locate dbus-glib-1 include paths and libraries
+#  dbus-glib-1 can be found at http://www.freedesktop.org/wiki/Software/dbus
+#  Written by Frederic Heem, frederic.heem _at_ telsey.it
+
+# This module defines
+#  DBUSGLIB_FOUND, true if dbus-glib-1 has been found
+#  DBUSGLIB_VERSION, the dbus-glib-1 version
+#  DBUSGLIB_INCLUDE_DIRS, where to find dbus/dbus-glib.h, etc.
+#  DBUSGLIB_LIBRARIES, library to link againt libdbus-glib-1
+#  DBUSGLIB_DEFINITIONS, the definitions used to compile dbus-glib-1
+#  DBUSGLIB_BINDING_TOOL_EXECUTABLE the glib dbus binding tool
+
+#D-Bus is required by dbus-glib-1
+FIND_PACKAGE(DBus REQUIRED)
+
+#Keep space in case of $ENV{PKG_CONFIG_PATH} is empty
+SET(PKG_CONFIG_PATH " $ENV{PKG_CONFIG_PATH}")
+
+FIND_PACKAGE(PkgConfig)
+#Find the D-Bus package
+IF (NOT WIN32)
+PKGCONFIG_FOUND(dbus-glib-1 ${PKG_CONFIG_PATH} DBUSGLIB_FOUND)
+
+IF(DBUSGLIB_FOUND)
+  MESSAGE(STATUS " D-Bus glib found")
+ELSE(DBUSGLIB_FOUND)
+  MESSAGE(FATAL " D-Bus glib cannot be found")
+ENDIF(DBUSGLIB_FOUND)
+
+#Includes
+PKGCONFIG_INCLUDE_DIRS(dbus-glib-1 ${PKG_CONFIG_PATH} DBUSGLIB_INCLUDE_DIRS_PKGCONFIG)
+ENDIF (NOT WIN32)
+
+#TODO
+FIND_PATH(DBUSGLIB_INCLUDE_DIR dbus/dbus-glib.h
+  PATHS
+  ${DBUSGLIB_INCLUDE_DIRS_PKGCONFIG}
+  /usr/include/dbus-1.0
+  DOC
+  "Path to dbus glib include file dbus-glib.h"
+  NO_DEFAULT_PATH
+  )
+
+SET(DBUSGLIB_INCLUDE_DIRS ${DBUSGLIB_INCLUDE_DIR} ${DBUS_INCLUDE_DIRS})
+
+IF(DBUSGLIB_INCLUDE_DIR)
+  MESSAGE(STATUS "D-Bus glib include dir set to ${DBUSGLIB_INCLUDE_DIR}")
+ELSE(DBUSGLIB_INCLUDE_DIR)
+  MESSAGE(FATAL "D-Bus glib include dir cannot be found")
+ENDIF(DBUSGLIB_INCLUDE_DIR)
+
+IF (NOT WIN32)
+#Library
+PKGCONFIG_LIBRARY_DIR(dbus-glib-1 ${PKG_CONFIG_PATH}  DBUSGLIB_LIBRARY_DIR)
+ENDIF (NOT WIN32)
+
+SET(DBUSGLIB_LIB_PATH_DESCRIPTION "The directory containing the dbus glib library. E.g /home/fred/dbus-glib/lib or c:\\dbus-glib\\lib")
+
+FIND_LIBRARY(DBUSGLIB_LIBRARY
+  NAMES
+  dbus-glib-1
+  PATHS
+  ${DBUSGLIB_LIBRARY_DIR}
+  DOC
+  ${DBUSGLIB_LIB_PATH_DESCRIPTION}
+  #NO_DEFAULT_PATH TODO fix PKGCONFIG_LIBRARY_DIR when pkg-config returns multiple directories
+  )
+
+SET(DBUSGLIB_LIBRARIES ${DBUSGLIB_LIBRARY} ${DBUS_LIBRARIES})
+
+IF(DBUSGLIB_LIBRARIES)
+  MESSAGE(STATUS "D-Bus glib library set to  ${DBUSGLIB_LIBRARIES}")
+ELSE(DBUSGLIB_LIBRARIES)
+  MESSAGE(FATAL "D-Bus glib library cannot be found")
+ENDIF(DBUSGLIB_LIBRARIES)
+
+IF (NOT WIN32)
+#Version
+PKGCONFIG_VERSION(dbus-glib-1 ${PKG_CONFIG_PATH} DBUSGLIB_VERSION)
+MESSAGE(STATUS "D-Bus glib version is ${DBUSGLIB_VERSION}")
+
+#Definition
+PKGCONFIG_DEFINITION(dbus-glib-1 ${PKG_CONFIG_PATH} DBUSGLIB_DEFINITIONS)
+MESSAGE(STATUS "D-Bus glib definitions are ${DBUSGLIB_DEFINITIONS}")
+ENDIF (NOT WIN32)
+
+#binding tool
+FIND_PROGRAM(DBUSGLIB_BINDING_TOOL_EXECUTABLE
+  NAMES
+  dbus-binding-tool
+  /usr/local/bin
+  )
+
+MARK_AS_ADVANCED(
+  DBUSGLIB_INCLUDE_DIR
+  DBUSGLIB_LIBRARY
+  DBUSGLIB_BINDING_TOOL_EXECUTABLE
+  )
+
diff --git a/tags/swarmtv-0.9.2/cmake_modules/FindESMTP.cmake b/tags/swarmtv-0.9.2/cmake_modules/FindESMTP.cmake
new file mode 100644
index 0000000..50aa254
--- /dev/null
+++ b/tags/swarmtv-0.9.2/cmake_modules/FindESMTP.cmake
@@ -0,0 +1,29 @@
+# - Try to find the libesmtp library
+# Once done this will define
+#
+#  ESMTP_FOUND - system has the libesmtp library
+#  ESMTP_CONFIG
+#  ESMTP_INCLUDE_DIR - the libesmtp include directory
+#  ESMTP_LIBRARIES - The libraries needed to use libesmtp
+#
+# Based on FindPCRE.cmake
+# Distributed under the BSD license.
+
+if (ESMTP_INCLUDE_DIR AND ESMTP_LIBRARIES)
+	# Already in cache, be silent
+	set(ESMTP_FIND_QUIETLY TRUE)
+endif (ESMTP_INCLUDE_DIR AND ESMTP_LIBRARIES)
+
+FIND_PROGRAM(ESMTP_CONFIG libesmtp-config)
+
+IF (ESMTP_CONFIG)
+	FIND_PATH(ESMTP_INCLUDE_DIR libesmtp.h )
+	EXEC_PROGRAM(${ESMTP_CONFIG} ARGS --libs OUTPUT_VARIABLE _ESMTP_LIBRARIES)
+	string(REGEX REPLACE "[\r\n]" " " _ESMTP_LIBRARIES "${_ESMTP_LIBRARIES}")
+	set (ESMTP_LIBRARIES ${_ESMTP_LIBRARIES} CACHE STRING "The libraries needed for ESMTP")
+ENDIF (ESMTP_CONFIG)
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(ESMTP DEFAULT_MSG ESMTP_INCLUDE_DIR ESMTP_LIBRARIES )
+
+MARK_AS_ADVANCED(ESMTP_INCLUDE_DIR ESMTP_LIBRARIES)
diff --git a/tags/swarmtv-0.9.2/cmake_modules/FindGLIB2.cmake b/tags/swarmtv-0.9.2/cmake_modules/FindGLIB2.cmake
new file mode 100644
index 0000000..9fa16ea
--- /dev/null
+++ b/tags/swarmtv-0.9.2/cmake_modules/FindGLIB2.cmake
@@ -0,0 +1,387 @@
+# - Try to find GLib2
+# Once done this will define
+#
+#  GLIB2_FOUND - system has GLib2
+#  GLIB2_INCLUDE_DIRS - the GLib2 include directory
+#  GLIB2_LIBRARIES - Link these to use GLib2
+#  GLIB2_DEFINITIONS - Compiler switches required for using GLib2
+#  GLIB2_LINK_FLAGS - Link flags
+#
+#  Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
+#  Copyright (c) 2006 Philippe Bernery <philippe.bernery@gmail.com>
+#  Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
+#
+#  Redistribution and use is allowed according to the terms of the New
+#  BSD license.
+#  For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+
+if (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS AND GLIB2_PUBLIC_LINK_FLAGS)
+  # in cache already
+  set(GLIB2_FOUND TRUE)
+else (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS AND GLIB2_PUBLIC_LINK_FLAGS)
+  # use pkg-config to get the directories and then use these values
+  # in the FIND_PATH() and FIND_LIBRARY() calls
+  include(UsePkgConfig)
+
+  ## Glib
+  pkgconfig(glib-2.0 _GLIB2IncDir _GLIB2LinkDir _GLIB2LinkFlags _GLIB2Cflags)
+
+  # Prefer pkg-config results for custom builds found in PKG_CONFIG_PATH
+  find_path(GLIBCONFIG_INCLUDE_DIR
+    NAMES
+      glibconfig.h
+    PATHS
+      ${_GLIB2IncDir}
+    NO_DEFAULT_PATH
+  )
+
+  find_path(GLIBCONFIG_INCLUDE_DIR
+    NAMES
+      glibconfig.h
+    PATHS
+      /opt/gnome/lib64/glib-2.0/include
+      /opt/gnome/lib/glib-2.0/include
+      /opt/lib/glib-2.0/include
+      /opt/local/lib/glib-2.0/include
+      /sw/lib/glib-2.0/include
+      /usr/lib64/glib-2.0/include
+      /usr/lib/glib-2.0/include
+      /usr/lib/x86_64-linux-gnu/glib-2.0/include
+      /usr/lib/i386-linux-gnu/glib-2.0/include
+      /include
+  )
+
+  set(GLIB2_DEFINITIONS ${_GLIB2Cflags})
+
+  find_path(GLIB2_INCLUDE_DIR
+    NAMES
+      glib.h
+    PATHS
+      ${_GLIB2IncDir}
+    NO_DEFAULT_PATH
+  )
+
+  find_path(GLIB2_INCLUDE_DIR
+    NAMES
+      glib.h
+    PATHS
+      /opt/gnome/include/glib-2.0
+      /opt/local/include/glib-2.0
+      /sw/include/glib-2.0
+      /usr/include/glib-2.0
+      /usr/local/include/glib-2.0
+      /include/glib-2.0
+  )
+
+  find_library(GLIB2_LIBRARY
+    NAMES
+      glib-2.0
+    PATHS
+      ${_GLIB2LinkDir}
+    NO_DEFAULT_PATH
+  )
+
+  find_library(GLIB2_LIBRARY
+    NAMES
+      glib-2.0
+    PATHS
+      /opt/gnome/lib
+      /opt/local/lib
+      /sw/lib
+      /usr/lib
+      /usr/local/lib
+      /lib
+  )
+  ##
+
+  ## GModule
+  pkgconfig(gmodule-2.0 _GMODULE2IncDir _GMODULE2LinkDir _GMODULE2LinkFlags _GMODULE2Cflags)
+
+  set(GMODULE2_DEFINITIONS ${_GMODULE2Cflags})
+
+  # Prefer pkg-config results for custom builds found in PKG_CONFIG_PATH
+  find_path(GMODULE2_INCLUDE_DIR
+    NAMES
+      gmodule.h
+    PATHS
+      ${_GMODULE2IncDir}
+    NO_DEFAULT_PATH
+  )
+
+  find_path(GMODULE2_INCLUDE_DIR
+    NAMES
+      gmodule.h
+    PATHS
+      /opt/gnome/include/glib-2.0
+      /opt/local/include/glib-2.0
+      /sw/include/glib-2.0
+      /usr/include/glib-2.0
+      /usr/local/include/glib-2.0
+  )
+
+  find_library(GMODULE2_LIBRARY
+    NAMES
+      gmodule-2.0
+    PATHS
+      ${_GMODULE2LinkDir}
+    NO_DEFAULT_PATH
+  )
+
+  find_library(GMODULE2_LIBRARY
+    NAMES
+      gmodule-2.0
+    PATHS
+      /opt/gnome/lib
+      /opt/local/lib
+      /sw/lib
+      /usr/lib
+      /usr/local/lib
+      /lib
+  )
+  if (GMODULE2_LIBRARY AND GMODULE2_INCLUDE_DIR)
+    set(GMODULE2_FOUND TRUE)
+  endif (GMODULE2_LIBRARY AND GMODULE2_INCLUDE_DIR)
+  ##
+
+  ## GThread
+  pkgconfig(gthread-2.0 _GTHREAD2IncDir _GTHREAD2LinkDir _GTHREAD2LinkFlags _GTHREAD2Cflags)
+
+  set(GTHREAD2_DEFINITIONS ${_GTHREAD2Cflags})
+
+  # Prefer pkg-config results for custom builds found in PKG_CONFIG_PATH
+  find_path(GTHREAD2_INCLUDE_DIR
+    NAMES
+      gthread.h
+    PATHS
+      ${_GTHREAD2IncDir}
+    PATH_SUFFIXES
+      glib
+    NO_DEFAULT_PATH
+  )
+
+  find_path(GTHREAD2_INCLUDE_DIR
+    NAMES
+      gthread.h
+    PATHS
+      /opt/gnome/include/glib-2.0
+      /opt/local/include/glib-2.0
+      /sw/include/glib-2.0
+      /usr/include/glib-2.0
+      /usr/local/include/glib-2.0
+      /include/glib-2.0
+    PATH_SUFFIXES
+      glib
+  )
+
+  find_library(GTHREAD2_LIBRARY
+    NAMES
+      gthread-2.0
+    PATHS
+      ${_GTHREAD2LinkDir}
+    NO_DEFAULT_PATH
+  )
+
+  find_library(GTHREAD2_LIBRARY
+    NAMES
+      gthread-2.0
+    PATHS
+      /opt/gnome/lib
+      /opt/local/lib
+      /sw/lib
+      /usr/lib
+      /usr/local/lib
+      /lib
+  )
+
+  if (GTHREAD2_LIBRARY AND GTHREAD2_INCLUDE_DIR)
+    set(GTHREAD2_FOUND TRUE)
+  endif (GTHREAD2_LIBRARY AND GTHREAD2_INCLUDE_DIR)
+  ##
+
+  ## GObject
+  pkgconfig(gobject-2.0 _GOBJECT2IncDir _GOBJECT2LinkDir _GOBJECT2LinkFlags _GOBJECT2Cflags)
+
+  set(GOBJECT2_DEFINITIONS ${_GOBJECT2Cflags})
+
+  # Prefer pkg-config results for custom builds found in PKG_CONFIG_PATH
+  find_path(GOBJECT2_INCLUDE_DIR
+    NAMES
+      gobject.h
+    PATHS
+      ${_GOBJECT2IncDir}
+    PATH_SUFFIXES
+      gobject
+    NO_DEFAULT_PATH
+  )
+
+  find_path(GOBJECT2_INCLUDE_DIR
+    NAMES
+      gobject.h
+    PATHS
+      /opt/gnome/include/glib-2.0
+      /opt/local/include/glib-2.0
+      /sw/include/glib-2.0
+      /usr/include/glib-2.0
+      /usr/local/include/glib-2.0
+      /include/glib-2.0
+    PATH_SUFFIXES
+      gobject
+  )
+
+  find_library(GOBJECT2_LIBRARY
+    NAMES
+      gobject-2.0
+    PATHS
+      ${_GOBJECT2LinkDir}
+    NO_DEFAULT_PATH
+  )
+
+  find_library(GOBJECT2_LIBRARY
+    NAMES
+      gobject-2.0
+    PATHS
+      /opt/gnome/lib
+      /opt/local/lib
+      /sw/lib
+      /usr/lib
+      /usr/local/lib
+      /lib
+  )
+
+  if (GOBJECT2_LIBRARY AND GOBJECT2_INCLUDE_DIR)
+    set(GOBJECT2_FOUND TRUE)
+  endif (GOBJECT2_LIBRARY AND GOBJECT2_INCLUDE_DIR)
+  ##
+
+  ## libintl
+  find_path(LIBINTL_INCLUDE_DIR
+    NAMES
+      libintl.h
+    NO_DEFAULT_PATH
+    PATHS
+      /opt/gnome/include/glib-2.0
+      /opt/local/include/glib-2.0
+      /opt/local/include
+      /sw/include
+      /usr/include/glib-2.0
+      /usr/local/include/glib-2.0
+      /include/glib-2.0
+  )
+
+  find_library(LIBINTL_LIBRARY
+    NAMES
+      intl
+    NO_DEFAULT_PATH
+    PATHS
+      /opt/gnome/lib
+      /opt/local/lib
+      /sw/lib
+      /usr/local/lib
+      /usr/lib
+      /lib
+  )
+
+  if (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
+    set(LIBINTL_FOUND TRUE)
+  endif (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
+  ##
+
+  ## libiconv
+  find_path(LIBICONV_INCLUDE_DIR
+    NAMES
+      iconv.h
+    NO_DEFAULT_PATH
+    PATHS
+      /opt/gnome/include/glib-2.0
+      /opt/local/include/glib-2.0
+      /opt/local/include
+      /sw/include
+      /sw/include/glib-2.0
+      /usr/local/include/glib-2.0
+      /usr/include/glib-2.0
+      /include/glib-2.0
+  )
+
+  find_library(LIBICONV_LIBRARY
+    NAMES
+      iconv
+    NO_DEFAULT_PATH
+    PATHS
+      /opt/gnome/lib
+      /opt/local/lib
+      /sw/lib
+      /usr/lib
+      /lib
+      /usr/local/lib
+  )
+
+  if (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
+    set(LIBICONV_FOUND TRUE)
+  endif (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
+  ##
+
+  set(GLIB2_INCLUDE_DIRS
+    ${GLIB2_INCLUDE_DIR}
+    ${GLIBCONFIG_INCLUDE_DIR}
+  )
+  set(GLIB2_LIBRARIES
+    ${GLIB2_LIBRARY}
+  )
+
+  set(GLIB2_PUBLIC_LINK_FLAGS
+    ${_GLIB2LinkFlags} ${_GMODULE2LinkFlags} ${_GTHREAD2LinkFlags}
+  )
+
+  if (GMODULE2_FOUND)
+    set(GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${GMODULE2_LIBRARY})
+    set(GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${GMODULE2_INCLUDE_DIR})
+  endif (GMODULE2_FOUND)
+
+  if (GTHREAD2_FOUND)
+    set(GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${GTHREAD2_LIBRARY})
+    set(GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${GTHREAD2_INCLUDE_DIR})
+  endif (GTHREAD2_FOUND)
+
+  if (GOBJECT2_FOUND)
+    set(GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARY})
+    set(GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${GOBJECT2_INCLUDE_DIR})
+  endif (GOBJECT2_FOUND)
+
+  if (LIBINTL_FOUND)
+    set(GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBINTL_LIBRARY})
+    set(GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBINTL_INCLUDE_DIR})
+  endif (LIBINTL_FOUND)
+
+  if (LIBICONV_FOUND)
+    set(GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
+    set(GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
+  endif (LIBICONV_FOUND)
+
+  if (GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
+    set(GLIB2_FOUND TRUE)
+  endif (GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
+
+  if (GLIB2_FOUND)
+    if (NOT GLIB2_FIND_QUIETLY)
+      message(STATUS "Found GLib2: ${GLIB2_LIBRARIES}")
+    endif (NOT GLIB2_FIND_QUIETLY)
+  else (GLIB2_FOUND)
+    if (GLIB2_FIND_REQUIRED)
+      message(FATAL_ERROR "Could not find GLib2")
+    endif (GLIB2_FIND_REQUIRED)
+  endif (GLIB2_FOUND)
+
+  # show the GLIB2_INCLUDE_DIRS and GLIB2_LIBRARIES variables only in the advanced view
+  mark_as_advanced(GLIB2_INCLUDE_DIRS GLIB2_LIBRARIES GLIB2_PUBLIC_LINK_FLAGS)
+
+  # same for all other variables
+  mark_as_advanced(GLIB2_INCLUDE_DIR GLIB2_LIBRARY GLIBCONFIG_INCLUDE_DIR)
+  mark_as_advanced(GMODULE2_INCLUDE_DIR GMODULE2_LIBRARY)
+  mark_as_advanced(GOBJECT2_INCLUDE_DIR GOBJECT2_LIBRARY)
+  mark_as_advanced(GTHREAD2_INCLUDE_DIR GTHREAD2_LIBRARY)
+  mark_as_advanced(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARY)
+  mark_as_advanced(LIBINTL_INCLUDE_DIR LIBINTL_LIBRARY)
+
+endif (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS AND GLIB2_PUBLIC_LINK_FLAGS)
diff --git a/tags/swarmtv-0.9.2/cmake_modules/FindPCRE.cmake b/tags/swarmtv-0.9.2/cmake_modules/FindPCRE.cmake
new file mode 100644
index 0000000..cbe1ff4
--- /dev/null
+++ b/tags/swarmtv-0.9.2/cmake_modules/FindPCRE.cmake
@@ -0,0 +1,48 @@
+# - Try to find the PCRE regular expression library
+# Once done this will define
+#
+#  PCRE_FOUND - system has the PCRE library
+#  PCRE_INCLUDE_DIR - the PCRE include directory
+#  PCRE_LIBRARIES - The libraries needed to use PCRE
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+if (PCRE_INCLUDE_DIR AND PCRE_PCREPOSIX_LIBRARY AND PCRE_PCRE_LIBRARY)
+	# Already in cache, be silent
+	set(PCRE_FIND_QUIETLY TRUE)
+endif (PCRE_INCLUDE_DIR AND PCRE_PCREPOSIX_LIBRARY AND PCRE_PCRE_LIBRARY)
+
+
+if (NOT WIN32)
+	# use pkg-config to get the directories and then use these values
+	# in the FIND_PATH() and FIND_LIBRARY() calls
+	find_package(PkgConfig)
+
+	pkg_check_modules(PC_PCRE libpcre)
+
+	set(PCRE_DEFINITIONS ${PC_PCRE_CFLAGS_OTHER})
+
+endif (NOT WIN32)
+
+find_path(PCRE_INCLUDE_DIR pcre.h
+	HINTS ${PC_PCRE_INCLUDEDIR} ${PC_PCRE_INCLUDE_DIRS}
+	PATH_SUFFIXES pcre)
+
+find_library(PCRE_PCRE_LIBRARY NAMES pcre HINTS ${PC_PCRE_LIBDIR} ${PC_PCRE_LIBRARY_DIRS})
+
+find_library(PCRE_PCREPOSIX_LIBRARY NAMES pcreposix HINTS ${PC_PCRE_LIBDIR} ${PC_PCRE_LIBRARY_DIRS})
+
+include(FindPackageHandleStandardArgs)
+IF(NOT WIN32)
+	find_package_handle_standard_args(PCRE DEFAULT_MSG PCRE_INCLUDE_DIR PCRE_PCRE_LIBRARY PCRE_PCREPOSIX_LIBRARY )
+	mark_as_advanced(PCRE_INCLUDE_DIR PCRE_LIBRARIES PCRE_PCREPOSIX_LIBRARY PCRE_PCRE_LIBRARY)
+	set(PCRE_LIBRARIES ${PCRE_PCRE_LIBRARY} ${PCRE_PCREPOSIX_LIBRARY})
+ELSE()
+	find_package_handle_standard_args(PCRE DEFAULT_MSG PCRE_INCLUDE_DIR PCRE_PCRE_LIBRARY  )
+	set(PCRE_LIBRARIES ${PCRE_PCRE_LIBRARY} )
+	mark_as_advanced(PCRE_INCLUDE_DIR PCRE_LIBRARIES PCRE_PCRE_LIBRARY)
+ENDIF()
diff --git a/tags/swarmtv-0.9.2/cmake_modules/FindSqlite.cmake b/tags/swarmtv-0.9.2/cmake_modules/FindSqlite.cmake
new file mode 100644
index 0000000..757cbb4
--- /dev/null
+++ b/tags/swarmtv-0.9.2/cmake_modules/FindSqlite.cmake
@@ -0,0 +1,32 @@
+# - Try to find the sqlite library
+# Once done this will define
+#
+#  SQLITE_FOUND - system has sqlite
+#  SQLITE_INCLUDE_DIR - the sqlite include directory
+#  SQLITE_LIBRARIES - Link these to use sqlite
+#  SQLITE_DEFINITIONS - Compiler switches required for using sqlite
+#
+
+IF ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
+    SET( SQLITE_FIND_QUIETLY TRUE )
+ENDIF ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
+
+# Look for sqlite3 include dir and libraries
+FIND_PATH( SQLITE_INCLUDE_DIR sqlite3.h PATHS ${_LibSQLITEIncDir} )
+
+FIND_LIBRARY( SQLITE_LIBRARIES NAMES sqlite3 PATHS ${_LibSQLITELinkDir} )
+
+IF ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
+	SET( SQLITE_FOUND 1 )
+	IF ( NOT SQLITE_FIND_QUIETLY )
+		MESSAGE ( STATUS "Found sqlite3: ${SQLITE_LIBRARIES}" )
+	ENDIF ( NOT SQLITE_FIND_QUIETLY )
+ELSE ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
+	IF ( NOT SQLITE_FIND_QUIETLY )
+		MESSAGE ( STATUS "Could NOT find sqlite3." )
+	ENDIF ( NOT SQLITE_FIND_QUIETLY )
+ENDIF ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
+
+# Hide advanced variables from CMake GUIs
+MARK_AS_ADVANCED( SQLITE_INCLUDE_DIR SQLITE_LIBRARIES )
+
diff --git a/tags/swarmtv-0.9.2/cmake_modules/UsePkgConfig.cmake b/tags/swarmtv-0.9.2/cmake_modules/UsePkgConfig.cmake
new file mode 100644
index 0000000..d5412d1
--- /dev/null
+++ b/tags/swarmtv-0.9.2/cmake_modules/UsePkgConfig.cmake
@@ -0,0 +1,143 @@
+# - pkg-config module for CMake
+#
+# Defines the following macros:
+#
+#  PKGCONFIG_FOUND(package found)
+#  PKGCONFIG(package includedir libdir linkflags cflags)
+#  PKGCONFIG_VERSION(package version)
+#  PKGCONFIG_DEFINITION(package definition)
+
+# Calling PKGCONFIG_FOUND will fill into the argument the value of the package search's result
+# e.g. PKGCONFIG_FOUND(libart-2.0 LIBART_FOUND)
+#
+# Calling PKGCONFIG_VERSION will fill the desired version into the argument,
+# e.g. PKGCONFIG_VERSION(libart-2.0 LIBART_VERSION)
+# Calling PKGCONFIG will fill the desired information into the 4 given arguments,
+# e.g. PKGCONFIG(libart-2.0 LIBART_INCLUDE_DIR LIBART_LINK_DIR LIBART_LINK_FLAGS LIBART_CFLAGS)
+# if pkg-config was NOT found or the specified software package doesn't exist, the
+# variable will be empty when the function returns, otherwise they will contain the respective information
+#
+# Calling PKGCONFIG_VERSION will fill the desired version into the argument,
+# e.g. PKGCONFIG_VERSION(libart-2.0 LIBART_VERSION)
+#
+# Calling PKGCONFIG_DEFINITION will fill the definition (e.g -D_REENTRANT) into the argument,
+# e.g. PKGCONFIG_DEFINITION(libart-2.0 LIBART_DEFINITION)
+
+if (UNIX AND NOT WIN32)
+	FIND_PROGRAM(PKGCONFIG_EXECUTABLE NAMES pkg-config PATHS /bin )
+else (WIN32)
+	FIND_PROGRAM(PKGCONFIG_EXECUTABLE NAMES pkg-config.exe PATHS /bin )
+endif (UNIX AND NOT WIN32)
+
+
+MACRO(PKGCONFIG _package _include_DIR _link_DIR _link_FLAGS _cflags)
+# reset the variables at the beginning
+SET(${_include_DIR})
+SET(${_link_DIR})
+SET(${_link_FLAGS})
+SET(${_cflags})
+
+# if pkg-config has been found
+IF(PKGCONFIG_EXECUTABLE)
+
+EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_package} --exists RETURN_VALUE _return_VALUE OUTPUT_VARIABLE _pkgconfigDevNull )
+
+# and if the package of interest also exists for pkg-config, then get the information
+IF(NOT _return_VALUE)
+
+EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_package} --variable=includedir OUTPUT_VARIABLE ${_include_DIR} )
+
+EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_package} --variable=libdir OUTPUT_VARIABLE ${_link_DIR} )
+
+EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_package} --libs OUTPUT_VARIABLE ${_link_FLAGS} )
+
+EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_package} --cflags OUTPUT_VARIABLE ${_cflags} )
+
+ENDIF(NOT _return_VALUE)
+
+ENDIF(PKGCONFIG_EXECUTABLE)
+
+ENDMACRO(PKGCONFIG _include_DIR _link_DIR _link_FLAGS _cflags)
+
+
+
+MACRO(PKGCONFIG_FOUND _package _pkgpath _found)
+# reset the variable at the beginning
+SET(${_found})
+
+# if pkg-config has been found
+  IF(PKGCONFIG_EXECUTABLE)
+SET(ENV{PKG_CONFIG_PATH} ${_pkgpath})
+EXECUTE_PROCESS(COMMAND ${PKGCONFIG_EXECUTABLE} --print-errors --exists ${_package} RESULT_VARIABLE _return_VALUE OUTPUT_VARIABLE _pkgconfigDevNull )
+
+IF(${_pkgconfigDevNull})
+  MESSAGE(STATUS "${_pkgconfigDevNull}")
+ENDIF(${_pkgconfigDevNull})
+
+IF(NOT _return_VALUE)
+  SET(${_found} "TRUE")
+  ENDIF(NOT _return_VALUE)
+ENDIF(PKGCONFIG_EXECUTABLE)
+
+ENDMACRO(PKGCONFIG_FOUND _package _pkgpath _found)
+
+
+#TODO: doesn't work when pkgconfig returns multiples inlude path
+MACRO(PKGCONFIG_INCLUDE_DIRS _package _pkgpath _include_dirs)
+# reset the variable at the beginning
+SET(${_include_dirs})
+  IF(PKGCONFIG_EXECUTABLE)
+SET(ENV{PKG_CONFIG_PATH} ${_pkgpath})
+EXECUTE_PROCESS(COMMAND ${PKGCONFIG_EXECUTABLE} --cflags-only-I ${_package} OUTPUT_VARIABLE include)
+  STRING(REGEX REPLACE "-I/" "/" _include_dirs_temp ${include})
+  STRING(REGEX REPLACE "[\n\r]" "" ${_include_dirs} ${_include_dirs_temp})
+#When the include directory is /usr/include, pkgconfig returns a space and a new line
+  IF("${_include_dirs}" STREQUAL " ")
+  SET(${_include_dirs} "/usr/include")
+  ENDIF("${_include_dirs}" STREQUAL " ")
+  ENDIF(PKGCONFIG_EXECUTABLE)
+ENDMACRO(PKGCONFIG_INCLUDE_DIRS _package _pkgpath _include_dirs)
+
+MACRO(PKGCONFIG_LIBRARY_DIR _package _pkgpath _library_dir)
+# reset the variable at the beginning
+SET(${_library_dir})
+  IF(PKGCONFIG_EXECUTABLE)
+SET(ENV{PKG_CONFIG_PATH} ${_pkgpath})
+EXECUTE_PROCESS(COMMAND ${PKGCONFIG_EXECUTABLE} --libs-only-L ${_package} OUTPUT_VARIABLE libraries)
+  STRING(REGEX REPLACE "-L/" "/" _library_dirs_temp ${libraries})
+  MESSAGE(STATUS "lib dir ${_library_dirs_temp} end")
+  STRING(REGEX REPLACE "[\r\n]" "" ${_library_dir} ${_library_dirs_temp})
+#When the library directory is /usr/lib, pkgconfig returns an empty stringand a new line
+  IF("${_library_dir}" STREQUAL " ")
+  SET(${_library_dir} "/usr/lib")
+  ENDIF("${_library_dir}" STREQUAL " ")
+  MESSAGE(STATUS "lib dir ${${_library_dir}} end")
+  ENDIF(PKGCONFIG_EXECUTABLE)
+ENDMACRO(PKGCONFIG_LIBRARY_DIR _package _pkgpath _library_dir)
+
+MACRO(PKGCONFIG_VERSION _package _pkgpath _version)
+# reset the variable at the beginning
+SET(${_version})
+
+  IF(PKGCONFIG_EXECUTABLE)
+SET(ENV{PKG_CONFIG_PATH} ${_pkgpath})
+EXECUTE_PROCESS(COMMAND ${PKGCONFIG_EXECUTABLE} --modversion ${_package} OUTPUT_VARIABLE version)
+  STRING(REGEX REPLACE "[\n\r]" "" ${_version} ${version})
+ENDIF(PKGCONFIG_EXECUTABLE)
+
+ENDMACRO(PKGCONFIG_VERSION _package _pkgpath _version)
+
+MACRO(PKGCONFIG_DEFINITION _package _pkgpath _definition)
+# reset the variable at the beginning
+SET(${_definition})
+
+  IF(PKGCONFIG_EXECUTABLE)
+SET(ENV{PKG_CONFIG_PATH} ${_pkgpath})
+EXECUTE_PROCESS(COMMAND ${PKGCONFIG_EXECUTABLE} --cflags-only-other ${_package} OUTPUT_VARIABLE definition)
+  STRING(REGEX REPLACE "[\n\r]" "" ${_definition} ${definition})
+ENDIF(PKGCONFIG_EXECUTABLE)
+
+ENDMACRO(PKGCONFIG_DEFINITION _package _pkgpath _definition)
+
+MARK_AS_ADVANCED(PKGCONFIG_EXECUTABLE)
+
diff --git a/tags/swarmtv-0.9.2/cmake_uninstall.cmake.in b/tags/swarmtv-0.9.2/cmake_uninstall.cmake.in
new file mode 100644
index 0000000..28097cf
--- /dev/null
+++ b/tags/swarmtv-0.9.2/cmake_uninstall.cmake.in
@@ -0,0 +1,22 @@
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+  STRING(REGEX REPLACE "\n" ";" files "${files}")
+FOREACH(file ${files})
+  MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+  IF(EXISTS "$ENV{DESTDIR}${file}")
+  EXEC_PROGRAM(
+      "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+      OUTPUT_VARIABLE rm_out
+      RETURN_VALUE rm_retval
+      )
+  IF(NOT "${rm_retval}" STREQUAL 0)
+  MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+  ENDIF(NOT "${rm_retval}" STREQUAL 0)
+  ELSE(EXISTS "$ENV{DESTDIR}${file}")
+  MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+  ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ENDFOREACH(file)
+
diff --git a/tags/swarmtv-0.9.2/examples.bat b/tags/swarmtv-0.9.2/examples.bat
new file mode 100644
index 0000000..81c13f0
--- /dev/null
+++ b/tags/swarmtv-0.9.2/examples.bat
@@ -0,0 +1,36 @@
+@ECHO OFF
+
+REM This script inserts example sources and filters into the database.
+
+REM NB: I don't do windows batch scripting . .
+
+IF NOT EXIST swarmtv.exe ECHO "Please install SwarmTv before running this script."
+IF NOT EXIST swarmtv.exe PAUSE
+IF NOT EXIST swarmtv.exe EXIT
+
+FOR /F "tokens=3 delims=	" %%G IN ('REG QUERY "HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Common Documents"') DO (SET docsdir=%%G)
+
+mkdir "%docsdir%\torrents"
+mkdir "%docsdir%\nzb"
+
+echo "Delete all SQL and simple filters."
+  swarmtv.exe --del-all-simple
+  swarmtv.exe --del-filter all
+echo "Done."
+
+echo "Inserting sources."
+  swarmtv.exe --add-source="Eztv" --url="http://www.ezrss.it/feed/" --source-parser="defaultrss" --metatype="torrent"
+  swarmtv.exe --add-source="The Piratebay" --url="http://rss.thepiratebay.org/205" --source-parser="defaultrss" --metatype="torrent"
+  swarmtv.exe --add-source="KickAssTorrents" --url="http://www.kickasstorrents.com/tv/?rss=1" --source-parser="defaultrss" --metatype="torrent"
+echo "Done."
+
+echo "Insert Simple filters."
+  swarmtv.exe --add-simple="House" --nodup="newer" --title="^house" --exclude="hunters international" --max-size="700.00 MB" --min-size="200.00 MB"
+  swarmtv.exe --add-simple="Lost" --nodup="newer" --title="^lost" --max-size="700.00 MB" --min-size="200.00 MB"
+  swarmtv.exe --add-simple="BBC" --nodup="link" --title="^bbc" --exclude="QI" --max-size="1024.00 MB" --min-size="100.00 MB"
+  swarmtv.exe --add-simple="Top Gear" --nodup="newer" --title="^top gear" --max-size="1024.00 MB" --min-size="100.00 MB"
+  swarmtv.exe --add-simple="Breaking Bad" --nodup="newer" --title="^breaking bad" --max-size="700.00 MB" --min-size="100.00 MB"
+  swarmtv.exe --add-simple="Dirty jobs" --nodup="newer" --title="^dirty jobs" --max-size="700.00 MB" --min-size="100.00 MB"
+  swarmtv.exe --add-simple="Dollhouse" --nodup="newer" --title="^dollhouse" --max-size="600.00 MB" --min-size="100.00 MB"
+  swarmtv.exe --add-simple="Computer Chronicles" --nodup="link" --title="Computer Chronicles" --max-size="800.00 MB"
+echo "Done."
diff --git a/tags/swarmtv-0.9.2/examples.sh b/tags/swarmtv-0.9.2/examples.sh
new file mode 100755
index 0000000..ce5b745
--- /dev/null
+++ b/tags/swarmtv-0.9.2/examples.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+#
+# This script inserts example sources and filters into the database.
+#
+
+# Check if RSS-torrent is built
+if [ ! -e `which swarmtv` ]; then
+  echo "Please install SwarmTv before running this script."
+  exit
+fi
+
+# Cleaning database
+echo "Delete all SQL and simple filters."
+  swarmtv --del-all-simple
+  swarmtv --del-filter all
+echo "Done."
+
+# INSERT INTO "sources" (name, url, filter) VALUES( "swarmtvs", "http://rsstorrents.com/rss.php?cat=8", "rsstorrent");
+echo "Inserting sources."
+  swarmtv --add-source="Eztv" --url="http://www.ezrss.it/feed/" --source-parser="defaultrss" --metatype="torrent"
+  swarmtv --add-source="The Piratebay" --url="http://rss.thepiratebay.org/205" --source-parser="defaultrss" --metatype="torrent"
+  swarmtv --add-source="KickAssTorrents" --url="http://www.kickasstorrents.com/tv/?rss=1" --source-parser="defaultrss" --metatype="torrent"
+echo "Done."
+
+# Although SQL filters are still supported they are not the default filter method anymore.
+# Plus 99% of the filters can be written using simple filters now.
+#echo "Insert SQL filters."
+#./swarmtv -F "DollHouse:select id, link, title, pubdate, category, season, episode from newtorrents where title REGEXP('^[Dd]ollhouse') AND size < '400000000' AND new = 'Y'" \
+#  -T "SELECT title FROM downloaded WHERE link=?1 OR (season>=?2 AND episode>=?3 AND title REGEXP('^[Dd]ollhouse'))"
+#./swarmtv -F "House:select id, link, title, pubdate, category, season, episode from newtorrents where title REGEXP('^[hH]ouse') AND size < '400000000' AND new = 'Y'" \
+#  -T "SELECT title FROM downloaded WHERE link=?1 OR (season>=?2 AND episode>=?3 AND title REGEXP('^[hH]ouse'))"
+#./swarmtv -F "Stargate Universe:select id, link, title, pubdate, category, season, episode from newtorrents where title REGEXP('^[sS]targate [Uu]niverse') AND size < '800000000' AND new = 'Y'" \
+#  -T "SELECT title FROM downloaded WHERE link=?1 OR (season>=?2 AND episode>=?3 AND title REGEXP('^[sS]targate [Uu]niverse'))"
+#./swarmtv -F "BBC:select id, link, title, pubdate, category, season, episode from newtorrents where title REGEXP('^BBC') AND size < '800000000' AND new = 'Y'" \
+#  -T "SELECT title FROM downloaded WHERE link=?1"
+#./swarmtv -F "Mythbusters:select id, link, title, pubdate, category, season, episode from newtorrents where title REGEXP('^[Mm]ythbusters') AND size < '800000000' AND new = 'Y'" \
+#  -T "SELECT title FROM downloaded WHERE link=?1 OR (season>=?2 AND episode>=?3 AND title REGEXP('^[mM]ythbusters'))"
+#./swarmtv -F "Dirty Jobs:select id, link, title, pubdate, category, season, episode from newtorrents where title REGEXP('^[dD]irty [jJ]obs') AND size < '400000000' AND new = 'Y'" \
+#  -T "SELECT title FROM downloaded WHERE link=?1 OR (season>=?2 AND episode>=?3 AND title REGEXP('^[dD]irty [jJ]obs'))"
+#./swarmtv -F "Lost:select id, link, title, pubdate, category, season, episode from newtorrents where title REGEXP('^[Ll]ost') AND size < '400000000' AND new = 'Y'" \
+#  -T "SELECT title FROM downloaded WHERE link=?1 OR (season>=?2 AND episode>=?3 AND title REGEXP('^[Ll]ost'))"
+#echo "Done."
+
+
+echo "Insert Simple filters."
+  swarmtv --add-simple='House' --nodup='newer' --title='^house' --exclude='hunters international' --max-size='700.00 MB' --min-size='200.00 MB'
+  swarmtv --add-simple='Lost' --nodup='newer' --title='^lost' --max-size='700.00 MB' --min-size='200.00 MB'
+  swarmtv --add-simple='BBC' --nodup='link' --title='^bbc' --exclude='QI' --max-size='1024.00 MB' --min-size='100.00 MB'
+  swarmtv --add-simple='Top Gear' --nodup='newer' --title='^top gear' --max-size='1024.00 MB' --min-size='100.00 MB'
+  swarmtv --add-simple='Breaking Bad' --nodup='newer' --title='^breaking bad' --max-size='700.00 MB' --min-size='100.00 MB'
+  swarmtv --add-simple='Dirty jobs' --nodup='newer' --title='^dirty jobs' --max-size='700.00 MB' --min-size='100.00 MB'
+  swarmtv --add-simple='Dollhouse' --nodup='newer' --title='^dollhouse' --max-size='600.00 MB' --min-size='100.00 MB'
+  swarmtv --add-simple='Computer Chronicles' --nodup='link' --title='Computer Chronicles' --max-size='800.00 MB'
+echo "Done."
diff --git a/tags/swarmtv-0.9.2/libswarmtv/CMakeLists.txt b/tags/swarmtv-0.9.2/libswarmtv/CMakeLists.txt
new file mode 100644
index 0000000..62f597d
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/CMakeLists.txt
@@ -0,0 +1,98 @@
+# The name of our project is "HELLO". CMakeLists files in this project can
+# refer to the root source directory of the project as ${HELLO_SOURCE_DIR} and
+# to the root binary directory of the project as ${HELLO_BINARY_DIR}.
+cmake_minimum_required(VERSION 2.6)
+project (swarmtv C)
+
+# Use the detected libraries to set build variables.
+SET(optionalLibs)
+IF(LIBXML2_FOUND)
+	INCLUDE_DIRECTORIES( ${LIBXML2_INCLUDE_DIR} )
+	SET(optionalLibs ${optionalLibs} ${LIBXML2_LIBRARIES} )
+ENDIF(LIBXML2_FOUND)
+
+IF(SQLITE_FOUND)
+	INCLUDE_DIRECTORIES( ${SQLITE_INCLUDE_DIR} )
+	SET(optionalLibs ${optionalLibs} ${SQLITE_LIBRARIES} )
+ENDIF(SQLITE_FOUND)
+
+IF(PCRE_FOUND)
+	INCLUDE_DIRECTORIES( ${PCRE_INCLUDE_DIR} )
+	SET(optionalLibs ${optionalLibs} ${PCRE_LIBRARIES} )
+ENDIF(PCRE_FOUND)
+
+IF(CURL_FOUND)
+	INCLUDE_DIRECTORIES( ${CURL_INCLUDE_DIR} )
+	SET(optionalLibs ${optionalLibs} ${CURL_LIBRARIES} )
+ENDIF(CURL_FOUND)
+
+IF(ESMTP_FOUND)
+	INCLUDE_DIRECTORIES( ${ESMTP_INCLUDE_DIR} )
+	SET(optionalLibs ${optionalLibs} ${ESMTP_LIBRARIES} )
+ENDIF(ESMTP_FOUND)
+
+# Compiler directives
+if (UNIX AND NOT WIN32)
+	add_definitions(-Wall -W -fPIC)
+else (WIN32)
+	add_definitions(-Wall -W -DPIC -DDLL_EXPORT)
+endif (UNIX AND NOT WIN32)
+IF(DEBUG_ENABLE)
+  add_definitions(-g)
+ENDIF()
+include_directories(.)
+
+# All other sources
+# getmissed callbackimpl
+if (UNIX AND NOT WIN32)
+SET(LIBSRC setup database databaseimpl config regexp source
+		filter runloop curlfile torrentdb torrentdownload logfile
+		sandboxdb testfilter filesystem lastdownloaded
+		simplefilter callback stats baretitle)
+else (WIN32)
+SET(LIBSRC setup database databaseimpl config regexp source workarounds
+		filter runloop curlfile torrentdb torrentdownload logfile
+		sandboxdb testfilter filesystem lastdownloaded
+		simplefilter callback stats baretitle)
+endif (UNIX AND NOT WIN32)
+
+# Subdirectories
+INCLUDE(srcparser/CMakeLists.txt)
+INCLUDE(filehandler/CMakeLists.txt)
+
+# Add static library
+add_library (swarmtv-static ${LIBSRC})
+TARGET_LINK_LIBRARIES(swarmtv-static ${optionalLibs} )
+
+# Add library
+add_library (swarmtv SHARED ${LIBSRC})
+TARGET_LINK_LIBRARIES(swarmtv ${optionalLibs} )
+
+# Set the build version (VERSION) and the API version (SOVERSION)
+SET_TARGET_PROPERTIES(swarmtv
+		PROPERTIES
+		VERSION 1.0.0
+		SOVERSION 1)
+
+# Generating pkg-config file
+# create .pc file <install base path> <template path> <destination path>
+EXEC_PROGRAM( ${CMAKE_CURRENT_SOURCE_DIR}/createpc.sh ARGS ${CMAKE_INSTALL_PREFIX} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR})
+
+# Create libtool .la file
+CREATE_LIBTOOL_FILE(swarmtv /lib)
+
+# Installation of the library
+INSTALL(TARGETS swarmtv
+		DESTINATION lib
+		PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
+
+INSTALL(TARGETS swarmtv-static
+		DESTINATION lib
+		PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
+
+INSTALL(FILES swarmtv.h
+		DESTINATION include
+		PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
+
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/libswarmtv.pc DESTINATION lib/pkgconfig/ )
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/libswarmtv.pc DESTINATION share/pkgconfig/ )
diff --git a/tags/swarmtv-0.9.2/libswarmtv/baretitle.c b/tags/swarmtv-0.9.2/libswarmtv/baretitle.c
new file mode 100644
index 0000000..87cde3a
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/baretitle.c
@@ -0,0 +1,187 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009 - 2010
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pcre.h>
+#include <sqlite3.h>
+#include <time.h>
+
+#include "types.h"
+#include "regexp.h"
+#include "logfile.h"
+
+
+/*
+ * This function removes all charakters from string NOT being
+ * a-z, A-Z or 0-9
+ * This in order to keep the regexps created from this title sane.
+ * This function alters the input-string !
+ * @arguments
+ * baretitle title to clean up
+ */
+static void rsstcleantitle(char *baretitle, char **strippedtitle)
+{
+  char *current=NULL;
+  char *curwrite=NULL;
+  char *stripped=NULL;
+
+  /*
+   * Allocate the stripped title
+   * +1 to have an extra /0 at the end of the string at all times.
+   */
+  stripped = calloc(1, strlen(baretitle)+1);
+
+  /*
+   * Loop all the characters
+   */
+  curwrite=stripped;
+  current=baretitle;
+  while(*current != '\0'){
+
+    /*
+     * When not in range of valid characters, replace with a ' '
+     */
+    if((*current >= 'a' && *current <= 'z') ||
+        (*current >= 'A' && *current <= 'Z') ||
+        (*current >= '0' && *current <= '9') ||
+        (*current == ' '))
+    {
+      *curwrite=*current;
+      curwrite++;
+    }
+
+    current++;
+  }
+
+  *strippedtitle = stripped;
+}
+
+/*
+ * Isolate the title from the title captured from the RSS-title
+ * @Arguments
+ * downed      Title provided by the RSS feed
+ * @Return
+ * 0 on success otherwise -1
+ */
+int rsstfillbaretitle(downloaded_struct *downed)
+{
+  int   rc=0;
+  int   retval=0;
+  char *title=NULL;
+  char *baretitle=NULL;
+  char *strippedtitle=NULL;
+
+  /*
+   * Regexp to strip bare title from title.
+   */
+  char *bareregexp="([^0-9]*?)[ ]?[sS]?[0-9]";
+
+  /*
+   * initialize local pointer
+   */
+  title=downed->title;
+
+  /*
+   * Get the bare title
+   */
+  rc = rsstcapturefirstmatch(bareregexp, 0, title, &baretitle);
+  if(rc == PCRE_ERROR_NOMATCH){
+    /*
+     * When the regexp failed to match take the whole title.
+     */
+    rsstalloccopy(&baretitle, title, strlen(title));
+  }
+  else if(rc < 0){
+    /*
+     * Problems with regexp.
+     */
+    rsstwritelog(LOG_ERROR, "Regep failed in baretitle %s:%d", __FILE__, __LINE__);
+    retval = -1;
+  }
+
+  /*
+   * Strip all none letter chars from string
+   */
+  rsstcleantitle(baretitle, &strippedtitle);
+  free(baretitle);
+
+  //printf("title:      '%s'\n", title);
+  //printf("baretitle:  '%s'\n", baretitle);
+
+  /*
+   * write back bare title.
+   */
+  downed->baretitle=strippedtitle;
+
+  /*
+   * return outcome.
+   */
+  return retval;
+}
+
+
+/*
+ * Transform the bare title to a regexp matching the bare title
+ * @Arguments
+ * baretitle Title to transform
+ * bareregexp regexp to return
+ */
+void rsstmakebareregexp(char *baretitle, char **bareregexp)
+{
+  int regsize=0;
+
+  /*
+   * Check sanity
+   */
+  if(baretitle == 0) {
+    rsstwritelog(LOG_ERROR, "NULL pointer passed to rsstmakebareregexp function. %s:%d", __FILE__, __LINE__);
+    return;
+  }
+
+  /*
+   * Front and back additions
+   */
+  char *frontreg  = "^";
+  char *endreg    = "";
+
+  /*
+   * Calculate size of the regexp
+   */
+  regsize = strlen(frontreg);
+  regsize += strlen(endreg);
+  regsize += strlen(baretitle);
+  regsize++;
+
+  /*
+   * Allocate memory and print the regexp there
+   */
+  *bareregexp = calloc(1, regsize);
+  snprintf(*bareregexp, regsize, "%s%s%s", frontreg, baretitle, endreg);
+
+  /*
+   * @@DEBUG
+   */
+  //printf("bareregexp: '%s'\n", *bareregexp);
+
+  /*
+   * Done
+   */
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/baretitle.h b/tags/swarmtv-0.9.2/libswarmtv/baretitle.h
new file mode 100644
index 0000000..932a0de
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/baretitle.h
@@ -0,0 +1,37 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009 - 2010
+ */
+
+/*
+ * Isolate the title from the title captured from the RSS-title
+ * @Arguments
+ * downed      Title provided by the RSS feed
+ * @Return
+ * 0 on success otherwise -1
+ */
+int rsstfillbaretitle(downloaded_struct *downed);
+
+/*
+ * Transform the bare title to a regexp matching the bare title
+ * @Arguments
+ * baretitle Title to transform
+ * bareregexp regexp to return
+ */
+void rsstmakebareregexp(char *baretitle, char **bareregexp);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/callback.c b/tags/swarmtv-0.9.2/libswarmtv/callback.c
new file mode 100644
index 0000000..385504e
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/callback.c
@@ -0,0 +1,209 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2010
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "swarmtv.h"
+#include "callback.h"
+
+/*
+ * Initialize the struct_callback.
+ * @Arguments
+ * callstruct pointer to structure to initialize
+ * @return
+ * 0 on success, -1 when initialisation fails
+ */
+int rsstinitcallback(struct_callback **callstruct)
+{
+	/*
+	 * Allocate structure
+	 */
+	*callstruct = calloc(1, sizeof(struct_callback));
+	if(*callstruct == NULL) {
+		fprintf(stderr, "Allocation failed of callback structure failed. %s:%d\n", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Done
+	 */
+	return 0;
+}
+
+/*
+ * Free the callback structure
+ * @Arguments
+ * callstruct callback structure to free
+ */
+void rsstfreecallback(struct_callback *callstruct)
+{
+	/*
+	 * Free should allow passing NULL pointer to it
+	 */
+	if(callstruct == NULL) {
+		return;
+	}
+
+	/*
+	 * free array of function pointers
+	 */
+	free(callstruct->callback);
+	free(callstruct->data);
+
+	/*
+	 * Free callback structure itself
+	 */
+	free(callstruct);
+}
+
+/*
+ * Add pointer.
+ * @arguments
+ * handle swarmtv handle
+ * enumcall the name of the callback funct
+ * callback pointer to the callback function
+ * data   pointer that will be returned as the data pointer.
+ * @return
+ * 0 on successful addition, -1 on error
+ */
+int rsstaddcallback(rsstor_handle *handle, enum_callbacks callenum, rsstcallbackfnct callback, void *data)
+{
+	int                newcount=0;
+  struct_callbacks   *callbacks=NULL;
+  struct_callback   **callcol=NULL;
+  struct_callback   *callstruct=NULL;
+
+  /*
+   * Get pointer
+   */
+  callbacks = &(handle->callback);
+  callcol = (struct_callback**) callbacks;
+  callstruct = callcol[callenum];
+
+	/*
+	 * Set new count
+	 */
+	newcount = callstruct->nr + 1;
+
+	/*
+	 * Reallocate the array to store the function pointer
+	 */
+	callstruct->callback = realloc(callstruct->callback, sizeof(rsstcallbackfnct) * newcount);
+	if(callstruct->callback == NULL) {
+		fprintf(stderr, "Allocation of callback pointer array failed! %s:%d\n", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Reallocate the array to store the data pointer
+	 */
+	callstruct->data = realloc(callstruct->data, sizeof(void*) * newcount);
+	if(callstruct->callback == NULL) {
+		fprintf(stderr, "Allocation of callback pointer array failed! %s:%d\n", __FILE__, __LINE__);
+		return -1;
+	}
+
+
+	/*
+	 * Add the new pointers
+	 */
+	callstruct->callback[newcount-1] = *callback;
+	callstruct->data[newcount-1] = data;
+
+	/*
+	 * Add one to the pointer number
+	 */
+	callstruct->nr = newcount;
+
+	/*
+	 * All is done
+	 */
+	return 0;
+}
+
+
+/*
+ * Call callbacks.
+ * @arguments
+ * callstruct	Structure of callbacks to execute one by one
+ * data				Structure containing callback data (should be casted to proper structure)
+ * @return
+ * 0 on success, !0 when on of the called functions did not return 0
+ */
+int rsstexecallstruct(struct_callback *callstruct, void *calldata)
+{
+	int count=0;
+	int retval=0;
+
+	/*
+	 * Walk past all pointers, and call the function pointers
+	 */
+	for(count=0; count < callstruct->nr; count++)
+	{
+		/*
+		 * Or the return value, when one is !0 the return value != 0
+		 */
+		retval |= callstruct->callback[count](callstruct->data[count], calldata);
+	}
+
+	/*
+	 * Return the results.
+	 */
+	return retval;
+}
+
+
+/*
+ * execute routines that are handling on RSS download events
+ * @Arguments
+ * handle     Handle to RSS-torrent pointer
+ * callenum   Name name of the callback to call
+ * load       payload to provide together with the callback
+ * @return
+ * return 0 when all called functions returned 0, otherwise != 0
+ */
+int rsstexecallbacks(rsstor_handle *handle, enum_callbacks callenum, void *load)
+{
+  int rc=0;
+  struct_callbacks *callbacks=NULL;
+  struct_callback **callcol=NULL;
+  struct_callback  *callstruct=NULL;
+
+  /*
+   * Get callback structure pointer.
+   */
+  callbacks = &(handle->callback);
+  callcol = (struct_callback**) callbacks;
+  callstruct = callcol[callenum];
+
+  /*
+   * call the callbacks.
+   */
+  rc = rsstexecallstruct(callstruct, load);
+
+  /*
+   * Return the execute value
+   */
+  return rc;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/callback.h b/tags/swarmtv-0.9.2/libswarmtv/callback.h
new file mode 100644
index 0000000..b27bcfa
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/callback.h
@@ -0,0 +1,62 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2010
+ */
+
+
+/*
+ * Initialize the struct_callback.
+ * @Arguments
+ * callstruct pointer to structure to initialize
+ * @return
+ * 0 on success, -1 when initialisation fails
+ */
+int rsstinitcallback(struct_callback **callstruct);
+
+/*
+ * Free the callback structure
+ * @Arguments
+ * callstruct callback structure to free
+ */
+void rsstfreecallback(struct_callback *callstruct);
+
+
+/*
+ * Add pointer.
+ * @arguments
+ * handle swarmtv handle
+ * enumcall the name of the callback funct
+ * callback pointer to the callback function
+ * data   pointer that will be returned as the data pointer.
+ * @return
+ * 0 on successful addition, -1 on error
+ */
+int rsstaddcallback(rsstor_handle *handle, enum_callbacks enumcall, rsstcallbackfnct callback, void *data);
+
+
+/*
+ * execute routines that are handling on RSS download events
+ * @Arguments
+ * handle     Handle to RSS-torrent pointer
+ * callenum   Name name of the callback to call
+ * load       payload to provide together with the callback
+ * @return
+ * return 0 when all called functions returned 0, otherwise != 0
+ */
+int rsstexecallbacks(rsstor_handle *handle, enum_callbacks callenum, void *load);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/config.c b/tags/swarmtv-0.9.2/libswarmtv/config.c
new file mode 100644
index 0000000..27bd912
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/config.c
@@ -0,0 +1,212 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pcre.h>
+#include <sqlite3.h>
+#include <time.h>
+
+#include "types.h"
+#include "database.h"
+#include "logfile.h"
+
+#define  MAXLENGHT 400
+
+/*
+ * Get value of a config object.
+ * Make sure the free the value returned in the value pointer.
+ * arguments
+ * prop name of config property to retrieve
+ * value pointer to the pointer that is going to hold the retrieved value.
+ * returns
+ * 0 when the value was found, otherwise -1.
+ */
+int rsstconfiggetproperty(rsstor_handle *handle, char *prop, char **value)
+{
+  char  *query;
+  int   rc=0;
+	sqlite3 *db=NULL;
+
+	/*
+	 * get db pointer
+	 */
+	db = handle->db;
+
+  query="select value from config where prop = ?1";
+
+  rc =  rsstdosingletextquery(db, (unsigned char const**) value, query, "s", prop);
+  if(rc == 0){
+    return 0;
+  }
+  rsstwritelog(LOG_ERROR, "Config value '%s' not found!", prop);
+
+  return -1;
+}
+
+
+/*
+ * Get value of a config object.
+ * Arguments
+ * prop 	name of the property
+ * number the pointer the property value will be put in.
+ * return 0 when prop is found, -1 when not found.
+ */
+int rsstconfiggetint(rsstor_handle *handle, char *prop, int *number)
+{
+  char *value;
+  int rc=0;
+
+  rc = rsstconfiggetproperty(handle, prop,(char**) &value);
+  if(rc == 0){
+    *number = atoi(value);
+    free(value);
+    return 0;
+  }
+  rsstwritelog(LOG_ERROR, "Config value '%s' not found!", prop);
+
+  return -1;
+}
+
+
+/*
+ * Get value of a config object.
+ * Arguments
+ * prop 	name of the property
+ * number the pointer the property value will be put in.
+ * return
+ * 0 when prop is found, -1 when not found.
+ */
+int rsstconfiggetlong(rsstor_handle *handle, char *prop, long *number)
+{
+  char *value;
+  int rc=0;
+
+  rc = rsstconfiggetproperty(handle, prop,(char**) &value);
+  if(rc == 0){
+    *number = atol(value);
+    free(value);
+    return 0;
+  }
+  rsstwritelog(LOG_ERROR, "Config value '%s' not found!", prop);
+
+  return -1;
+}
+
+/*
+ * Set config item
+ * Arguments
+ * prop		property to set
+ * value	Value to set
+ * returns
+ * When not found -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstsetconfigitem(rsstor_handle *handle, const char *prop, const char *value)
+{
+  sqlite3_stmt  *ppStmt=NULL;
+  const char    *pzTail=NULL;
+  int           rc=0;
+  char          *zErrMsg=NULL;
+	sqlite3       *db=NULL;
+
+	/*
+	 * Get database handle.
+	 */
+	db = handle->db;
+
+  /*
+   * Init query
+   */
+  const char* query = "update config set value=?1 where config.prop=?2";
+
+  /*
+   * Prepare the Sqlite statement
+   */
+  rc = rsst_sqlite3_prepare(
+      db,                 /* Database handle */
+      query,            /* SQL statement, UTF-8 encoded */
+      strlen(query),    /* Maximum length of SQL query in bytes. */
+      &ppStmt,             /* OUT: Statement handle */
+      &pzTail              /* OUT: Pointer to unused portion of Sql */
+      );
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return -1;
+  }
+
+  /*
+   * bind property and value to the query
+   *
+   */
+  rc = sqlite3_bind_text(ppStmt, 1, value, -1, SQLITE_TRANSIENT);
+  if( rc!=SQLITE_OK ){
+    //fprintf(stderr, "sqlite3_bind_text failed on value\n");
+    rsstwritelog(LOG_ERROR, "sqlite3_bind_text failed on value %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+  rc = sqlite3_bind_text(ppStmt, 2, prop, -1, SQLITE_TRANSIENT);
+  if( rc!=SQLITE_OK ){
+    //fprintf(stderr, "sqlite3_bind_text failed on prop\n");
+    rsstwritelog(LOG_ERROR, "sqlite3_bind_text failed on prop %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Evaluate the result.
+   */
+  rc = sqlite3_step(ppStmt);
+  if( rc!=SQLITE_DONE ) {
+    //fprintf(stderr, "sqlite3_step\n");
+    //fprintf(stderr, "SQL error: %s\n", zErrMsg);
+    rsstwritelog(LOG_ERROR, "sqlite3_step %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return -1;
+  }
+
+  /*
+   * Free statement
+   */
+  rc = sqlite3_finalize(ppStmt);
+  if( rc!=SQLITE_OK ){
+    //fprintf(stderr, "Finalize failed in %s at line %d.!", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "Finalize failed in %s at line %d.!", __FILE__, __LINE__);
+    exit(1);
+  }
+
+
+  /*
+   * If the number of rows modified = 0 the config item was not found.
+   */
+  rc = sqlite3_changes(db);
+  if(rc == 0) {
+    return -1;
+  }
+
+  /*
+   * All gone well.
+   */
+  return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/config.h b/tags/swarmtv-0.9.2/libswarmtv/config.h
new file mode 100644
index 0000000..21d861b
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/config.h
@@ -0,0 +1,65 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+
+/*
+ * Get value of a config object.
+ * Make sure the free the value returned in the value pointer.
+ * @arguments
+ * prop name of config property to retrieve
+ * value pointer to the pointer that is going to hold the retrieved value.
+ * @returns
+ * 0 when the value was found, otherwise -1.
+ */
+int rsstconfiggetproperty(rsstor_handle *handle, char *prop, char **value);
+
+/*
+ * Set config item
+ * @arguments
+ * prop name of the propertie to change
+ * value new value to enter
+ * @returns
+ * When not found -1 is returned.
+ * On succes 0 is returned.
+ */
+int rsstsetconfigitem(rsstor_handle *handle, const char *prop, const char *value);
+
+/*
+ * Get value of a config object.
+ * @arguments
+ * prop name of the propertie to change
+ * number pointer to place to store value of prop
+ * @returns
+ * When not found -1 is returned.
+ * On succes 0 is returned.
+ */
+int rsstconfiggetint(rsstor_handle *handle, char *prop, int *number);
+
+/*
+ * Get value of a config object.
+ * @arguments
+ * prop name of the propertie to change
+ * number pointer to place to store value of prop
+ * @returns
+ * When not found -1 is returned.
+ * On succes 0 is returned.
+ */
+int rsstconfiggetlong(rsstor_handle *handle, char *prop, long *number);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/createpc.sh b/tags/swarmtv-0.9.2/libswarmtv/createpc.sh
new file mode 100755
index 0000000..be53b26
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/createpc.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+#cat libswarmtv/libswarmtv.pc.template | sed "s|@PREFIX@|${1}|" > libswarmtv.pc
+cat ${2}/libswarmtv.pc.template | sed "s|@PREFIX@|${1}|" > ${3}/libswarmtv.pc
diff --git a/tags/swarmtv-0.9.2/libswarmtv/curlfile.c b/tags/swarmtv-0.9.2/libswarmtv/curlfile.c
new file mode 100644
index 0000000..ade8d20
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/curlfile.c
@@ -0,0 +1,512 @@
+/*****************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * $Id: getinmemory.c,v 1.13 2008-09-06 04:28:45 yangtse Exp $
+ *
+ * Example source code to show how the callback function can be used to
+ * download data into a chunk of memory instead of storing it in a file.
+ *
+ * This exact source code has not been verified to work.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sqlite3.h>
+
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+
+#include "types.h"
+#include "curlfile.h"
+#include "regexp.h"
+#include "logfile.h"
+#include "config.h"
+
+#ifdef __MINGW32__
+#define strtok_r( _s, _sep, _lasts ) \
+( *(_lasts) = strtok( (_s), (_sep) ) )
+#endif /* !__MINGW32__ */
+
+/* Size of array to store regexp match pointers in */
+#define REGEXPSIZE      40
+/* End of line Character sequence in http header */
+#define HEADEREOL       "\r\n"
+/* The max amount of redirects  to follow */
+#define MAX_REDIR       3
+/* Time to wait before connection timeout on curl download */
+#define CONNECT_TIMEOUT 20
+#define CURL_TIMEOUT 60
+
+/*
+ * Reallocate
+ */
+static void *myrealloc(void *ptr, size_t size);
+
+/*
+ * Reallocate bigger memory when the file is big.
+ */
+static void *myrealloc(void *ptr, size_t size)
+{
+  /* There might be a realloc() out there that doesn't like reallocating
+   *      NULL pointers, so we take care of it here */
+  if(ptr)
+    return realloc(ptr, size);
+  else
+    return calloc(size, 1);
+}
+
+/*
+ * Callback function to download content to memory
+ */
+static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
+{
+  size_t realsize = size * nmemb;
+  MemoryStruct *mem = (MemoryStruct *)data;
+
+  mem->memory = myrealloc((void*) mem->memory, mem->size + realsize + 1);
+  if (mem->memory) {
+    memcpy(&(mem->memory[mem->size]), ptr, realsize);
+    mem->size += realsize;
+    mem->memory[mem->size] = 0;
+  }
+  return realsize;
+}
+
+/*
+ * Callback function to download header to memory
+ */
+static size_t WriteHeaderCallback(void *ptr, size_t size, size_t nmemb, void *data)
+{
+  size_t realsize = size * nmemb;
+  MemoryStruct *mem = (MemoryStruct *)data;
+
+  mem->header = myrealloc((void*) mem->header, mem->headersize + realsize + 1);
+  if (mem->header) {
+    memcpy(&(mem->header[mem->headersize]), ptr, realsize);
+    mem->headersize += realsize;
+    mem->header[mem->headersize] = 0;
+  }
+  return realsize;
+}
+
+
+/*
+ * Set proxy settings to Curl instance
+ */
+static void rsstcurlproxy(rsstor_handle *handle, CURL *curl_handle)
+{
+  char *enabled=NULL;
+  char *url=NULL;
+  char *userpass=NULL;
+  char *type=NULL;
+
+  /*
+   * Get variables for proxy
+   * CONF_PROXYENABLE  "proxy_enable"
+   * CONF_PROXYURL     "proxy_url"
+   * CONF_PROXYUSEPASS "proxy_userpass"
+   */
+  rsstconfiggetproperty(handle, CONF_PROXYENABLE, &enabled);
+  rsstconfiggetproperty(handle, CONF_PROXYURL, &url);
+  rsstconfiggetproperty(handle, CONF_PROXYUSEPASS, &userpass);
+  rsstconfiggetproperty(handle, CONF_PROXYTYPE, &type);
+
+  /*
+   * See if proxy support is set
+   */
+  if(strcasecmp(enabled, "y") == 0){
+    curl_easy_setopt(curl_handle, CURLOPT_PROXY, url);
+    curl_easy_setopt(curl_handle, CURLOPT_PROXYUSERPWD, userpass);
+
+    /*
+     * Translate proxy type to curl proxy type
+     */
+    if(strcasecmp(type, RSST_PROXY_SOCKS4) == 0){
+      curl_easy_setopt(curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+    }
+    if(strcasecmp(type, RSST_PROXY_SOCKS5) == 0){
+      curl_easy_setopt(curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+    }
+  }
+
+  /*
+   * Clean up
+   */
+  free(enabled);
+  free(url);
+  free(userpass);
+  free(type);
+}
+
+
+/*
+ * Initialize the CURL handle.
+ */
+static void rsstcurlinit(rsstor_handle *handle, CURL **curl_handle)
+{
+  /* Initialize the curl session */
+  *curl_handle = curl_easy_init();
+  if(*curl_handle == NULL) {
+    return;
+  }
+
+  /* Set max redirects */
+  curl_easy_setopt(*curl_handle, CURLOPT_MAXREDIRS, MAX_REDIR);
+
+  /* Set connection timeout on 1 minute */
+  curl_easy_setopt(*curl_handle, CURLOPT_CONNECTTIMEOUT, CONNECT_TIMEOUT);
+  curl_easy_setopt(*curl_handle, CURLOPT_TIMEOUT, CURL_TIMEOUT);
+
+  /* some servers don't like requests that are made without a user-agent
+   *      field, so we provide one */
+  curl_easy_setopt(*curl_handle, CURLOPT_USERAGENT, "SwarmTV");
+
+  /* Set generate error string */
+  curl_easy_setopt(*curl_handle, CURLOPT_ENCODING, "");
+
+  /* Make curl Follow redirects */
+  curl_easy_setopt(*curl_handle, CURLOPT_FOLLOWLOCATION, 1);
+
+  /*
+   * Handle proxy settings here
+   */
+  rsstcurlproxy(handle, *curl_handle);
+}
+
+/*
+ * Download URL and put the resulting data in chunk.
+ */
+int rsstdownloadtobuffer(rsstor_handle *handle, char *url, MemoryStruct *chunk)
+{
+  CURL *curl_handle=NULL;
+  int 	rc=0;
+  int   retval=0;
+	char *realurl=NULL;
+	char *cleanurl=NULL;
+	char *userpass=NULL;
+  char 	errorBuffer[CURL_ERROR_SIZE];
+
+  chunk->memory=NULL; /* we expect realloc(NULL, size) to work */
+  chunk->size = 0;    /* no data at this point */
+  chunk->header=NULL; /* header is empty */
+  chunk->headersize=0;  /* headersize is 0 */
+
+	/*
+	 * Determine if the URL holds user names and passwords.
+	 */
+	rc = rsstgetusernamepassword(url, &cleanurl, &userpass);
+	switch(rc) {
+		case 0:
+			/*
+			 * No password
+			 */
+			realurl=calloc(1, strlen(url)+1);
+			strncpy(realurl, url, strlen(url));
+			rsstwritelog(LOG_DEBUG, "Realurl			: %s\n", realurl);
+			break;
+		case 1:
+			/*
+			 * Password found
+			 */
+			rsstwritelog(LOG_DEBUG, "Passwd_url			: %s\n", url);
+			rsstwritelog(LOG_DEBUG, "Userpass				: %s\n", userpass);
+			rsstwritelog(LOG_DEBUG, "Cleanurl				: %s\n", cleanurl);
+
+		default:
+			/*
+			 * Any other case
+			 */
+			realurl=cleanurl;
+      cleanurl=NULL;
+      retval=-1;
+      break;
+  }
+
+  /* Generic initialization */
+  if(retval == 0) {
+    rsstcurlinit(handle, &curl_handle);
+  }
+
+  if(curl_handle == NULL) {
+    retval = -1;
+  } else {
+    /* specify URL to get */
+    curl_easy_setopt(curl_handle, CURLOPT_URL, realurl);
+
+    /* send all data to this function  */
+    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
+
+    /* send headers to this function */
+    curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, WriteHeaderCallback);
+
+    /* we pass our 'chunk' struct to the callback function */
+    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)chunk);
+
+    /* we pass our 'chunk' struct to the callback function */
+    curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *)chunk);
+
+    /* Set generate error string */
+    curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, errorBuffer);
+
+    /* If a user name and password is set add it to the options */
+    if(userpass != NULL) {
+      curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+      curl_easy_setopt(curl_handle, CURLOPT_USERPWD, userpass);
+    }
+
+    /* get it! */
+    rc = curl_easy_perform(curl_handle);
+
+    /* cleanup curl stuff */
+    curl_easy_cleanup(curl_handle);
+  }
+
+  /*
+   * Now, our chunk.memory points to a memory block that is chunk.size
+   * bytes big and contains the remote file.
+   *
+   * Do something nice with it!
+   *
+   * You should be aware of the fact that at this point we might have an
+   * allocated data block, and nothing has yet deallocated that data. So when
+   * you're done with it, you should free() it as a nice application.
+   */
+
+  /*
+   * Cleanup
+   */
+  free(realurl);
+  free(userpass);
+
+  return retval;
+}
+
+/*
+ * Download callback to file.
+ */
+static size_t curlfwrite(void *buffer, size_t size, size_t nmemb, void *stream)
+{
+  struct FtpFile *out=(struct FtpFile *)stream;
+  if(out && !out->stream) {
+    /* open file for writing */
+    out->stream=fopen(out->filename, "wb");
+    if(!out->stream)
+      return -1; /* failure, can't open file to write */
+  }
+  return fwrite(buffer, size, nmemb, out->stream);
+}
+
+/*
+ * Download to file.
+ * arguments
+ * url	URL to download from
+ * path	Path to store downloaded content in.
+ * return
+ * return 0 on success and -1 on failure.
+ */
+int rsstdownloadtofile(rsstor_handle *handle, char *url, char *path)
+{
+  CURL *curl;
+  CURLcode res;
+  struct FtpFile ftpfile;
+  int rc = 0;
+
+  /*
+   * Initialize ftp file struct
+   */
+  ftpfile.filename = path;
+  ftpfile.stream = NULL;
+
+  curl_global_init(CURL_GLOBAL_DEFAULT);
+
+  //curl = curl_easy_init();
+  rsstcurlinit(handle, &curl);
+  if(curl) {
+    /*
+		 * Set the URL the download is originating from.
+     */
+    curl_easy_setopt(curl, CURLOPT_URL, url);
+    /* Define our callback to get called when there's data to be written */
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlfwrite);
+    /* Set a pointer to our struct to pass to the callback */
+    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
+    /* Make curl Follow redirects */
+    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+    /* Set max redirects */
+    curl_easy_setopt(curl, CURLOPT_MAXREDIRS, MAX_REDIR);
+
+    /* Switch on full protocol/debug output */
+    //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+    res = curl_easy_perform(curl);
+
+    /* always cleanup */
+    curl_easy_cleanup(curl);
+
+    if(CURLE_OK != res) {
+      /* we failed */
+      rsstwritelog(LOG_ERROR, "curl told us %d %s:%d", res, __FILE__, __LINE__);
+      rc = -1; // Set Error
+    }
+  }
+
+  if(ftpfile.stream)
+    fclose(ftpfile.stream); /* close the local file */
+
+  curl_global_cleanup();
+
+  return rc;
+}
+
+
+/*
+ * Free the download and clean the leftovers
+ * Arguments :
+ * chunk 	pointer to downloaded data, NULL pointers are ignored.
+ */
+void rsstfreedownload(MemoryStruct *chunk)
+{
+  if(chunk != NULL) {
+    free(chunk->memory);
+    free(chunk->header);
+  }
+
+  return;
+}
+
+/*
+ * extract from HTTP-header
+ * This method extracts a given field from the http-header.
+ * The pointer returned contains the value.
+ * after use free the returned string
+ * Arguments
+ * name		Header value name.
+ * value	Pointer to store value in.
+ * chuck	Buffer to read header from.
+ * Return
+ * 0 on success, -1 on failure
+ */
+int rsstgetheadersvalue(char *name, char **value, MemoryStruct *chunk)
+{
+  char *header=NULL;
+  char *latest=NULL;
+  char *token=NULL;
+	char *lastvalue=NULL;
+  char regexp[REGEXPSIZE+1];
+  int rc=0;
+	int retvalue=-1;
+
+  /*
+   * Initialize vars
+   */
+  memset(regexp, 0, REGEXPSIZE+1);
+  *value=NULL;
+
+  /*
+   * Sanity checks
+   */
+  if(chunk == NULL || chunk->header == NULL) {
+    *value = 0;
+    return -1;
+  }
+
+  /*
+   * Copy the input buffer to temp buffer.
+   */
+	rsstalloccopy(&header, chunk->header, strlen(chunk->header));
+
+  /*
+   * Create regexp for getting header
+   */
+  snprintf(regexp, REGEXPSIZE, "^ *%s ?: ?(.*)", name);
+
+  /*
+   * Use strtok to split the header, and match line by line
+   */
+  token = strtok_r(header, HEADEREOL, &latest);
+  while(token != NULL) {
+    /*
+		 * Get the first match from the header
+		 */
+    rc =  rsstcapturefirstmatch(regexp, 0, token, value);
+    if(rc == 0) {
+      rsstwritelog(LOG_DEBUG, "Found '%s'->'%s'", token, *value);
+			/*
+			 * We want the last matching value only.
+			 * Free previous found value.
+			 */
+			free(lastvalue);
+			lastvalue=*value;
+			retvalue=0;
+    }
+
+    /*
+		 * Next token
+		 */
+    token = strtok_r(NULL, HEADEREOL, &latest);
+  }
+
+  /*
+   * Cleanup.
+   */
+  free(header);
+
+  /*
+	 * Return the value
+	 */
+  return retvalue;
+}
+
+/*
+ * Write retrieved buffer to file.
+ * arguments
+ * filename		path to store file in
+ * buffer			Buffer holding information.
+ * return
+ * 0 on success -1 on failure
+ */
+int rsstwritebuffer(char *filename, MemoryStruct *buffer)
+{
+  FILE          *file;
+  int           rc;
+  unsigned int  cur_char;
+
+  rsstwritelog(LOG_DEBUG,"Writing to : '%s' length '%ld' %s:%d", filename, buffer->size, __FILE__, __LINE__);
+
+  /*
+   * Save file to test.torrent
+   */
+  file = fopen(filename, "w+");
+  if(file == NULL) {
+    rsstwritelog(LOG_ERROR, "Could not open file : '%s'", strerror(errno));
+    return -1;
+  }
+
+  /* not very optimized, but coping for writing small files. */
+  for (cur_char = 0; cur_char < buffer->size; ++cur_char) {
+    rc = fputc(*(buffer->memory + cur_char), file);
+    if(rc == EOF) {
+      rsstwritelog(LOG_ERROR, "Could not write to file");
+      fclose(file);
+      return -1;
+    }
+  }
+
+  /*
+   * close file descriptor
+   */
+  fclose(file);
+
+  /*
+   * success !
+   */
+  return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/curlfile.h b/tags/swarmtv-0.9.2/libswarmtv/curlfile.h
new file mode 100644
index 0000000..246056d
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/curlfile.h
@@ -0,0 +1,83 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#ifndef CURLFILE
+#define CURLFILE
+
+/*
+ *  * HTTP header defines
+ *   * Not complete by a long shot, just what I need for now.
+ *    */
+#define HTTP_CONTENTTYPE  "Content-Type"
+#define HTTP_LENGHT       "Content-Length"
+#define HTTP_SERVER       "Server"
+
+/*
+ * Download url and put the resulting data in chunk.
+ * @arguments
+ * url
+ * chunk
+ * @returns
+ */
+int rsstdownloadtobuffer(rsstor_handle *handle, char *url, MemoryStruct *chunk);
+
+/*
+ * Free the download and clean the leftovers
+ * @arguments
+ * chuck pointer to MemoryStruct to free content of.
+ */
+void rsstfreedownload(MemoryStruct *chunk);
+
+/*
+ * Download to file.
+ * @arguments
+ * url the url to download the content from
+ * path the path to store the file (including filename)
+ * @returns
+ * 0 when all goes well
+ * -1 when not found
+ */
+int rsstdownloadtofile(rsstor_handle *handle, char *url, char *path);
+
+/*
+ * extract from HTTP-header
+ * This method extracts a given field from the http-header.
+ * The pointer returned contains the value.
+ * after use free the returned string
+ * @arguments
+ * name 	the name of the variable you wish to retrieve.
+ * value	the pointer to store the value of the variable in.
+ * chunk	the memory structure holding the header.
+ * @returns
+ * 0 on succes, -1 on failure
+ */
+int rsstgetheadersvalue(char *name, char **value, MemoryStruct *chunk);
+
+/*
+ * Write retrieved buffer to file.
+ * @arguments
+ * filename is the path to write the file to
+ * buffer to write to file
+ * @returns
+ * 0 on success, else -1
+ */
+int rsstwritebuffer(char *filename, MemoryStruct *buffer);
+
+#endif
diff --git a/tags/swarmtv-0.9.2/libswarmtv/database.c b/tags/swarmtv-0.9.2/libswarmtv/database.c
new file mode 100644
index 0000000..e49e6dc
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/database.c
@@ -0,0 +1,734 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pcre.h>
+#include <sqlite3.h>
+#include <stdarg.h>
+
+#include "types.h"
+#include "database.h"
+#include "logfile.h"
+#include "filesystem.h"
+#include "regexp.h"
+#include "setup.h"
+#include "sandboxdb.h"
+#include "testfilter.h"
+#include "simplefilter.h"
+#include "torrentdb.h"
+
+#ifdef __MINGW32__
+#define strtok_r( _s, _sep, _lasts ) \
+( *(_lasts) = strtok( (_s), (_sep) ) )
+#endif /* !__MINGW32__ */
+
+/*
+ * End of line character used by execute script routine.
+ */
+#define SCRIPT_EOL "\n"
+
+/*
+ * Memic to indicate comments used by execute script routine.
+ */
+#define SCRIPT_SYM "--"
+
+/*
+ * This is a fix for systems that use the old sqlite3 library without
+ * sqlite3_prepare_v2. Centos 5.6 is one of them.
+ */
+int rsst_sqlite3_prepare(
+    sqlite3 *db,            /* Database handle */
+    const char *zSql,       /* SQL statement, UTF-8 encoded */
+    int nByte,              /* Maximum length of zSql in bytes. */
+    sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
+    const char **pzTail     /* OUT: Pointer to unused portion of zSql */
+    )
+{
+  int rc=0;
+#if SQLITE_VERSION_NUMBER >= 3003009
+  rc = sqlite3_prepare_v2(
+      db,                 /* Database handle */
+      zSql,            /* SQL statement, UTF-8 encoded */
+      nByte,    /* Maximum length of zSql in bytes. */
+      ppStmt,             /* OUT: Statement handle */
+      pzTail              /* OUT: Pointer to unused portion of zSql */
+      );
+#else
+  rc = sqlite3_prepare(
+      db,                 /* Database handle */
+      zSql,            /* SQL statement, UTF-8 encoded */
+      nByte,    /* Maximum length of zSql in bytes. */
+      ppStmt,             /* OUT: Statement handle */
+      pzTail              /* OUT: Pointer to unused portion of zSql */
+      );
+#endif
+  return rc;
+}
+
+/*
+ * Executing script
+ * This function executes a script.
+ * Each line should be separated by a '\n' char.
+ * @Arguments
+ * script pointer so buffer holding script.
+ * @ returns
+ * 0 on success
+ * -1 on fail
+ */
+int dbexecscript(sqlite3 *db, const char *script)
+{
+	char 	*latest=NULL;
+	char 	*local=NULL;
+	char 	*line=NULL;
+	int		rc=0;
+	int		retval=0;
+	int		linenr=0;
+
+	/*
+	 * Copy to local buffer for strtok to modify
+	 */
+	rsstalloccopy(&local, script, strlen(script));
+
+	/*
+	 * Use strtok to separate the lines
+	 */
+	char *strtok(char *str, const char *delim);
+	line = strtok_r(local, SCRIPT_EOL, &latest);
+	while(line != NULL && retval == 0){
+		linenr++;
+
+		/*
+		 * Ignore comments
+		 */
+		if(strncmp(line, SCRIPT_SYM, strlen(SCRIPT_SYM)-1) == 0) {
+			line = strtok_r(NULL, SCRIPT_EOL, &latest);
+			continue;
+		}
+
+		/*
+		 * Execute line by line
+		 */
+		rc = rsstexecutequery(db, line, NULL);
+		if(rc < 0) {
+			/*
+			 * On error print report, and break loop.
+			 */
+			rsstwritelog(LOG_ERROR, "Error in script on line %d : %s", linenr, line);
+			retval = -1;
+		}
+
+		/*
+		 * Next line
+		 */
+		line = strtok_r(NULL, SCRIPT_EOL, &latest);
+	}
+
+	/*
+	 * Done.
+	 */
+	free(local);
+	return retval;
+}
+
+
+/*
+ * Do a query, and bind value's to the query in one step
+ * This is a simplified version as it only returns 1 value.
+ * that value is the first string of the first column.
+ * the value returned must be a TEXT value.
+ * the returned value will be put into text
+ * make sure to free text after use
+ * passing NULL to the fmt argument means no arguments.
+ * @Arguments
+ * text retrieved from the query
+ * query pointer to the query string
+ * fmt arguments pointer
+ * ... other arguments
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rsstdosingletextquery(sqlite3 *db, const unsigned char **text, const char *query, char *fmt, ...)
+{
+  sqlite3_stmt 	*ppStmt=NULL;
+  const char 		*pzTail=NULL;
+  int         	rc=0;
+  int         	step_rc=0;
+  char       		*zErrMsg = 0;
+  const unsigned char  *temptext=NULL;
+  va_list     	ap;
+  int         	retval=0;
+  int         	count=0;
+  char        	*s=NULL;
+  int          	d=0;
+  double       	f=0.0;
+
+  /*
+   * NULL = no arguments.
+   */
+  if(fmt == NULL) {
+    fmt = "";
+  }
+
+  /*
+   * Prepare the Sqlite statement
+   */
+  rc = rsst_sqlite3_prepare(
+      db,                 /* Database handle */
+      query,            /* SQL statement, UTF-8 encoded */
+      strlen(query),    /* Maximum length of zSql in bytes. */
+      &ppStmt,             /* OUT: Statement handle */
+      &pzTail              /* OUT: Pointer to unused portion of zSql */
+      );
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    retval = -1;
+  }
+
+  /*
+   * Handle the arguments
+   */
+  if(retval == 0) {
+    va_start(ap, fmt);
+    while (*fmt != '\0' && retval == 0){
+      count++; // next item
+      switch(*fmt++) {
+        case 's':            /* string */
+          s = va_arg(ap, char *);
+          rc = sqlite3_bind_text(ppStmt, count, s, -1, SQLITE_TRANSIENT);
+          if( rc!=SQLITE_OK ){
+            rsstwritelog(LOG_ERROR, "sqlite3_bind_text failed on argument '%d'\n'%s'\n'%s' %s:%d",
+                count, query, fmt, __FILE__, __LINE__);
+            rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+            sqlite3_free(zErrMsg);
+            retval=-1;
+          }
+          break;
+        case 'd':            /* int */
+          d = va_arg(ap, int);
+          rc = sqlite3_bind_int(ppStmt, count, d);
+          if( rc!=SQLITE_OK ){
+            rsstwritelog(LOG_ERROR, "sqlite3_bind_int failed on argument '%d'\n'%s'\n'%s' %s:%d",
+                count, query, fmt, __FILE__, __LINE__);
+            rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+            sqlite3_free(zErrMsg);
+            retval=-1;
+          }
+          break;
+        case 'f':            /* int */
+          f = va_arg(ap, double);
+          rc = sqlite3_bind_double(ppStmt, count, f);
+          if( rc!=SQLITE_OK ){
+            rsstwritelog(LOG_ERROR, "sqlite3_bind_double failed on argument '%d'\n'%s'\n'%s' %s:%d",
+                count, query, fmt, __FILE__, __LINE__);
+            rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+            sqlite3_free(zErrMsg);
+            retval=-1;
+          }
+          break;
+        default:
+          rsstwritelog(LOG_ERROR, "Unknown format '%c' on position '%d'\nQuery: '%s'\nFmt: '%s'",
+              *fmt, count, query, fmt);
+          retval=-1;
+      }
+    }
+    va_end(ap);
+  }
+
+  /*
+   * Get the first value discard the others.
+   */
+  if(retval == 0) {
+    /*
+     * Execute query
+     */
+    step_rc = sqlite3_step(ppStmt);
+
+    switch(step_rc){
+      case SQLITE_ROW:
+        /*
+         * context to output
+         */
+        temptext = sqlite3_column_text(ppStmt, 0);
+
+        /*
+         * Move result to premanent own location.
+         */
+				rsstalloccopy((char**)text,(char*) temptext, strlen((char*)temptext));
+
+        break;
+      case SQLITE_DONE:
+        *text=NULL;
+        break;
+      default:
+        rsstwritelog(LOG_ERROR, "sqlite3_step, %d %s:%d", step_rc, __FILE__, __LINE__);
+        rsstwritelog(LOG_ERROR, "in statement : \'%s\'", query);
+
+        *text=NULL;
+        retval=-1;
+        break;
+    }
+  }
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppStmt);
+
+  return retval;
+}
+
+/*
+ * Execute a query
+ * query, format, arguments
+ * format string accepts
+ * d = int , s = string, f = double, NULL pointer when no arguments.
+ * @arguments
+ * query pointer to query string
+ * fmt format string
+ * ... arguments to fill out in query
+ * @returns
+ * returns 1 on 1 row returned
+ * return 0 on no rows returned
+ * returns -1 on error
+ */
+int rsstexecutequery(sqlite3 *db, const char *query, char *fmt, ...)
+{
+  sqlite3_stmt 	*ppStmt=NULL;
+  const char 		*pzTail=NULL;
+  va_list     	ap;
+  int         	rc=0;
+  int         	retval=0;
+  int        		step_rc=0;
+  char       		*zErrMsg = 0;
+  char        	*s=NULL;
+  int          	d=0;
+  double       	f=0.0;
+  int          	count=0;
+  int          	changes=0;
+  int           errno=0;
+  const char   *errstring=NULL;
+
+  /*
+   * fmt pointer to NULL is do not substitutes
+   */
+  if(fmt == NULL){
+    fmt = "";
+  }
+
+  /*
+   * Prepare the Sqlite statement
+   */
+  rc = rsst_sqlite3_prepare(
+      db,                 /* Database handle */
+      query,            /* SQL statement, UTF-8 encoded */
+      strlen(query),    /* Maximum length of zSql in bytes. */
+      &ppStmt,             /* OUT: Statement handle */
+      &pzTail              /* OUT: Pointer to unused portion of zSql */
+      );
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    retval=-1;
+  }
+
+  /*
+   * Handle the arguments
+   */
+  va_start(ap, fmt);
+  while (*fmt != '\0' && retval == 0){
+    count++; // next item
+    switch(*fmt++) {
+      case 's':            /* string */
+        s = va_arg(ap, char *);
+        rc = sqlite3_bind_text(ppStmt, count, s, -1, SQLITE_TRANSIENT);
+        if( rc!=SQLITE_OK ){
+          rsstwritelog(LOG_ERROR, "sqlite3_bind_text failed on argument '%d'\n'%s'\n'%s' %s:%d",
+              count, query, fmt, __FILE__, __LINE__);
+          rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+          sqlite3_free(zErrMsg);
+          retval=-1;
+        }
+        break;
+      case 'd':            /* int */
+        d = va_arg(ap, int);
+        rc = sqlite3_bind_int(ppStmt, count, d);
+        if( rc!=SQLITE_OK ){
+          rsstwritelog(LOG_ERROR, "sqlite3_bind_int failed on argument '%d'\n'%s'\n'%s' %s:%d",
+              count, query, fmt, __FILE__, __LINE__);
+          rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+          sqlite3_free(zErrMsg);
+          retval=-1;
+        }
+        break;
+      case 'f':            /* int */
+        f = va_arg(ap, double);
+        rc = sqlite3_bind_double(ppStmt, count, f);
+        if( rc!=SQLITE_OK ){
+          rsstwritelog(LOG_ERROR, "sqlite3_bind_double failed on argument '%d'\n'%s'\n'%s' %s:%d",
+              count, query, fmt, __FILE__, __LINE__);
+          rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+          sqlite3_free(zErrMsg);
+          retval=-1;
+        }
+        break;
+      default:
+        rsstwritelog(LOG_ERROR, "Unknown format '%c' on position '%d'\nQuery: '%s'\nFmt: '%s'",
+          *fmt, count, query, fmt);
+        retval=-1;
+    }
+  }
+  va_end(ap);
+
+  /*
+   * Get the first value discard the others.
+   */
+  if(retval == 0){
+    step_rc = sqlite3_step(ppStmt);
+    switch(step_rc){
+      case SQLITE_ROW:
+        retval=ROWS_FOUND;
+        break;
+      case SQLITE_DONE:
+        retval=ROWS_EMPTY;
+        break;
+      case SQLITE_CONSTRAINT:
+        retval=ROWS_CONSTRAINT;
+        break;
+      default:
+        errno = sqlite3_errcode(db);
+        errstring = sqlite3_errmsg(db);
+        /*
+         * Workaround for older sqlite3 libraries, I hope they will upgrade soon to v2 compatible versions of sqlite
+         */
+#ifndef sqlite_prepare_v2
+        rsstwritelog(LOG_DEBUG, "sqlite3_step, %d %s:%d", step_rc, __FILE__, __LINE__);
+        rsstwritelog(LOG_DEBUG, "in statement : \'%s\'", query);
+#else
+        rsstwritelog(LOG_ERROR, "sqlite3_step, %s %d %s:%d", errstring, step_rc, __FILE__, __LINE__);
+        rsstwritelog(LOG_ERROR, "in statement : \'%s\'", query);
+#endif
+        retval=ROWS_ERROR;
+    }
+  }
+
+  /*
+   * If rows were changes return ROWS_CHANGED
+   */
+  if(retval == 0){
+    changes = sqlite3_changes(db);
+    if(changes > 0){
+      retval=ROWS_CHANGED;
+    }
+  }
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppStmt);
+
+  return retval;
+}
+
+/*
+ * Prepare a query
+ * query, format, arguments
+ * format string accepts
+ * d = int , s = string, f = double, NULL pointer when no arguments.
+ * @arguments
+ * ppstmt pointer carrying the results of the query
+ * query pointer to query string:
+ * fmt format string
+ * ... arguments to fill out in query
+ * @returns
+ * return 0 when all is okay
+ * returns -1  when the query fails
+ */
+int rsstexecqueryresult(sqlite3 *db, sqlite3_stmt **ppstmt, const char *query, char *fmt, ...)
+{
+	int rc=0;
+	va_list ap;
+
+	/*
+	 * Execute real function
+	 */
+	va_start(ap, fmt);
+	rc = rsstexecqueryresultva(db, ppstmt, query, fmt, ap);
+	va_end(ap);
+
+	/*
+	 * Done
+	 */
+	return rc;
+}
+
+/*
+ * Prepare a query
+ * query, format, arguments
+ * format string accepts
+ * d = int , s = string, f = double, NULL pointer when no arguments.
+ * @arguments
+ * ppstmt pointer carrying the results of the query
+ * query pointer to query string:
+ * fmt format string
+ * ap va_list argument list
+ * @returns
+ * return 0 on success
+ * returns -1 when the query fails
+ */
+int rsstexecqueryresultva(sqlite3 *db, sqlite3_stmt **ppstmt, const char *query, char *fmt, va_list ap)
+{
+  const char 		*pzTail=NULL;
+  int         	rc=0;
+  int         	retval=0;
+  char       		*zErrMsg = 0;
+  char        	*s=NULL;
+  int          	d=0;
+  double       	f=0.0;
+  int          	count=0;
+
+  /*
+   * fmt pointer to NULL is do not substitutes
+   */
+  if(fmt == NULL){
+    fmt = "";
+  }
+
+  /*
+   * Prepare the Sqlite statement
+   */
+  rc = rsst_sqlite3_prepare(
+      db,                 /* Database handle */
+      query,            /* SQL statement, UTF-8 encoded */
+      strlen(query),    /* Maximum length of zSql in bytes. */
+      ppstmt,             /* OUT: Statement handle */
+      &pzTail              /* OUT: Pointer to unused portion of zSql */
+      );
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    retval=-1;
+  }
+
+  /*
+   * Handle the arguments
+   */
+  while (*fmt != '\0' && retval == 0){
+    count++; // next item
+    switch(*fmt++) {
+      case 's':            /* string */
+        s = va_arg(ap, char *);
+        rc = sqlite3_bind_text(*ppstmt, count, s, -1, SQLITE_TRANSIENT);
+        if( rc!=SQLITE_OK ){
+          rsstwritelog(LOG_ERROR, "sqlite3_bind_text failed on argument '%d'\n'%s'\n'%s' %s:%d",
+              count, query, fmt, __FILE__, __LINE__);
+          rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+          sqlite3_free(zErrMsg);
+          retval=-1;
+        }
+        break;
+      case 'd':            /* int */
+        d = va_arg(ap, int);
+        rc = sqlite3_bind_int(*ppstmt, count, d);
+        if( rc!=SQLITE_OK ){
+          rsstwritelog(LOG_ERROR, "sqlite3_bind_int failed on argument '%d'\n'%s'\n'%s' %s:%d",
+              count, query, fmt, __FILE__, __LINE__);
+          rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+          sqlite3_free(zErrMsg);
+          retval=-1;
+        }
+        break;
+      case 'f':            /* float */
+        f = va_arg(ap, double);
+        rc = sqlite3_bind_double(*ppstmt, count, f);
+        if( rc!=SQLITE_OK ){
+          rsstwritelog(LOG_ERROR, "sqlite3_bind_double failed on argument '%d'\n'%s'\n'%s' %s:%d",
+              count, query, fmt, __FILE__, __LINE__);
+          rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+          sqlite3_free(zErrMsg);
+          retval=-1;
+        }
+        break;
+      default:
+        rsstwritelog(LOG_ERROR, "Unknown format '%c' on position '%d'\nQuery: '%s'\nFmt: '%s'",
+          *fmt, count, query, fmt);
+        retval=-1;
+    }
+  }
+
+  return retval;
+}
+
+/*
+ * Prints columns from query to standard out.
+ * third argument is the number of rows returned.
+ * Arguments
+ * query	query to print.
+ * Return
+ * return 0 when okay.
+ * return -1 on error.
+ */
+int rsstprintquery(sqlite3 *db, const char *query, char *fmt, ...)
+{
+  sqlite3_stmt  *ppstmt=NULL;
+  int           rc=0;
+  int           step_rc=0;
+  int           cols=0;
+  char          *zErrMsg=NULL;
+  int           count=0;
+  const unsigned char *text=NULL;
+	va_list				ap;
+
+  /*
+   * Prepare the Sqlite statement
+   */
+	va_start(ap, fmt);
+	rc = rsstexecqueryresultva(db, &ppstmt, query, fmt, ap);
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return -1;
+  }
+	va_end(ap);
+
+  /*
+   * Get number of columns
+   * int sqlite3_column_count(sqlite3_stmt *pStmt);
+   */
+  cols = sqlite3_column_count(ppstmt);
+
+  /*
+   * loop until the end of the dataset is found
+   */
+  while( SQLITE_DONE != (step_rc = sqlite3_step(ppstmt))) {
+
+    for(count=0; count<cols; count++){
+      /*
+       * Print the content of the row
+       */
+      text = sqlite3_column_text(ppstmt, count);
+      printf("%-25s", text);
+      if(count+1 < cols){
+        printf(" : ");
+      }
+    }
+
+    /*
+     * new line at end of record.
+     */
+    if(step_rc == SQLITE_ROW){
+      printf("\n");
+    }
+  }
+
+  /*
+   * Done with query, finalizing.
+   */
+  sqlite3_finalize(ppstmt);
+
+  /*
+   * All gone well
+   */
+  return rc;
+}
+
+
+/*
+ * Prints columns from query to standard out.
+ * third argument is the number of rows returned.
+ * Arguments
+ * query	Query to print.
+ * names	The names that should be printed in front of values.
+ * fmt		Format string describing the.
+ * Return
+ * return 0 when okay.
+ * return -1 on error.
+ */
+int rsstprintquerylist(sqlite3 *db, const char *query, char *names[], char *fmt, ...)
+{
+  sqlite3_stmt  *ppstmt=NULL;
+  int           rc=0;
+  int           step_rc=0;
+  int           cols=0;
+  char          *zErrMsg=NULL;
+  int           count=0;
+  const unsigned char *text=NULL;
+	va_list				ap;
+
+  /*
+   * Prepare the Sqlite statement
+   */
+	va_start(ap, fmt);
+	rc = rsstexecqueryresultva(db, &ppstmt, query, fmt, ap);
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return -1;
+  }
+	va_end(ap);
+
+  /*
+   * Get number of columns
+   * int sqlite3_column_count(sqlite3_stmt *pStmt);
+   */
+  cols = sqlite3_column_count(ppstmt);
+
+  /*
+   * loop until the end of the dataset is found
+   */
+  while( SQLITE_DONE != (step_rc = sqlite3_step(ppstmt))) {
+
+    for(count=0; count<cols; count++){
+      /*
+       * Print the content of the row
+       */
+      if(count == 0){
+        printf("%s\n", names[cols]);
+      }
+      text = sqlite3_column_text(ppstmt, count);
+      printf("%-15s : %s\n", names[count], text);
+    }
+
+    /*
+     * new line at end of record.
+     */
+    if(step_rc == SQLITE_ROW){
+      printf("\n");
+    }
+  }
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppstmt);
+
+  /*
+   * All gone well
+   */
+  return rc;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/database.h b/tags/swarmtv-0.9.2/libswarmtv/database.h
new file mode 100644
index 0000000..b1a2c02
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/database.h
@@ -0,0 +1,143 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Number of elements to allocate initially for returning results
+ */
+#define RSST_START_ELEMENTS 10
+
+/*
+ * This is a fix for systems that use the old sqlite3 library without
+ * sqlite3_prepare_v2. Centos 5.6 is one of them.
+ */
+int rsst_sqlite3_prepare(
+    sqlite3 *db,            /* Database handle */
+    const char *zSql,       /* SQL statement, UTF-8 encoded */
+    int nByte,              /* Maximum length of zSql in bytes. */
+    sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
+    const char **pzTail     /* OUT: Pointer to unused portion of zSql */
+    );
+
+/*
+ * Do a query, and bind value's to the query in one step
+ * This is a simplified version as it only returns 1 value.
+ * that value is the first string of the first colomn.
+ * the value returned must be a TEXT value.
+ * the returned value will be put into text
+ * make sure to free text after use
+ * @Arguments
+ * text retrieved from the query
+ * query pointer to the query string
+ * fmt arguments pointer
+ * ... other arguments
+ * @return
+ * 0 on succes, -1 on failure
+ */
+int rsstdosingletextquery(sqlite3 *db, const unsigned char **text, const char *query, char *fmt, ...);
+
+/*
+ * Execute a query
+ * query, format, arguments
+ * format string accepts
+ * d = int , s = string, f = double, NULL pointer when no arguments.
+ * @arguments
+ * query pointer to query string
+ * fmt format string
+ * ... arguments to fill out in query
+ * @returns
+ * returns 1 on 1 row returned
+ * return 0 on no rows returned
+ * returns -1 on error
+ */
+int rsstexecutequery(sqlite3 *db, const char *query, char *fmt, ...);
+
+/*
+ * Execute a query
+ * query, format, arguments
+ * format string accepts
+ * d = int , s = string, f = double, NULL pointer when no arguments.
+ * @arguments
+ * ppstmt pointer carying the results of the query
+ * query pointer to query string:
+ * fmt format string
+ * ... arguments to fill out in query
+ * @returns
+ * returns 1 on 1 row returned
+ * return 0 on no rows returned
+ * returns -1 on error
+ */
+int rsstexecqueryresult(sqlite3 *db, sqlite3_stmt **ppstmt, const char *query, char *fmt, ...);
+
+/*
+ * Execute a query
+ * query, format, arguments
+ * format string accepts
+ * d = int , s = string, f = double, NULL pointer when no arguments.
+ * @arguments
+ * ppstmt pointer carying the results of the query
+ * query pointer to query string:
+ * fmt format string
+ * ap va_list argument list
+ * @returns
+ * returns 1 on 1 row returned
+ * return 0 on no rows returned
+ * returns -1 on error
+ */
+int rsstexecqueryresultva(sqlite3 *db, sqlite3_stmt **ppstmt, const char *query, char *fmt, va_list ap);
+
+/*
+ * Prints columns from query to standard out.
+ * third argumnt is the number of rows returned.
+ * @Arguments
+ * query the query that retrieves the values to print
+ * fmt format string that goes with the query
+ * ... Arguments
+ * @Returns
+ * return 0 when okay
+ * return -1 on error
+ */
+int rsstprintquery(sqlite3 *db, const char *query, char *fmt, ...);
+
+
+/*
+ * Prints columns from query to standard out.
+ * third argumnt is the number of rows returned.
+ * Arguments
+ * query	Query to print.
+ * names	The names that should be printed infront of values.
+ * fmt		Format string describing the.
+ * Return
+ * return 0 when okay.
+ * return -1 on error.
+ */
+int rsstprintquerylist(sqlite3 *db, const char *query, char *names[], char *fmt, ...);
+
+/*
+ * Executing script
+ * This function executes a script.
+ * Each line should be separated by a '\n' char.
+ * @Arguments
+ * script pointer so buffer holding script.
+ * @ returns
+ * 0 on success
+ * -1 on fail
+ */
+int dbexecscript(sqlite3 *db, const char *script);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/databaseimpl.c b/tags/swarmtv-0.9.2/libswarmtv/databaseimpl.c
new file mode 100644
index 0000000..b3b021a
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/databaseimpl.c
@@ -0,0 +1,2085 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pcre.h>
+#include <sqlite3.h>
+#include <stdarg.h>
+
+#include "types.h"
+#include "database.h"
+#include "databaseimpl.h"
+#include "logfile.h"
+#include "filesystem.h"
+#include "regexp.h"
+#include "setup.h"
+#include "sandboxdb.h"
+#include "testfilter.h"
+#include "simplefilter.h"
+#include "torrentdb.h"
+#include "database.h"
+
+
+
+/*
+ * Database create script version 4
+ */
+static const char *dbinitscript =
+"BEGIN TRANSACTION"
+""
+"-- Drop tables\n"
+"drop table if exists version;\n"
+"drop table if exists newtorrents;\n"
+"drop table if exists downloaded;\n"
+"drop table if exists filters;\n"
+"drop table if exists sources;\n"
+"drop table if exists config;\n"
+"drop table if exists simplefilters;\n"
+"\n"
+"-- Create versioning field\n"
+"create table version (version INTEGER);\n"
+"INSERT INTO 'version' VALUES(4);\n"
+"\n"
+"-- Create the newtorrents table\n"
+"create table newtorrents (id INTEGER PRIMARY KEY,title TEXT, link TEXT UNIQUE, pubdate DATE, "
+"category TEXT, season INTEGER, episode INTEGER, seeds INTEGER DEFAULT 0, peers INTEGER DEFAULT 0, size INTEGER, source TEXT DEFAULT 'unknown', metatype TEXT DEFAULT 'torrent', new TEXT DEFAULT 'Y');\n"
+"\n"
+"-- Create the downloaded table\n"
+"create table downloaded (id INTEGER PRIMARY KEY,title TEXT, link TEXT UNIQUE, pubdate DATE, "
+"category TEXT, season INTEGER, episode INTEGER, date DATE, metatype TEXT DEFAULT 'torrent');\n"
+"\n"
+"-- Create the filters table\n"
+"create table filters (id INTEGER PRIMARY KEY, name TEXT UNIQUE, filter TEXT, nodouble TEXT DEFAULT '');\n"
+"CREATE TABLE simplefilters (id INTEGER PRIMARY KEY, name TEXT UNIQUE, title TEXT, exclude TEXT, category TEXT, source TEXT, maxsize INTEGER DEFAULT 0, "
+"minsize INTEGER DEFAULT 0, nodup TEXT NOT NULL, fromseason INTEGER DEFAULT 0, fromepisode INTEGER DEFAULT 0, metatype TEXT DEFAULT '');\n"
+"\n"
+"-- Create the sources table\n"
+"create table sources (id INTEGER PRIMARY KEY, name TEXT UNIQUE, url TEXT, parser TEXT, metatype TEXT DEFAULT 'torrent');\n"
+"\n"
+"-- Create the lastdownloaded table\n"
+"CREATE TABLE lastdownload (id INTEGER PRIMARY KEY, simple_id INTEGER UNIQUE, sql_id INTEGER UNIQUE, downloaded_id INTEGER);"
+"\n"
+"-- Create the config table, and fill out the table with the 'standard' values\n"
+"create table config (id INTEGER PRIMARY KEY, prop TEXT UNIQUE, value TEXT, descr TEXT);\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('torrentdir', '~/torrents', 'Path the downloaded Torrents are placed in.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('nzbdir', '~/nzb', 'Path the downloaded NZBs are placed in.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('logfile', '~/.swarmtv/swarmtv.log', 'Path to logfile.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('lockfile', '~/.swarmtv/lockfile.pid', 'Path to lockfile.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('refresh', '3600', 'Seconds between refreshes.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('retain', '30', 'The number of days source information is retained.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('default_parser', 'defaultrss', 'The default RSS filter to add to new rss sources.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('smtp_enable', 'N', '`Y` is send email notifications on new download, `N` is don`t.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('smtp_to', 'foo@bar.nl', 'Host to send the notifications to.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('smtp_from', 'user@somehost.nl', 'The from email-address in the mail headers.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('smtp_host', 'smtp.foobar.nl:25', 'The STMP server used to send the notifications.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('min_size', '4000000', 'When size is smaller then this, download torrent and check.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('tor_mon_dir', '~', 'Path downloaded Torrents end up.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('tor_mon_enable', 'n', 'Enable/disable tor partition usage monitering.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('nzb_mon_dir', '~', 'Path downloaded NZBs end up.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('nzb_mon_enable', 'n', 'Enable/disable nzb partition usage monitering.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('mon_limit', '90', 'Stop downloading when the disk usage exceeds.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('proxy_enable', 'n', 'Enable proxy support.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('proxy_url', '', 'URL of the HTTP proxy.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('proxy_userpass', '', 'User name and password of the proxy.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('proxy_type', '', 'Set the type of proxy to use default is HTTP.');\n"
+""
+"COMMIT"
+"\n";
+
+/*
+ * Database update script v1 to v2
+ */
+static const char *updatev1tov2 =
+"BEGIN TRANSACTION"
+""
+"-- Add parser column to newtorrents table\n"
+"ALTER TABLE newtorrents ADD COLUMN source TEXT DEFAULT 'unknown';\n"
+""
+"-- Add parser column to simplefilters table\n"
+"ALTER TABLE simplefilters ADD COLUMN source TEXT DEFAULT '';\n"
+""
+"-- Up database version from version 1 to 2\n"
+"update version set version = '2';\n"
+""
+"COMMIT"
+"\n";
+
+/*
+ * Database update script v2 to v3
+ */
+static const char *updatev2tov3 =
+"BEGIN TRANSACTION"
+""
+"-- Add filetype to newtorrents table (Might be renamed all togethera)\n"
+"ALTER TABLE newtorrents ADD COLUMN metatype TEXT DEFAULT 'torrent';\n"
+""
+"-- Add nzb Monitor directory to config-options\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('nzbdir', '~/nzb', 'Path the downloaded NZBs are placed in.');\n"
+""
+"-- Add meta type to source table\n"
+"ALTER TABLE sources  ADD COLUMN metatype TEXT DEFAULT 'torrent';\n"
+""
+"-- Add metatype column to simplefilters table\n"
+"ALTER TABLE simplefilters ADD COLUMN metatype TEXT DEFAULT '';\n"
+""
+"-- Make sure to include the metatype the file came from in the downloaded table.\n"
+"ALTER TABLE downloaded ADD COLUMN metatype TEXT DEFAULT 'torrent';\n"
+""
+"-- Up database version from version 2 to 3\n"
+"update version set version = '3';\n"
+""
+"-- Add the lastdownloaded tablei\n"
+"CREATE TABLE lastdownload (id INTEGER PRIMARY KEY, simple_id INTEGER UNIQUE, sql_id INTEGER UNIQUE, downloaded_id INTEGER);\n"
+""
+"COMMIT"
+"\n";
+
+static const char *updatev3tov4 =
+"BEGIN TRANSACTION"
+""
+"-- Inserting new properties\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('tor_mon_dir', '~', 'Path downloaded Torrents end up.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('tor_mon_enable', 'n', 'Enable/disable tor partition usage monitering.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('nzb_mon_dir', '~', 'Path downloaded NZBs end up.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('nzb_mon_enable', 'n', 'Enable/disable nzb partition usage monitering.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('mon_limit', '90', 'Stop downloading when the disk usage exceeds.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('proxy_enable', 'n', 'Enable proxy support.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('proxy_url', '', 'URL of the HTTP proxy.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('proxy_userpass', '', 'User name and password of the proxy.');\n"
+"INSERT INTO 'config' (prop, value, descr) VALUES('proxy_type', '', 'Set the type of proxy to use default is HTTP.');\n"
+""
+"-- Up database version from version 3 to 4\n"
+"update version set version = '4';\n"
+""
+"COMMIT"
+"\n";
+
+
+/*
+ * Get database version.
+ * @arguments
+ * version pointer to int holding database version number
+ * @return
+ * 0 on success, -1 on failure
+ */
+static int getdbversion(sqlite3 *db, int *version)
+{
+	int 	rc=0;
+	char *text=NULL;
+
+	const char *existquery="SELECT * FROM sqlite_master WHERE name = 'version' AND type = 'table'";
+	const char *query="SELECT version FROM version";
+
+	/*
+	 * Test if version table exists
+	 */
+	rc = rsstexecutequery(db, existquery, NULL);
+	free(text);
+	if(rc != 1) {
+		/*
+		 * version table not there
+		 */
+		*version=0;
+		return -1;
+	}
+
+	/*
+	 * Execute query.
+	 * translate value when found
+	 */
+	rc = rsstdosingletextquery(db, (unsigned char const**)&text, query, NULL);
+	if(rc == 0) {
+		*version = atoi(text);
+	}
+
+	/*
+	 * Return rc from dosingeltextquery
+	 */
+	free(text);
+	return rc;
+}
+
+/*
+ * Create a complete database if needed, otherwise run update scripts.
+ * @arguments
+ * version current database version
+ * @return
+ * 0 on success, -1 on failure
+ */
+static int fixdb(rsstor_handle *handle, int version)
+{
+  int 			rc=0;
+	sqlite3  *db=NULL;
+
+	/*
+	 * get db pointer
+	 */
+	db = handle->db;
+
+  /*
+   * When version is < 1 database state unknown reinitialize whole db
+   */
+  if(version < 1) {
+    rc = rsstrundbinitscript(handle);
+    return rc;
+  }
+
+  /*
+   * When the database version < 2 run this script to update it to version 2.
+   */
+  if(version < 2) {
+    rsstwritelog(LOG_NORMAL, "Updating database from version 1 to version 2.");
+    rc = dbexecscript(db, updatev1tov2);
+    if(rc < 0) {
+      rsstwritelog(LOG_ERROR, "Update script version 1 to version 2 Failed!");
+      rsstwritelog(LOG_ERROR, "Update aborted.");
+      return rc;
+    }
+  }
+  if(version < 3) {
+    rsstwritelog(LOG_NORMAL, "Updating database from version 2 to version 3.");
+    rc = dbexecscript(db, updatev2tov3);
+    if(rc < 0) {
+      rsstwritelog(LOG_ERROR, "Update script version 2 to version 3 Failed!");
+      rsstwritelog(LOG_ERROR, "Update aborted.");
+      return rc;
+    }
+  }
+  if(version < 4) {
+    rsstwritelog(LOG_NORMAL, "Updating database from version 3 to version 4.");
+    rc = dbexecscript(db, updatev3tov4);
+    if(rc < 0) {
+      rsstwritelog(LOG_ERROR, "Update script version 3 to version 4 Failed!");
+      rsstwritelog(LOG_ERROR, "Update aborted.");
+      return rc;
+    }
+  }
+
+  /*
+   * All update scripts done, return result
+   */
+  return rc;
+}
+
+/*
+ * Run the Database init script.
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rsstrundbinitscript(rsstor_handle *handle)
+{
+	int rc=0;
+
+	/*
+	 * Execute query
+	 */
+	rc = dbexecscript(handle->db, dbinitscript);
+
+	/*
+	 * return result
+	 */
+	return rc;
+}
+
+
+/*
+ * This function implements PCRE functionality to the queries.
+ * called every time Sqlite crosses an regexp.
+ */
+static void genregexpfunc(sqlite3_context *db, int num, sqlite3_value **sqlite3_value, int opt){
+  int   			rc=0;
+  const char 	*var1=NULL;
+  const char 	*var2=NULL;
+  pcre 				*re = NULL;
+  const char 	*error = NULL;
+  int 				errOffset = 0;
+  int 				match=0;
+
+  /*
+   * sanity check
+   */
+  if(num != 2) {
+    rsstwritelog(LOG_ERROR, "on line: %d, in file: %s, the wrong number of arguments were called: %d",
+      __LINE__,
+      __FILE__,
+      num);
+    exit(1);
+  }
+
+  /*
+   * Extract the values from the function call.
+   */
+  var1 = (const char*) sqlite3_value_text(sqlite3_value[0]);
+  var2 = (const char*) sqlite3_value_text(sqlite3_value[1]);
+
+	/*
+	 * When NULL is provided, match fails.
+	 */
+	if(var2 == NULL) {
+		sqlite3_result_int(db, 0);
+		return;
+	}
+
+  /*
+   * Compile regular expression
+   */
+  re = pcre_compile( var1, opt, &error,
+      &errOffset, NULL);
+  if (re == NULL) {
+    rsstwritelog(LOG_ERROR, "Regexp compilation failed at "
+        "offset %d: %s %s:%d\n", errOffset, error, __FILE__, __LINE__);
+    exit(1);
+  }
+
+  /*
+   * Do the match and interpret outcome.
+   */
+  rc = pcre_exec(re, NULL, var2, strlen(var2), 0,
+      0 /* default options */, NULL, 0);
+  switch (rc) {
+    case PCRE_ERROR_NOMATCH:
+      match = 0;
+      break;
+    case PCRE_ERROR_BADOPTION:
+      rsstwritelog(LOG_ERROR, "An unrecognized bit was set in the "
+          "options argument %s:%d", __FILE__, __LINE__);
+      break;
+    case PCRE_ERROR_NOMEMORY:
+      rsstwritelog(LOG_ERROR, "Not enough memory available. %s:%d", __FILE__, __LINE__);
+      break;
+    default:
+      if (rc < 0) {
+        rsstwritelog(LOG_ERROR, "A regexp match error "
+            "occurred: %d %s:%d", rc, __FILE__, __LINE__);
+      }
+      else {
+        match = 1;
+      }
+      break;
+  }
+
+  /*
+   * Close the regexp
+   */
+  pcre_free(re);
+
+  /*
+   * return result.
+   */
+  sqlite3_result_int(db, match);
+}
+
+
+/*
+ * This function implement PCRE functionality to the queries.
+ * called every time Sqlite crosses an regexp.
+ */
+static void regexpfunc(sqlite3_context *db, int num, sqlite3_value **sqlite3_value)
+{
+	genregexpfunc(db, num, sqlite3_value, 0);
+}
+
+
+/*
+ * This function implement PCRE functionality to the queries.
+ * called every time Sqlite crosses an regexp.
+ * This function matches case insensitive.
+ */
+static void iregexpfunc(sqlite3_context *db, int num, sqlite3_value **sqlite3_value)
+{
+	genregexpfunc(db, num, sqlite3_value, PCRE_CASELESS);
+}
+
+
+/*
+ * Open database, and add regexp functionality.
+ * make sure the handle pointer is pointing to an valid address
+ * @Arguments
+ * filename Database filename
+ * handle RSS-torrent handle
+ * @Returns
+ *
+ */
+int rsstinitdatabase(const char *filename, rsstor_handle *handle)
+{
+	int         rc=0; /* return code */
+	int					version=0;
+	char       *zErrMsg = 0;
+	char       *dbpath = NULL;
+	sqlite3    *db=NULL;
+
+	/*
+	 * Complete the filename is it contains a ~ as home dir
+	 */
+	rsstcompletepath(filename, &dbpath);
+
+	/*
+   * Open the Sqlite database.
+   */
+  rc = sqlite3_open(dbpath, &db);
+  if( rc ){
+    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
+    sqlite3_close(db);
+    return !SQLITE_OK;
+  }
+
+	/*
+	 * Store db pointer
+	 */
+	handle->db = db;
+
+  /*
+   * free db path
+   */
+  free(dbpath);
+
+	/*
+	 * Test if database is initialized and of the right version.
+	 */
+	rc = getdbversion(db, &version);
+	if(rc != 0 || version != RSST_DB_VERSION){
+		/*
+		 * Create new DB
+		 */
+		printf("Running create database script.\n");
+    rc = fixdb(handle, version);
+		if(rc == -1){
+			fprintf(stderr, "Can't open database, init script failed!\n");
+			sqlite3_close(db);
+			return !SQLITE_OK;
+		}
+	}
+
+  /*
+   * Add regexp function.
+   */
+  typedef struct sqlite3_value sqlite3_value;
+  rc = sqlite3_create_function(
+      db,
+      "regexp",       // name of the function
+      2,              // number of arguments
+      SQLITE_UTF8,    // Kind of encoding we expect
+      NULL,
+      regexpfunc,     // function to call
+      NULL,           //
+      NULL
+      );
+  if( rc!=SQLITE_OK ){
+    fprintf(stderr, "sqlite3_create_function\n");
+    fprintf(stderr, "SQL error: %s\n", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return !SQLITE_OK;
+  }
+
+  rc = sqlite3_create_function(
+      db,
+      "iregexp",       // name of the function
+      2,              // number of arguments
+      SQLITE_UTF8,    // Kind of encoding we expect
+      NULL,
+      iregexpfunc,     // function to call
+      NULL,           //
+      NULL
+			);
+  if( rc!=SQLITE_OK ){
+    fprintf(stderr, "sqlite3_create_function\n");
+    fprintf(stderr, "SQL error: %s\n", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return !SQLITE_OK;
+  }
+
+  /*
+   * All went well.
+   */
+  return SQLITE_OK;
+}
+
+/*
+ * Reallocate if not big enough
+ * @Arguments
+ * buffer Pointer to buffer
+ * bufnr pointer to number of elements in the buffer
+ * occupied number of elements occupied
+ * structsize size of the structure in place
+ * @returns
+ * pointer to new area, null or fail.
+ */
+static void *rsstmakespace(void *buffer, int *bufnr, int occupied, size_t structsize)
+{
+	size_t newsize=0;
+
+	/*
+	 * Reallocate twice the size when we run out of space
+	 */
+	if(occupied == *bufnr) {
+		*bufnr = *bufnr * 2;
+		newsize = *bufnr * structsize;
+		buffer = realloc(buffer, newsize);
+		if(buffer == NULL) {
+			rsstwritelog(LOG_ERROR, "Realloc failed ! %s:%d", __FILE__, __LINE__);
+			return NULL;
+		}
+	}
+
+	return buffer;
+}
+
+
+/*
+ * Store database result into struct
+ * @Arguments
+ * result
+ * container
+ * @returns
+ * 0 on success otherwise -1
+ */
+static int rsststoreconfigcontainer(sqlite3_stmt *result, config_container *container)
+{
+	int 		count=0;
+	int 		allocrecords=0;
+	char 	 *column=NULL;
+
+	/*
+	 * prealloc for START_ELEMENTS number of records
+	 */
+	allocrecords = RSST_START_ELEMENTS;
+	container->config = calloc(allocrecords, sizeof(config_struct));
+	if(container->config == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+  /*
+   * loop until the end of the dataset is found
+	 * Copy results to struct
+   */
+  while( SQLITE_DONE != sqlite3_step(result)) {
+		/*
+		 * Store values
+		 */
+		container->config[count].id = sqlite3_column_int(result, 0);
+		column = (char*) sqlite3_column_text(result, 1);
+		rsstalloccopy(&(container->config[count].name), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 2);
+		rsstalloccopy(&(container->config[count].value), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 3);
+		rsstalloccopy(&(container->config[count].description), column, strlen(column));
+		count++;
+
+		/*
+		 * Realloc goes here
+		 */
+		container->config = rsstmakespace(container->config, &allocrecords, count, sizeof(config_struct));
+  }
+
+	/*
+	 * Save number of records retrieved
+	 */
+	container->nr=count;
+
+	return 0;
+}
+
+/*
+ * Get all config settings
+ * @Arguments
+ * configitems The container to store the config items in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallconfig(rsstor_handle *handle, config_container **configitems)
+{
+	int 					rc=0;
+	int 					retval=0;
+	sqlite3_stmt *ppstmt=NULL;
+	config_container *localitems=NULL;
+	char         *zErrMsg=NULL;
+	sqlite3      *db=NULL;
+
+	/*
+	 * Get db pointer.
+	 */
+	db = handle->db;
+
+	/*
+	 * Query to retrieve config items
+	 */
+	const char *query = "select id, prop, value, descr from config";
+
+	/*
+	 * Alloc the container
+	 */
+	localitems = calloc(1, sizeof(config_container));
+	if(localitems == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecqueryresult(db, &ppstmt, query, NULL);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Store result into container
+	 */
+	rc = rsststoreconfigcontainer(ppstmt, localitems);
+
+	/*
+	 * Set output.
+	 */
+	*configitems = localitems;
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppstmt);
+	return retval;
+}
+
+/*
+ * Free config struct
+ * @Arguments
+ * config pointer to config structure
+ */
+static void rsstfreeconfig(config_struct *config)
+{
+	free(config->name);
+	free(config->value);
+	free(config->description);
+}
+
+/*
+ * Delete content from config_container struct
+ * @Arguments
+ * container Pointer to configcontainer to free content of
+ * @Return
+ * 0 on success, -1 on failure
+ */
+int rsstfreeconfigcontainer(config_container *container)
+{
+	int count=0;
+
+	/*
+	 * Sanity checks
+	 */
+	if(container->config == NULL) {
+		return -1;
+	}
+
+	/*
+	 * Free config values structures in container
+	 */
+	for(count=0; count < container->nr; count++)
+	{
+		rsstfreeconfig(container->config+count);
+	}
+
+	/*
+	 * free the container itself
+	 */
+	free(container->config);
+	free(container);
+
+	return 0;
+}
+
+/*
+ * Free config struct
+ * @Arguments
+ * config pointer to config structure
+ */
+static void rsstfreefilter(filter_struct *filter)
+{
+	free(filter->name);
+	free(filter->filter);
+	free(filter->nodup);
+}
+
+/*
+ * Delete content from config_container struct
+ * @Arguments
+ * container Pointer to configcontainer to free content of
+ * @Return
+ * 0 on success, -1 on failure
+ */
+int rsstfreefiltercontainer(filter_container *container)
+{
+	int count=0;
+
+	/*
+	 * Sanity checks
+	 */
+	if(container->filter == NULL) {
+		return -1;
+	}
+
+	/*
+	 * Free config values structures in container
+	 */
+	for(count=0; count < container->nr; count++)
+	{
+		rsstfreefilter(container->filter+count);
+	}
+
+	/*
+	 * free the container itself
+	 */
+	free(container->filter);
+	free(container);
+
+	return 0;
+}
+
+/*
+ * Store database result into struct
+ * @Arguments
+ * result
+ * container
+ * @returns
+ * 0 on success otherwise -1
+ */
+static int rsststorefiltercontainer(sqlite3_stmt *result, filter_container *container)
+{
+	int 		count=0;
+	int 		allocrecords=0;
+	char 	 *column=NULL;
+
+	/*
+	 * prealloc for START_ELEMENTS number of records
+	 */
+	allocrecords = RSST_START_ELEMENTS;
+	container->filter = calloc(allocrecords, sizeof(filter_struct));
+	if(container->filter == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+  /*
+   * loop until the end of the dataset is found
+	 * Copy results to struct
+   */
+  while( SQLITE_DONE != sqlite3_step(result)) {
+		/*
+		 * Store values
+		 */
+		container->filter[count].id = sqlite3_column_int(result, 0);
+		column = (char*) sqlite3_column_text(result, 1);
+		rsstalloccopy(&(container->filter[count].name), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 2);
+		rsstalloccopy(&(container->filter[count].filter), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 3);
+		rsstalloccopy(&(container->filter[count].nodup), column, strlen(column));
+		count++;
+
+		/*
+		 * Realloc goes here
+		 */
+		container->filter = rsstmakespace(container->filter, &allocrecords, count, sizeof(filter_struct));
+  }
+
+	/*
+	 * Save number of records retrieved
+	 */
+	container->nr=count;
+
+	return 0;
+}
+
+/*
+ * Get all SQL filter settings
+ * @Arguments
+ * handle RSS-torrent handle
+ * container The container to store the container in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallfilter(rsstor_handle *handle, filter_container **container)
+{
+	int 					rc=0;
+	int 					retval=0;
+	sqlite3_stmt *ppstmt=NULL;
+	filter_container *localitems=NULL;
+	char         *zErrMsg=NULL;
+	sqlite3      *db=NULL;
+
+	/*
+	 * Get db pointer.
+	 */
+	db = handle->db;
+
+	/*
+	 * Query to retrieve filter items
+	 */
+	const char *query = "select id, name, filter, nodouble from 'filters'";
+
+	/*
+	 * Alloc the container
+	 */
+	localitems = calloc(1, sizeof(filter_container));
+	if(localitems == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecqueryresult(db, &ppstmt, query, NULL);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "Sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Store result into container
+	 */
+	rc = rsststorefiltercontainer(ppstmt, localitems);
+
+	/*
+	 * Set output.
+	 */
+	*container = localitems;
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppstmt);
+	return retval;
+}
+
+/*
+ * Get all SQL filter settings
+ * @Arguments
+ * handle RSS-torrent handle
+ * container The container to store the container in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetfilterbyname(rsstor_handle *handle, char *name, filter_container **container)
+{
+	int 					rc=0;
+	int 					retval=0;
+	sqlite3_stmt *ppstmt=NULL;
+	filter_container *localitems=NULL;
+	char         *zErrMsg=NULL;
+	sqlite3      *db=NULL;
+
+	/*
+	 * Sanity check
+	 */
+	if(name == NULL){
+		return -1;
+	}
+
+	/*
+	 * Get db pointer.
+	 */
+	db = handle->db;
+
+	/*
+	 * Query to retrieve filter items
+	 */
+	const char *query = "select id, name, filter, nodouble from 'filters' where name = ?1";
+
+	/*
+	 * Alloc the container
+	 */
+	localitems = calloc(1, sizeof(filter_container));
+	if(localitems == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecqueryresult(db, &ppstmt, query, "s", name);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Store result into container
+	 */
+	rc = rsststorefiltercontainer(ppstmt, localitems);
+
+	/*
+	 * Set output.
+	 */
+	*container = localitems;
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppstmt);
+	return retval;
+}
+
+
+/*
+ * Store database result into struct
+ * @Arguments
+ * result
+ * container
+ * @returns
+ * 0 on success otherwise -1
+ */
+static int rsststoredownloadedcontainer(sqlite3_stmt *result, downloaded_container *container)
+{
+	int 		count=0;
+	int 		allocrecords=0;
+	char 	 *column=NULL;
+
+	/*
+	 * prealloc for START_ELEMENTS number of records
+	 */
+	allocrecords = RSST_START_ELEMENTS;
+	container->downloaded = calloc(allocrecords, sizeof(downloaded_struct));
+	if(container->downloaded == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+  /*
+   * loop until the end of the dataset is found
+	 * Copy results to struct
+   */
+  while( SQLITE_DONE != sqlite3_step(result)) {
+		/*
+		 * Store values
+		 */
+		container->downloaded[count].id = sqlite3_column_int(result, 0);
+		column = (char*) sqlite3_column_text(result, 1);
+		rsstalloccopy(&(container->downloaded[count].title), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 2);
+		rsstalloccopy(&(container->downloaded[count].link), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 3);
+		rsstalloccopy(&(container->downloaded[count].pubdate), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 4);
+		rsstalloccopy(&(container->downloaded[count].category), column, strlen(column));
+		container->downloaded[count].season = sqlite3_column_int(result, 5);
+		container->downloaded[count].episode = sqlite3_column_int(result, 6);
+		column = (char*)sqlite3_column_text(result, 7);
+		rsstalloccopy(&(container->downloaded[count].downdate), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 8);
+		rsstalloccopy(&(container->downloaded[count].metatype), column, strlen(column));
+    container->downloaded[count].baretitle=NULL;
+    container->downloaded[count].filter=NULL;
+		count++;
+
+		/*
+		 * Reallocate goes here
+		 */
+		container->downloaded = rsstmakespace(container->downloaded, &allocrecords, count, sizeof(downloaded_struct));
+	}
+
+	/*
+	 * Save number of records retrieved
+	 */
+	container->nr=count;
+
+	return 0;
+}
+
+
+/*
+ * Get downloaded torrents
+ * @arguments
+ * downloaded The container to store the downloaded in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetdownloaded(rsstor_handle *handle, downloaded_container **downloaded, int limit, int offset)
+{
+	int 					rc=0;
+	int 					retval=0;
+	sqlite3_stmt *ppstmt=NULL;
+	downloaded_container *localitems=NULL;
+	char         *zErrMsg=NULL;
+	sqlite3      *db=NULL;
+
+	/*
+	 * handle
+	 */
+	db = handle->db;
+
+	/*
+	 * Query to retrieve downloaded items
+	 * int   id;
+	 * char *title;
+	 * char *link;
+	 * char *pubdate;
+	 * char *category;
+	 * int  season;
+	 * int  episode;
+	 */
+	const char *query = "SELECT id, title, link, pubdate, category, season, episode, date, metatype "
+    "FROM downloaded "
+    "ORDER BY date DESC LIMIT ?1 OFFSET ?2";
+
+	/*
+	 * Allocate the container
+	 */
+	localitems = calloc(1, sizeof(downloaded_container));
+	if(localitems == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecqueryresult(db, &ppstmt, query, "dd", limit, offset);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Store result into container
+	 */
+	rc = rsststoredownloadedcontainer(ppstmt, localitems);
+
+	/*
+	 * Set output.
+	 */
+	*downloaded = localitems;
+
+	/*
+	 * Done with query, finalizing.
+	 */
+	rc = sqlite3_finalize(ppstmt);
+	return retval;
+}
+
+
+/*
+ * Free downloaded structure
+ * @Arguments
+ * downloaded pointer to downloaded struct to be freed
+ */
+void rsstfreedownloaded(downloaded_struct *downloaded)
+{
+  if(downloaded == NULL) {
+    return;
+  }
+
+	/*
+	 * char *title;
+	 * char *link;
+	 * char *pubdate;
+	 * char *category;
+	 */
+	free(downloaded->title);
+	free(downloaded->link);
+	free(downloaded->pubdate);
+	free(downloaded->category);
+  free(downloaded->metatype);
+  free(downloaded->baretitle);
+  free(downloaded->downdate);
+  free(downloaded->filter);
+}
+
+
+/*
+ * Delete content from source_container struct
+ * @Arguments
+ * container downloaded container content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreedownloadedcontainer(downloaded_container *container)
+{
+	int count=0;
+
+	/*
+	 * Sanity checks
+	 */
+	if(container->downloaded == NULL) {
+		return -1;
+	}
+
+	/*
+	 * Free config values structures in container
+	 */
+	for(count=0; count < container->nr; count++)
+	{
+		rsstfreedownloaded(container->downloaded+count);
+	}
+
+	/*
+	 * free the array itself
+	 */
+	free(container->downloaded);
+	free(container);
+
+	return 0;
+}
+
+/*
+ * Store the database result into a simple struct
+ */
+static void rsststoresimplestruct(sqlite3_stmt *result, simplefilter_struct *simple)
+{
+	char 	 *column=NULL;
+
+  /*
+   * Store values
+   */
+  simple->id = sqlite3_column_int(result, 0);
+  column = (char*) sqlite3_column_text(result, 1);
+  rsstalloccopy(&(simple->name), column, strlen(column));
+  column = (char*) sqlite3_column_text(result, 2);
+  rsstalloccopy(&(simple->title), column, strlen(column));
+  column = (char*) sqlite3_column_text(result, 3);
+  rsstalloccopy(&(simple->exclude), column, strlen(column));
+  column = (char*)sqlite3_column_text(result, 4);
+  rsstalloccopy(&(simple->category), column, strlen(column));
+  column = (char*)sqlite3_column_text(result, 5);
+  rsstalloccopy(&(simple->source), column, strlen(column));
+  simple->maxsize = sqlite3_column_double(result, 6);
+  simple->minsize = sqlite3_column_double(result, 7);
+  column = (char*)sqlite3_column_text(result, 8);
+  rsstalloccopy(&(simple->nodup), column, strlen(column));
+  simple->fromseason  = sqlite3_column_double(result, 9);
+  simple->fromepisode = sqlite3_column_double(result, 10);
+}
+
+
+/*
+ * Store database result into struct
+ * @Arguments
+ * result
+ * container
+ * @returns
+ * 0 on success otherwise -1
+ */
+static int rsststoresimplecontainer(sqlite3_stmt *result, simplefilter_container *container)
+{
+	int 		count=0;
+	int 		allocrecords=0;
+  simplefilter_struct *simplestruct=NULL;
+
+	/*
+	 * reallocate for START_ELEMENTS number of records
+	 */
+	allocrecords = RSST_START_ELEMENTS;
+	container->simplefilter = calloc(allocrecords, sizeof(simplefilter_struct));
+	if(container->simplefilter == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+  /*
+   * loop until the end of the dataset is found
+	 * Copy results to struct
+   */
+  while( SQLITE_DONE != sqlite3_step(result)) {
+    /*
+     * Fill the simple structure
+     */
+    simplestruct=&(container->simplefilter[count]);
+    rsststoresimplestruct(result, simplestruct);
+
+		count++;
+
+		/*
+		 * Reallocate goes here
+		 */
+		container->simplefilter = rsstmakespace(container->simplefilter, &allocrecords, count, sizeof(simplefilter_struct));
+	}
+
+	/*
+	 * Save number of records retrieved
+	 */
+	container->nr=count;
+
+	return 0;
+}
+
+
+/*
+ * Get simplefilter torrents
+ * @arguments
+ * simplefilter The container to store the simplefilter in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallsimplefilter(rsstor_handle *handle, simplefilter_container **simplefilter, int limit, int offset)
+{
+	int 					rc=0;
+	int 					retval=0;
+	sqlite3_stmt *ppstmt=NULL;
+	simplefilter_container *localitems=NULL;
+	char         *zErrMsg=NULL;
+	sqlite3      *db=NULL;
+
+	/*
+	 * handle
+	 */
+	db = handle->db;
+
+	/*
+	 * Query to retrieve simplefilter items
+	 */
+	const char *query =  "SELECT id, name, title, exclude, category, source, maxsize, minsize, nodup, fromseason, fromepisode "
+											 "FROM 'simplefilters' ORDER BY name LIMIT ?1 OFFSET ?2";
+
+	/*
+	 * Allocate the container
+	 */
+	localitems = calloc(1, sizeof(simplefilter_container));
+	if(localitems == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecqueryresult(db, &ppstmt, query, "dd", limit, offset);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "Rsstexecqueryresult failed %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Store result into container
+	 */
+	rc = rsststoresimplecontainer(ppstmt, localitems);
+
+	/*
+	 * Set output.
+	 */
+	*simplefilter = localitems;
+
+	/*
+	 * Done with query, finalizing.
+	 */
+	rc = sqlite3_finalize(ppstmt);
+	return retval;
+}
+
+
+/*
+ * Get simplefilter torrents
+ * @arguments
+ * simplefilter The container to store the simplefilter in
+ * id id of the simple filter
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetsimplefilterid(rsstor_handle *handle, simplefilter_struct **simplefilter, int id)
+{
+	int 					rc=0;
+	int 					retval=0;
+	sqlite3_stmt *ppstmt=NULL;
+	simplefilter_struct *localitem=NULL;
+	char         *zErrMsg=NULL;
+	sqlite3      *db=NULL;
+
+	/*
+	 * handle
+	 */
+	db = handle->db;
+
+	/*
+	 * Query to retrieve simplefilter items
+	 */
+	const char *query =  "SELECT id, name, title, exclude, category, source, maxsize, minsize, nodup, fromseason, fromepisode "
+											 "FROM 'simplefilters' WHERE id=?1";
+
+	/*
+	 * Allocate the container
+	 */
+	localitem = calloc(1, sizeof(simplefilter_struct));
+	if(localitem == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecqueryresult(db, &ppstmt, query, "d", id);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "Rsstexecqueryresult failed %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Store result into container
+   * Do one step before executing
+   */
+  if(SQLITE_DONE != sqlite3_step(ppstmt)) {
+
+    /*
+     * Set output.
+     */
+    rsststoresimplestruct(ppstmt, localitem);
+    *simplefilter = localitem;
+  } else {
+    *simplefilter = NULL;
+    retval=-1;
+  }
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppstmt);
+  return retval;
+}
+
+
+/*
+ * Get simplefilter torrents
+ * @arguments
+ * simplefilter The container to store the simplefilter in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetsimplefiltername(rsstor_handle *handle, simplefilter_container **simplefilter, char *name)
+{
+	int 					rc=0;
+	int 					retval=0;
+	sqlite3_stmt *ppstmt=NULL;
+	simplefilter_container *localitems=NULL;
+	char         *zErrMsg=NULL;
+	sqlite3      *db=NULL;
+
+	/*
+	 * handle
+	 */
+	db = handle->db;
+
+	/*
+	 * Query to retrieve simplefilter items
+	 */
+	const char *query =  "SELECT id, name, title, exclude, category, source, maxsize, minsize, nodup, fromseason, fromepisode "
+											 "FROM 'simplefilters' WHERE name=?1";
+
+	/*
+	 * Allocate the container
+	 */
+	localitems = calloc(1, sizeof(simplefilter_container));
+	if(localitems == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecqueryresult(db, &ppstmt, query, "s", name);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "Rsstexecqueryresult failed %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Store result into container
+	 */
+	rc = rsststoresimplecontainer(ppstmt, localitems);
+
+	/*
+	 * Set output.
+	 */
+	*simplefilter = localitems;
+
+	/*
+	 * Done with query, finalizing.
+	 */
+	rc = sqlite3_finalize(ppstmt);
+	return retval;
+}
+
+
+/*
+ * Free simplefilter structure
+ * @Arguments
+ * simplefilter pointer to simplefilter struct to be freed
+ */
+void rsstfreesimplefilter(simplefilter_struct *simplefilter)
+{
+	/*
+	 * Free all strings
+	 */
+	free(simplefilter->name);
+	free(simplefilter->title);
+	free(simplefilter->exclude);
+	free(simplefilter->category);
+	free(simplefilter->source);
+	free(simplefilter->nodup);
+}
+
+
+/*
+ * Delete content from source_container struct
+ * @Arguments
+ * container simplefilter container content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreesimplefiltercontainer(simplefilter_container *container)
+{
+	int count=0;
+
+	/*
+	 * Sanity checks
+	 */
+	if(container->simplefilter == NULL) {
+		return -1;
+	}
+
+	/*
+	 * Free config values structures in container
+	 */
+	for(count=0; count < container->nr; count++)
+	{
+		rsstfreesimplefilter(container->simplefilter+count);
+	}
+
+	/*
+	 * free the array itself
+	 */
+	free(container->simplefilter);
+	free(container);
+
+	return 0;
+}
+
+
+/*
+ * Store database result into struct
+ * @Arguments
+ * result
+ * container
+ * @returns
+ * 0 on success otherwise -1
+ */
+static int rsststoresourcecontainer(sqlite3_stmt *result, source_container *container)
+{
+	int 		count=0;
+	int 		allocrecords=0;
+	char 	 *column=NULL;
+
+	/*
+	 * reallocate for START_ELEMENTS number of records
+	 */
+	allocrecords = RSST_START_ELEMENTS;
+	container->source = calloc(allocrecords, sizeof(source_struct));
+	if(container->source == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * loop until the end of the dataset is found
+	 * Copy results to struct
+	 */
+	while( SQLITE_DONE != sqlite3_step(result)) {
+		/*
+		 * Store values
+		 * int   id;
+		 * char *name;
+		 * char *url;
+		 * char *parser;
+     * char *metatype;
+		 */
+		container->source[count].id = sqlite3_column_int(result, 0);
+		column = (char*) sqlite3_column_text(result, 1);
+		rsstalloccopy(&(container->source[count].name), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 2);
+		rsstalloccopy(&(container->source[count].url), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 3);
+		rsstalloccopy(&(container->source[count].parser), column, strlen(column));
+		column = (char*)sqlite3_column_text(result, 4);
+		rsstalloccopy(&(container->source[count].metatype), column, strlen(column));
+		count++;
+
+		/*
+		 * reallocate goes here
+		 */
+		container->source = rsstmakespace(container->source, &allocrecords, count, sizeof(source_struct));
+	}
+
+	/*
+	 * Save number of records retrieved
+	 */
+	container->nr=count;
+
+	return 0;
+}
+
+
+/*
+ * Get RSS-source by id
+ * @arguments
+ * handle RSS-torrent handle
+ * id source id to get
+ * source structure containing the retrieved struct
+ * @Return
+ * 0 when okay, -1 on error
+ */
+int rsstgetsource(rsstor_handle *handle, int id, source_struct **source)
+{
+  int            rc=0;
+  source_struct *sourcestr=NULL;
+	sqlite3_stmt  *ppstmt=NULL;
+	char 	        *column=NULL;
+	char          *zErrMsg=NULL;
+
+	/*
+	 * Query to retrieve source items
+	 */
+	const char *query = "SELECT id, name, url, parser, metatype FROM sources WHERE id=?1";
+
+	/*
+	 * Alloc the container
+	 */
+	sourcestr = calloc(1, sizeof(source_struct));
+	if(sourcestr == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecqueryresult(handle->db, &ppstmt, query, "d", id);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+  sqlite3_step(ppstmt);
+
+  /*
+   * Store retrieved data
+   */
+  sourcestr->id = sqlite3_column_int(ppstmt, 0);
+  column = (char*) sqlite3_column_text(ppstmt, 1);
+  rsstalloccopy(&(sourcestr->name), column, strlen(column));
+  column = (char*)sqlite3_column_text(ppstmt, 2);
+  rsstalloccopy(&(sourcestr->url), column, strlen(column));
+  column = (char*)sqlite3_column_text(ppstmt, 3);
+  rsstalloccopy(&(sourcestr->parser), column, strlen(column));
+  column = (char*)sqlite3_column_text(ppstmt, 4);
+  rsstalloccopy(&(sourcestr->metatype), column, strlen(column));
+
+  /*
+   * Set structure to be returned.
+   */
+  *source = sourcestr;
+
+  /*
+   * Clean up
+   */
+	rc = sqlite3_finalize(ppstmt);
+
+  return 0;
+}
+
+
+/*
+ * Get all RSS-sources
+ * @arguments
+ * sources The container to store the sources in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallsources(rsstor_handle *handle, source_container **sources)
+{
+	int 					rc=0;
+	int 					retval=0;
+	sqlite3_stmt *ppstmt=NULL;
+	source_container *localitems=NULL;
+	char         *zErrMsg=NULL;
+	sqlite3      *db=NULL;
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+	/*
+	 * Query to retrieve source items
+	 */
+	const char *query = "SELECT id, name, url, parser, metatype FROM sources ORDER BY name";
+
+	/*
+	 * Alloc the container
+	 */
+	localitems = calloc(1, sizeof(source_container));
+	if(localitems == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecqueryresult(db, &ppstmt, query, NULL);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Store result into container
+	 */
+	rc = rsststoresourcecontainer(ppstmt, localitems);
+
+	/*
+	 * Set output.
+	 */
+	*sources = localitems;
+
+	/*
+	 * Done with query, finalizing.
+	 */
+	rc = sqlite3_finalize(ppstmt);
+	return retval;
+}
+
+
+/*
+ * Free source structure
+ * @Arguments
+ * source pointer to source struct to be freed
+ */
+void rsstfreesource(source_struct *source)
+{
+	free(source->name);
+	free(source->url);
+	free(source->parser);
+  free(source->metatype);
+}
+
+
+/*
+ * Delete content from source_container struct
+ * @Arguments
+ * container sources container content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreesourcecontainer(source_container *container)
+{
+	int count=0;
+
+	/*
+	 * Sanity checks
+	 */
+	if(container->source == NULL) {
+		return -1;
+	}
+
+	/*
+	 * Free config values structures in container
+	 */
+	for(count=0; count < container->nr; count++)
+	{
+		rsstfreesource(container->source+count);
+	}
+
+	/*
+	 * free the array itself
+	 */
+	free(container->source);
+	free(container);
+
+	return 0;
+}
+
+/*
+ * Store newtorrent result into newtorrents_struct
+ * @arguments
+ * newtor newtorrents_struct
+ * result sqlstatement set to the current record to store
+ */
+void rsststorenewtorrentstruct(sqlite3_stmt *result, newtorrents_struct *newstruct)
+{
+  char 	 *column=NULL;
+
+  /*
+   * Store values
+   */
+  newstruct->id = sqlite3_column_int(result, 0);
+  column = (char*) sqlite3_column_text(result, 1);
+  rsstalloccopy(&(newstruct->title), column, strlen(column));
+  column = (char*)sqlite3_column_text(result, 2);
+  rsstalloccopy(&(newstruct->link), column, strlen(column));
+  newstruct->pubdate = sqlite3_column_int(result, 3);
+  column = (char*)sqlite3_column_text(result, 4);
+  rsstalloccopy(&(newstruct->category), column, strlen(column));
+  column = (char*)sqlite3_column_text(result, 5);
+  rsstalloccopy(&(newstruct->source), column, strlen(column));
+  column = (char*)sqlite3_column_text(result, 6);
+  rsstalloccopy(&(newstruct->metatype), column, strlen(column));
+  newstruct->season = sqlite3_column_int(result, 7);
+  newstruct->episode = sqlite3_column_int(result,8);
+  newstruct->seeds = sqlite3_column_int(result, 9);
+  newstruct->peers = sqlite3_column_int(result, 10);
+  newstruct->size = sqlite3_column_double(result, 11);
+}
+
+/*
+ * Store database result into struct
+ * @Arguments
+ * result
+ * container
+ * @returns
+ * 0 on success otherwise -1
+ */
+int rsststorenewtorrentcontainer(sqlite3_stmt *result, newtorrents_container *container)
+{
+	int 		count=0;
+	int 		allocrecords=0;
+
+	/*
+	 * reallocate for START_ELEMENTS number of records
+	 */
+	allocrecords = RSST_START_ELEMENTS;
+	container->newtorrent = calloc(allocrecords, sizeof(newtorrents_struct));
+	if(container->newtorrent == NULL) {
+		rsstwritelog(LOG_ERROR, "Calloc failed ! %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * loop until the end of the dataset is found
+	 * Copy results to struct
+	 */
+	while( SQLITE_DONE != sqlite3_step(result)) {
+    /*
+     * Fill struct
+     */
+    rsststorenewtorrentstruct(result, &(container->newtorrent[count]));
+
+		/*
+		 * Move to next record & reallocate
+		 */
+		count++;
+		container->newtorrent = rsstmakespace(container->newtorrent, &allocrecords, count, sizeof(newtorrents_struct));
+	}
+
+	/*
+	 * Save number of records retrieved
+	 */
+	container->nr=count;
+
+	return 0;
+}
+
+/*
+ * Find newtorrents entries
+ * @Arguments
+ * filter simplefilterstruct to filter out the newtorrent entries we want
+ * newtorrents container handling newtorrents entries
+ * limit is the amount of rows we want to retrieve
+ * offset is the amount of rows we want to skip at the start
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfindnewtorrents(simplefilter_struct *filter, newtorrents_container **newtorrents, int limit, int offset)
+{
+	int 					 rc=0;
+	sandboxdb 		*sandbox=NULL;
+	sqlite3_stmt 	*ppstmt=NULL;
+	char         	*zErrMsg=NULL;
+	rsstor_handle  handle;
+
+	/*
+	 * init handle;
+	 */
+	memset(&handle, 0, sizeof(rsstor_handle));
+
+	/*
+	 * Query to retrieve the data from the sandbox after all the work is done.
+	 */
+	char *query="SELECT newtorrents.id, downloaded.title, newtorrents.link, newtorrents.pubdate, newtorrents.category, "
+		"newtorrents.source, downloaded.metatype, downloaded.season, downloaded.episode, newtorrents.seeds, "
+    "newtorrents.peers, newtorrents.size "
+    "FROM newtorrents, downloaded "
+		"WHERE newtorrents.link = downloaded.link "
+    "ORDER BY newtorrents.id LIMIT ?1 OFFSET ?2"; // get values from downloaded table
+
+	/*
+	 * Create sandbox
+	 */
+	sandbox = rsstinitfiltertest();
+	if(sandbox == NULL){
+		rsstwritelog(LOG_ERROR, "Sandbox creation failed %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Dirty but needed
+	 */
+	handle.db=sandbox->db;
+
+	/*
+	 * Remove unwanted data from sandbox.
+	 */
+	rc = rsstcleanoutdb(sandbox);
+	if(rc != 0){
+		rsstwritelog(LOG_ERROR, "Cleaning out sandbox failed %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Add simple filter
+	 */
+	rc = rsstinsertsimplefilter(&handle, filter);
+	if(rc != 0){
+		rsstwritelog(LOG_ERROR, "Inserting simple filter failed %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Execute filter
+	 * with simulate 1, to run the simplefilters only in the database.
+	 */
+	rc = rsstdownloadsimple(&handle, (SIM) sim);
+	if(rc != 0){
+		rsstwritelog(LOG_ERROR, "Executing filter failed %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Get records using query
+	 */
+	rc = rsstexecqueryresult(sandbox->db, &ppstmt, query, "dd", limit, offset);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Allocate and fill container
+	 */
+	*newtorrents = calloc(1, sizeof(newtorrents_container));
+	rc = rsststorenewtorrentcontainer(ppstmt, *newtorrents);
+	if(rc != 0){
+		rsstwritelog(LOG_ERROR, "Storing in newtor failed %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Done with Sqlite result set
+	 */
+	sqlite3_finalize(ppstmt);
+
+	/*
+	 * Close sandbox
+	 */
+	rc = rsstclosesandbox(sandbox);
+	if(rc != 0){
+		printf("Closing sandbox failed.\n");
+		rsstwritelog(LOG_ERROR, "Closing sandbox failed %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Get newtorrent information providing its ID
+ * @Arguments
+ * handle Swarmtv Handle
+ * id id number of torrent to retrieve
+ * newtorrent structure holding information
+ * @Return
+ * Returns 0 when found, -1 on not found or error
+ */
+int rsstnewtorrentsbyid(rsstor_handle *handle, int newtorid, newtorrents_struct *newtorrent)
+{
+  int            rc=0;
+	sqlite3_stmt 	*ppstmt=NULL;
+	char         	*zErrMsg=NULL;
+
+  /*
+   * Query To filter newtorrents on filter.
+   */
+	char *query="SELECT newtorrents.id, newtorrents.title, newtorrents.link, strftime('%s', newtorrents.pubdate), newtorrents.category, "
+		"newtorrents.source, newtorrents.metatype, newtorrents.season, newtorrents.episode, newtorrents.seeds, "
+    "newtorrents.peers, newtorrents.size "
+    "FROM newtorrents "
+		"WHERE newtorrents.id = ?1";
+
+	/*
+	 * Get records using query
+	 */
+	rc = rsstexecqueryresult(handle->db, &ppstmt, query, "d", newtorid);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+  /*
+   * Did we find anything ?
+   */
+	if( SQLITE_DONE == sqlite3_step(ppstmt)) {
+		rsstwritelog(LOG_ERROR, "No records found for id: %d %s:%d", newtorid, __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Store result in newtorrents struct
+   */
+  rsststorenewtorrentstruct(ppstmt, newtorrent);
+
+  /*
+   * Clean up
+   */
+	sqlite3_finalize(ppstmt);
+
+  return 0;
+}
+
+
+/*
+ * Find newtorrents entries
+ * @Arguments
+ * handle SwarmTv Handle
+ * title title to match to
+ * newtorrents container handling newtorrents entries
+ * limit is the amount of rows we want to retrieve
+ * offset is the amount of rows we want to skip at the start
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfindnewtorrentsbytitle(rsstor_handle *handle, char *title, newtorrents_container **newtorrents, int limit, int offset)
+{
+  int            rc=0;
+	sqlite3_stmt 	*ppstmt=NULL;
+	char         	*zErrMsg=NULL;
+
+  /*
+   * Query To filter newtorrents on filter.
+   */
+	char *query="SELECT newtorrents.id, newtorrents.title, newtorrents.link, newtorrents.pubdate, newtorrents.category, "
+		"newtorrents.source, newtorrents.metatype, newtorrents.season, newtorrents.episode, newtorrents.seeds, "
+    "newtorrents.peers, newtorrents.size "
+    "FROM newtorrents "
+		"WHERE IREGEXP(?1, newtorrents.title) "
+    "ORDER BY newtorrents.id DESC LIMIT ?2 OFFSET ?3"; // get values from downloaded table
+
+	/*
+	 * Get records using query
+	 */
+	rc = rsstexecqueryresult(handle->db, &ppstmt, query, "sdd", title, limit, offset);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		return -1;
+	}
+
+	/*
+	 * Allocate and fill container
+	 */
+	*newtorrents = calloc(1, sizeof(newtorrents_container));
+	rc = rsststorenewtorrentcontainer(ppstmt, *newtorrents);
+	if(rc != 0){
+		rsstwritelog(LOG_ERROR, "Storing in newtor failed %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Done with Sqlite result set
+	 */
+	sqlite3_finalize(ppstmt);
+
+  return 0;
+}
+
+
+/*
+ * Delete content from newtorrents_container
+ * @Arguments
+ * container newtorrents container the content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreenewtorrentscontainer(newtorrents_container *container)
+{
+	int count=0;
+
+	/*
+	 * Sanity checks
+	 */
+	if(container == NULL || container->newtorrent == NULL) {
+		return -1;
+	}
+
+	/*
+	 * Free config values structures in container
+	 */
+	for(count=0; count < container->nr; count++)
+	{
+		rsstfreenewtor(container->newtorrent + count);
+	}
+
+	/*
+	 * free the array itself
+	 */
+	free(container->newtorrent);
+
+	/*
+	 * NULL all pointers.
+	 */
+	memset(container, 0, sizeof(source_container));
+
+	return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/databaseimpl.h b/tags/swarmtv-0.9.2/libswarmtv/databaseimpl.h
new file mode 100644
index 0000000..0b320fd
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/databaseimpl.h
@@ -0,0 +1,246 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Database version.
+ * When the current version does not match the version in the version field
+ * The database is recreated
+ */
+#define RSST_DB_VERSION 4
+
+/*
+ * path to database file.
+ */
+#define  RSST_DBFILE "~/.swarmtv/swarm.db"
+
+/*
+ * Run the Database init script.
+ * @return
+ * 0 on succes, -1 on failure
+ */
+int rsstrundbinitscript(rsstor_handle *handle);
+
+/*
+ * Open database, and add regexp functionality.
+ * @Arguments
+ * filename Filename of database to open
+ * handle RSS-torrent handle
+ * @returns
+ * returns SQLITE_OK when all did go well.
+ */
+int rsstinitdatabase(const char *filename, rsstor_handle *handle);
+
+/*
+ * Get all config settings
+ * @Arguments
+ * configitems The container to store the configitems in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallconfig(rsstor_handle *handle, config_container **configitems);
+
+/*
+ * Delete content from config_container struct
+ * @Arguments
+ * container Pointer to configcontainer to free content of
+ * @Return
+ * 0 on success, -1 on failure
+ */
+int rsstfreeconfigcontainer(config_container *container);
+
+/*
+ * Delete content from config_container struct
+ * @Arguments
+ * container Pointer to configcontainer to free content of
+ * @Return
+ * 0 on success, -1 on failure
+ */
+int rsstfreefiltercontainer(filter_container *container);
+
+/*
+ * Get all SQL filter settings
+ * @Arguments
+ * handle RSS-torrent handle
+ * container The container to store the SQL filters in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallfilter(rsstor_handle *handle, filter_container **filteritem);
+
+/*
+ * Get all SQL filter settings
+ * @Arguments
+ * handle RSS-torrent handle
+ * container The container to store the container in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetfilterbyname(rsstor_handle *handle, char *name, filter_container **container);
+
+/*
+ * Get downloaded torrents
+ * @arguments
+ * downloaded The container to store the downloaded in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetdownloaded(rsstor_handle *handle, downloaded_container **downloaded, int limit, int offset);
+
+/*
+ * Free downloaded structure
+ * @Arguments
+ * downloaded pointer to downloaded struct to be freed
+ */
+void rsstfreedownloaded(downloaded_struct *downloaded);
+
+/*
+ * Free source structure
+ * @Arguments
+ * source pointer to source struct to be freed
+ */
+void rsstfreesource(source_struct *source);
+
+/*
+ * Delete content from source_container struct
+ * @Arguments
+ * container downloaded container content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreedownloadedcontainer(downloaded_container *container);
+
+/*
+ * Get simplefilter torrents
+ * @arguments
+ * simplefilter The container to store the simplefilter in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallsimplefilter(rsstor_handle *handle, simplefilter_container **simplefilter, int limit, int offset);
+
+/*
+ * Get simplefilter torrents
+ * @arguments
+ * simplefilter The container to store the simplefilter in
+ * name name of the simple filter
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetsimplefiltername(rsstor_handle *handle, simplefilter_container **simplefilter, char *name);
+
+/*
+ * Get simplefilter torrents
+ * @arguments
+ * simplefilter The container to store the simplefilter in
+ * id id of the simple filter
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetsimplefilterid(rsstor_handle *handle, simplefilter_struct **simplefilter, int id);
+
+/*
+ * Free simplefilter structure
+ * @Arguments
+ * simplefilter pointer to simplefilter struct to be freeed
+ */
+void rsstfreesimplefilter(simplefilter_struct *simplefilter);
+
+/*
+ * Delete content from source_container struct
+ * @Arguments
+ * container simplefilter container content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreesimplefiltercontainer(simplefilter_container *container);
+
+/*
+ * Get all RSS-sources
+ * @arguments
+ * sources The container to store the sources in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallsources(rsstor_handle *handle, source_container **sources);
+
+/*
+ * Delete content from source_container struct
+ * @Arguments
+ * container sources container content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreesourcecontainer(source_container *sources);
+
+/*
+ * Store database result into struct
+ * @Arguments
+ * result
+ * container
+ * @returns
+ * 0 on success otherwise -1
+ */
+int rsststorenewtorrentcontainer(sqlite3_stmt *result, newtorrents_container *container);
+
+/*
+ * Find newtorrents entries
+ * @Arguments
+ * filter simplefilterstruct to filter out the newtorrent entries we want
+ * newtorrents container handling newtorrents entries
+ * limit is the amount of rows we want to retrieve
+ * offset is the amount of rows we want to skip at the start
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfindnewtorrents(simplefilter_struct *filter, newtorrents_container **newtorrents, int limit, int offset);
+
+/*
+ * Get newtorrent information providing its ID
+ * @Arguments
+ * handle Swarmtv Handle
+ * newtorid id number of torrent to retrieve
+ * newtorrent structure holding information
+ * @Return
+ * Returns 0 when found, -1 on not found or error
+ */
+int rsstnewtorrentsbyid(rsstor_handle *handle, int newtorid, newtorrents_struct *newtorrent);
+
+/*
+ * Find newtorrents entries
+ * @Arguments
+ * handle SwarmTv Handle
+ * title title to match to
+ * newtorrents container handling newtorrents entries
+ * limit is the amount of rows we want to retrieve
+ * offset is the amount of rows we want to skip at the start
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfindnewtorrentsbytitle(rsstor_handle *handle, char *title, newtorrents_container **newtorrents, int limit, int offset);
+
+/*
+ * Delete content from newtorrents_container
+ * @Arguments
+ * container newtorrents container the content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreenewtorrentscontainer(newtorrents_container *newtorrents);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/CMakeLists.txt b/tags/swarmtv-0.9.2/libswarmtv/filehandler/CMakeLists.txt
new file mode 100644
index 0000000..b0e9f0b
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/CMakeLists.txt
@@ -0,0 +1,10 @@
+# The plugins should be inserted here.
+# When adding parsers here, make sure to add the parser in parser.c to.
+SET(FILEHANDLE_PATH filehandler)
+
+SET(LIBSRC ${LIBSRC}
+  ${FILEHANDLE_PATH}/filehandler
+)
+
+INCLUDE(filehandler/torrent/CMakeLists.txt)
+INCLUDE(filehandler/nzb/CMakeLists.txt)
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/filehandler.c b/tags/swarmtv-0.9.2/libswarmtv/filehandler/filehandler.c
new file mode 100644
index 0000000..fec1c51
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/filehandler.c
@@ -0,0 +1,213 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __MINGW32__
+#include "../types.h"  /* looks stupid! */
+#else
+#include "types.h"
+#endif
+#include "regexp.h"
+#include "curlfile.h"
+#include "filehandler.h"
+#include "torrent/findtorrent.h"
+#include "torrent/torrentparse.h"
+#include "nzb/findnzb.h"
+#include "nzb/nzbparse.h"
+
+/*
+ * char array holding the types of metafiles supported by librsstorrent
+ */
+char *supported_metatypes[] ={
+  "torrent",
+  "nzb",
+  NULL
+};
+
+/*
+ * Get supported meta file types
+ * @return
+ * Returns a pointer to the names of the supported meta types.
+ */
+char **getsupportedmetatypes()
+{
+  return supported_metatypes;
+}
+
+/*
+ * Convert string into METAFILETYPE
+ * @arguments
+ * metastr META file string
+ * metatype metafile output string
+ * @return
+ * 0 on success, -1 when not match is found.
+ */
+int metafilestrtotype(char *metastr, METAFILETYPE *type)
+{
+  int retval=0;
+
+  if(!strcmp(metastr, "torrent")) {
+    *type=torrent;
+  }
+  else if(!strcmp(metastr, "nzb")) {
+    *type=nzb;
+  }
+  else {
+    *type=undefined;
+    retval=-1;
+  }
+
+  return retval;
+}
+
+
+/*
+ * Provide the URL to the NZB,
+ * returns a structure containing some of the props of the NZB.
+ * free structure afterwards
+ * @arguments
+ * url URL to get NZB from
+ * props structure holding the NZB properties
+ * @return
+ * returns -1 on failure to parse URL, otherwise 0 is returned.
+ */
+int rsstgetmetafileinfo(rsstor_handle *handle, METAFILETYPE type, char *url, metafileprops **props)
+{
+  int rc=0;
+
+  /*
+   * Switch between the 2 meta file types.
+   */
+  switch(type){
+    case torrent:
+      rc = rsstgettorrentinfo(handle, url, props);
+      break;
+    case nzb:
+      rc = rsstgetnzbinfo(handle, url, props);
+      break;
+    case undefined:
+      /*
+       * When this happens, just fail
+       */
+      rsstwritelog(LOG_ERROR, "'url' requested metafile info without valid meta file type %s:%d",
+        url, __FILE__, __LINE__);
+      *props=NULL;
+      rc=-1;
+      break;
+  }
+
+  return rc;
+}
+
+
+/*
+ * Free torrentprop structure.
+ * @arguments
+ * props structure to be freed
+ */
+void rsstfreemetafileprops(metafileprops *props)
+{
+  /*
+   * For now just free the structure.
+   */
+  free(props);
+}
+
+
+/*
+ * This is a recursive function.
+ * It scans for torrent files, and will return the first one it encounteres.
+ * Note this might not be the correct torrent at all :)
+ * A counter prevents the recursing from getting out of hand.
+ * The torrent wil be contained in torbuffer.
+ * The url the torrent was found in torrenturl.
+ * Don't forget to free buffer and torrenturl !
+ * @arguments
+ * url the url to start searching.
+ * torrenturl the url found containing the torrent.
+ * torbuffer the buffer the torrent is returned in when found.
+ * recurse the number of recursions to do to find the torrent.
+ * @return
+ * 0 when nothing is found
+ * 1 when the torrent was found
+ */
+int rsstfindmetafile(rsstor_handle *handle, METAFILETYPE type, char *url, char **torrenturl, MemoryStruct **torbuffer, int recurse)
+{
+  int rc=0;
+
+  switch(type){
+    case torrent:
+      rc = rsstfindtorrent(handle, url, torrenturl, torbuffer, recurse);
+      break;
+    case nzb:
+      rc = rsstfindnzb(handle, url, torrenturl, torbuffer);
+      break;
+    case undefined:
+      /*
+       * When this happens, just fail
+       */
+      rsstwritelog(LOG_ERROR, "'url' requested metafile info without valid meta file type %s:%d",
+        url, __FILE__, __LINE__);
+      *torrenturl=NULL;
+      *torbuffer=NULL;
+      rc=-1;
+      break;
+  }
+
+  return rc;
+}
+
+
+/*
+ * Finds and writes torrent to file
+ * @arguments
+ * url the url to start looking for a torrent.
+ * name the path to store the torrent on disk.
+ * @return
+ * 0 on success
+ * -1 when torrent was not found or could not be stored.
+ */
+int rsstfindmetafilewrite(rsstor_handle *handle, METAFILETYPE type, char *url, char *name, char *filtername)
+{
+  int rc=0;
+
+  switch(type){
+    case torrent:
+      rc = rsstfindtorrentwrite(handle, url, name, filtername);
+      break;
+    case nzb:
+      rc = rsstfindnzbwrite(handle, url, name, filtername);
+      break;
+    case undefined:
+      /*
+       * When this happens, just fail
+       */
+      rsstwritelog(LOG_ERROR, "'url' requested metafile info without valid meta file type %s:%d",
+        url, __FILE__, __LINE__);
+      rc=-1;
+      break;
+  }
+
+  return rc;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/filehandler.h b/tags/swarmtv-0.9.2/libswarmtv/filehandler/filehandler.h
new file mode 100644
index 0000000..5adfda3
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/filehandler.h
@@ -0,0 +1,89 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#ifndef FILEHANDLER
+#define FILEHANDLER
+
+
+/*
+ * Get supported meta file types
+ */
+char **getsupportedmetatypes();
+
+/*
+ * Provide the URL to the NZB,
+ * returns a structure containing some of the props of the NZB.
+ * free structure afterwards
+ * @arguments
+ * url URL to get NZB from
+ * props structure holding the NZB properties
+ * @return
+ * returns -1 on failure to parse URL, otherwise 0 is returned.
+ */
+int rsstgetmetafileinfo(rsstor_handle *handle, METAFILETYPE type, char *url, metafileprops **props);
+
+/*
+ * Free torrentprop structure.
+ * @arguments
+ * props structure to be freed
+ */
+void rsstfreemetafileprops(metafileprops *props);
+
+/*
+ * This is a recursive function.
+ * It scans for torrent files, and will return the first one it encounteres.
+ * Note this might not be the correct torrent at all :)
+ * A counter prevents the recursing from getting out of hand.
+ * The torrent wil be contained in torbuffer.
+ * The url the torrent was found in torrenturl.
+ * Don't forget to free buffer and torrenturl !
+ * @arguments
+ * url the url to start searching.
+ * torrenturl the url found containing the torrent.
+ * torbuffer the buffer the torrent is returned in when found.
+ * recurse the number of recursions to do to find the torrent.
+ * @return
+ * 0 when nothing is found
+ * 1 when the torrent was found
+ */
+int rsstfindmetafile(rsstor_handle *handle, METAFILETYPE type, char *url, char **torrenturl, MemoryStruct **torbuffer, int recurse);
+
+/*
+ * Finds and writes torrent to file
+ * @arguments
+ * url the url to start looking for a torrent.
+ * name the path to store the torrent on disk.
+ * @return
+ * 0 on success
+ * -1 when torrent was not found or could not be stored.
+ */
+int rsstfindmetafilewrite(rsstor_handle *handle, METAFILETYPE type, char *url, char *name, char *filtername);
+
+/*
+ * Convert string into METAFILETYPE
+ * @arguments
+ * metastr META file string
+ * metatype metafile output string
+ * @return
+ * 0 on success, -1 when not match is found.
+ */
+int metafilestrtotype(char *metastr, METAFILETYPE *type);
+
+#endif
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/CMakeLists.txt b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/CMakeLists.txt
new file mode 100644
index 0000000..01ed2c4
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/CMakeLists.txt
@@ -0,0 +1,7 @@
+SET(TORRENT_PATH filehandler/nzb)
+
+SET(LIBSRC ${LIBSRC}
+    ${TORRENT_PATH}/findnzb
+		${TORRENT_PATH}/nzbparse)
+
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/findnzb.c b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/findnzb.c
new file mode 100644
index 0000000..0a24915
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/findnzb.c
@@ -0,0 +1,301 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "regexp.h"
+#include "curlfile.h"
+#include "logfile.h"
+#include "nzbparse.h"
+#include "findnzb.h"
+
+
+/*
+ * Test if the downloaded file really is an NZB
+ * @arguments
+ * @return
+ * -1 when not an NZB
+ * 0 when the file is and NZB
+ */
+static int testifnzb(xmlNode *root)
+{
+  char *doctype=NULL;
+  //int  rc=0;
+
+  /*
+   * Sanity checks
+   */
+  if(root == NULL || root->name == NULL)
+  {
+    /*
+     * No XML structure is no NZB :)
+     */
+    rsstwritelog(LOG_ERROR, "Document pointed not sane! %s:%d\n", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Retrieve the DOCTYPE
+   */
+  doctype = (char*) root->name;
+
+  /*
+   * Test if the doctype is 'nzb'
+   */
+  if(strcmp(doctype, "nzb") != 0) {
+    /*
+     * Not an NZB
+     */
+    rsstwritelog(LOG_DEBUG, "Doctype not NZB: '%s' %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * We found an NZB
+   */
+  return 0;
+}
+
+/*
+ * Parse XML Document from buffer
+ * @arguments
+ * url  The URL that gets included in the document as the source
+ * buffer The buffer containing the (hopefully) XML-data
+ * doc Do
+ * root_element
+ * @return
+ *
+ */
+int rsstparsebufxml(char *url, MemoryStruct *buffer, xmlNode **root_element)
+{
+  xmlDocPtr doc=NULL;
+
+  /*
+   * Read from memory
+   */
+  doc = xmlReadMemory(buffer->memory, buffer->size, url, NULL, 0);
+  if (doc == NULL) {
+    rsstwritelog(LOG_ERROR, "Failed to parse RSS document: '%s' %s:%d", url, __FILE__, __LINE__);
+    *root_element=NULL;
+    return -1;
+  }
+  *root_element = xmlDocGetRootElement(doc);
+
+  /*
+   * All gone well
+   */
+  return 0;
+}
+
+/*
+ * This is a recursive function.
+ * It scans for NZB files, and will return the first one it encounters.
+ * Note this might not be the correct NZB at all :)
+ * A counter prevents the recursing from getting out of hand.
+ * The NZB will be contained in nzbbuffer.
+ * The URL the NZB was found in NZB URL.
+ * Don't forget to free buffer and NZB URL !
+ * @arguments
+ * url the URL to start searching.
+ * nzburl the URL found containing the NZB.
+ * nzbbuffer the buffer the NZB is returned in when found.
+ * recurse the number of recursions to do to find the NZB.
+ * @return
+ * -1 when nothing was found
+ * 0 when the NZB is found
+ */
+int rsstfindnzb(rsstor_handle *handle, char *url, char **nzburl, MemoryStruct **nzbbuffer)
+{
+  int          rc=0;
+  xmlNode     *root=NULL;
+  MemoryStruct buffer;
+  int          doctype=0;
+  int          retval=0;
+
+  /*
+   * Initialize stuff
+   */
+  memset(&buffer, 0, sizeof(MemoryStruct));
+
+  /*
+   * Download URL into buffer.
+   */
+  rc = rsstdownloadtobuffer(handle, url, &buffer);
+  if(rc != 0) {
+    rsstwritelog(LOG_NORMAL,  "%s: Failed to download.", url);
+	  rsstfreedownload(&buffer);
+    return 0;
+  }
+
+  /*
+   * Parse into XML-document
+   */
+  rc = rsstparsebufxml(url, &buffer, &root);
+
+  /*
+   * Get document type
+   */
+  doctype = testifnzb(root);
+
+  /*
+   * When the type is NZB, copy the URL and return 0
+   */
+  if(doctype == 0){
+    /*
+     * Set URL to current URL
+     */
+    rsstalloccopy(nzburl, url, strlen(url));
+
+    /*
+     * Set output buffer
+     */
+    rsstalloccopy((void*)nzbbuffer, (void*) &buffer, sizeof(MemoryStruct));
+
+  } else {
+    rsstwritelog(LOG_NORMAL, "Document not an NZB file, URL: '%s' %s:%d\n", url, __FILE__, __LINE__);
+    retval = -1;
+  }
+
+  /*
+   * make sure we clean up
+   * If not give up for now and return -1 (not found)
+   */
+  if(root != NULL) {
+    xmlFreeDoc(root->doc);
+  }
+
+  return retval;
+}
+
+
+/*
+ * Set up handlers structure and call torrent handler (When available)
+ */
+static int rsstcallnzbhandle(rsstor_handle *handle, char *torurl, char *name, char *filtername, MemoryStruct *buffer)
+{
+  int retval=0;
+  struct_downedmetafile nzb;
+
+  /*
+   * Setup the callback structure
+   */
+  memset(&nzb, 0, sizeof(struct_downedmetafile));
+  nzb.name = name;
+  nzb.filtername = filtername;
+  nzb.metatype = "torrent";
+  nzb.url = torurl;
+  if(buffer != NULL) {
+    nzb.metadata = buffer->memory;
+    nzb.metasize = buffer->size;
+  } else {
+    rsstwritelog(LOG_ERROR, "No torrent-content for '%s' %s:%d", torurl, __FILE__, __LINE__);
+  }
+
+  /*
+   * Call the handler
+   */
+  retval = rsstexecallbacks(handle, handlenzbfile, &nzb);
+
+  /*
+   * Return the handler return code
+   */
+  return retval;
+}
+
+
+/*
+ * Finds and writes NZB to file
+ * @arguments
+ * url the URL to start looking for a NZB.
+ * name the path to store the NZB on disk.
+ * @return
+ * 0 on success
+ * -1 when NZB was not found or could not be stored.
+ */
+int rsstfindnzbwrite(rsstor_handle *handle, char *url, char *name, char *filtername)
+{
+  int             rc = 0;
+  int             rv = 0;
+  char            *nzburl = NULL;
+  MemoryStruct    *buffer = NULL;
+
+  rsstwritelog(LOG_DEBUG, "Attempting Writing nzb '%s' to file '%s'", url, name);
+
+  /*
+   * Get the buffer and URL to the torrent in there
+   */
+  rc = rsstfindnzb(handle, url, &nzburl, &buffer);
+  if(rc != 0) {
+    rsstwritelog(LOG_NORMAL, "NZB not found in '%s'", url);
+    rv=-1;
+  }
+
+  /*
+   * Print to result
+   */
+  if(rv == 0 && strcmp(url, nzburl) != 0) {
+    rsstwritelog(LOG_NORMAL, "Original URL : %s", url);
+    rsstwritelog(LOG_NORMAL, "NZB URL   : %s", nzburl);
+  }
+
+  /*
+   * Call the front end handler, when this does not provide a
+   * stop_processing back, continue.
+   */
+  rc = rsstcallnzbhandle(handle, nzburl, name, filtername, buffer);
+  if(rc == stop_processing) {
+    // When the callback has done the handling do no more
+    rsstwritelog(LOG_NORMAL, "Callback handled nzb download '%s'.", name);
+    rv=-1;
+  }
+
+  /*
+   * Save file to name
+   */
+  if(rv == 0) {
+    rc = rsstwritebuffer(name, buffer);
+    if(rc != 0){
+      rsstwritelog(LOG_ERROR, "Writing NZB '%s' failed.", name);
+      rv = -1;
+    }
+  }
+
+  /*
+   * free the result
+   */
+  free(nzburl);
+  rsstfreedownload(buffer);
+  free(buffer);
+
+  return rv;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/findnzb.h b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/findnzb.h
new file mode 100644
index 0000000..6b88043
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/findnzb.h
@@ -0,0 +1,55 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#ifndef FINDNZB
+#define FINDNZB
+
+/*
+ * This is a recursive function.
+ * It scans for NZB files, and will return the first one it encounters.
+ * Note this might not be the correct NZB at all :)
+ * A counter prevents the recursing from getting out of hand.
+ * The NZB will be contained in nzbbuffer.
+ * The URL the NZB was found in NZB URL.
+ * Don't forget to free buffer and NZB URL !
+ * @arguments
+ * url the URL to start searching.
+ * nzburl the URL found containing the NZB.
+ * nzbbuffer the buffer the NZB is returned in when found.
+ * recurse the number of recursions to do to find the NZB.
+ * @return
+ * 0 when nothing is found
+ * 1 when the NZB was found
+ */
+int rsstfindnzb(rsstor_handle *handle, char *url, char **nzburl, MemoryStruct **nzbbuffer);
+
+/*
+ * Finds and writes NZB to file
+ * @arguments
+ * url the URL to start looking for a NZB.
+ * name the path to store the NZB on disk.
+ * @return
+ * 0 on success
+ * -1 when NZB was not found or could not be stored.
+ */
+int rsstfindnzbwrite(rsstor_handle *handle, char *url, char *name, char *filtername);
+
+#endif
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/nzbparse.c b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/nzbparse.c
new file mode 100644
index 0000000..bda3ef8
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/nzbparse.c
@@ -0,0 +1,287 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "regexp.h"
+#include "curlfile.h"
+#include "findnzb.h"
+#include "nzbparse.h"
+
+/*
+ * Get Document type
+ * @Arguments
+ * doc the XML-tree to get the doctype from
+ * @return
+ * pointer to the string, NULL if error
+ */
+char *getdocumenttype(xmlDocPtr doc)
+{
+  char *doctype=NULL;
+
+  /*
+   * Sanity checks
+   */
+  if(doc == NULL || doc->children == NULL){
+    return NULL;
+  }
+
+  /*
+   * Get name of main node in the XML-document
+   */
+  doctype = (char*) doc->children->name;
+
+  return doctype;
+}
+
+
+
+
+/*
+ * This function parses the XML data in the MemoryStruct
+ * @arguments
+ * chuck the memory structure containing the downloaded information.
+ * doc XML document DOM tree
+ * @return
+ * 0 on success -1 on failure
+ */
+static int parsefrommem(char *url, MemoryStruct *chunk, xmlDocPtr *doc)
+{
+  /*
+   * Sanity check
+   */
+  if(chunk == NULL) {
+    rsstwritelog(LOG_DEBUG, "NULL pointer provided as chunk pointer. %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Parse document in memory, using url as docbase RFC 2396,
+   */
+  *doc = xmlReadMemory(chunk->memory, chunk->size, url, NULL, 0);
+  if (*doc == NULL) {
+    rsstwritelog(LOG_DEBUG, "Failed to parse document %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  return 0;
+}
+
+
+/*
+ * Find desired attribute, and return value contained within attribute
+ * @Arguments
+ * attr  Pointer to first attribute
+ * label Attribute label
+ * value value contained in the Attribute
+ * @Return
+ * returns 0 if all okay, otherwise -1
+ */
+static int getattributeval(xmlAttrPtr attr, char *label, char **value)
+{
+    if(attr == NULL) {
+      return -1;
+    }
+
+    /*
+     * Find the value
+     */
+    while(attr != NULL) {
+      if(!strcmp((char*)attr->name, label)) {
+        *value = (char*) attr->children->content;
+        return 0;
+      }
+      attr = attr->next;
+    }
+
+    /*
+     * Nothing found in the attr collection.
+     */
+    return -1;
+}
+
+
+/*
+ * Get total size from nzb
+ * @arguments
+ * doc libxml2 document pointer
+ * @ return
+ * 0 on success otherwise -1
+ */
+static int getnzbsize(xmlDocPtr doc, size_t *nzbsize, size_t *piece_nr)
+{
+  xmlXPathContextPtr xpathCtx=NULL;
+  xmlXPathObjectPtr xpathObj=NULL;
+  char *sizestr=NULL;
+  size_t cumulative=0;
+  int count=0;
+  xmlAttrPtr attr=NULL;
+  int rc=0;
+
+  /*
+   * XPath to get the segment nodes despite of the namespace involved.
+   */
+  char *sizesxpath="//*[local-name()='segment'][@bytes]";
+
+  /* Create Xpath evaluation context */
+  xpathCtx = xmlXPathNewContext(doc);
+  if(xpathCtx == NULL) {
+    fprintf(stderr,"Error: unable to create new XPath context\n");
+    return(-1);
+  }
+
+  /*
+   * Query all size objects
+   */
+  xpathObj = xmlXPathEvalExpression(BAD_CAST sizesxpath, xpathCtx);
+  if(xpathObj == NULL) {
+    fprintf(stderr,"Error: unable to evaluate Xpath expression \"%s\"\n", sizesxpath);
+    xmlXPathFreeContext(xpathCtx);
+    return(-1);
+  }
+
+  /*
+   * Add all sizes together
+   */
+  for (count=0; count < xpathObj->nodesetval->nodeNr; count++) {
+    attr = xpathObj->nodesetval->nodeTab[count]->properties;
+    rc = getattributeval(attr, "bytes", &sizestr);
+    if(rc == 0) {
+      //printf("keyword: %s\n", sizestr);
+      cumulative += atoi(sizestr);
+    }
+  }
+
+  /*
+   * store the value
+   */
+  *nzbsize = cumulative;
+  *piece_nr = xpathObj->nodesetval->nodeNr;
+
+  /*
+   * cleanup
+   */
+  xmlXPathFreeObject(xpathObj);
+  xmlXPathFreeContext(xpathCtx);
+
+  return 0;
+}
+
+
+/*
+ * Provide the URL to the NZB,
+ * returns a structure containing some of the props of the NZB.
+ * free structure afterwards
+ * @arguments
+ * url URL to get NZB from
+ * props structure holding the NZB properties
+ * @return
+ * returns -1 on failure to parse URL, otherwise 0 is returned.
+ */
+int rsstgetnzbinfo(rsstor_handle *handle, char *url, metafileprops **props)
+{
+  int            rc=0;
+  int            retval=0;
+  char          *nzburl=NULL;
+  MemoryStruct  *nzbbuffer=NULL;
+  xmlDocPtr      doc=NULL;
+
+  /*
+   * Initialize
+   */
+  *props=NULL;
+
+  /*
+   * Download data
+   */
+  rc = rsstfindnzb(handle, url, &nzburl, &nzbbuffer);
+  if(rc != 0){
+    rsstwritelog(LOG_DEBUG, "Downloading NZB '%s' failed.", url);
+    retval=-1;
+  }
+
+  if(retval == 0) {
+    /*
+     * Parse the data
+     */
+    rc = parsefrommem(url, nzbbuffer, &doc);
+      if(rc != 0){
+        rsstwritelog(LOG_DEBUG, "Parsing NZB '%s' failed.", url);
+        *props=NULL;
+        retval=-1;
+      }
+  }
+
+  /*
+   * Use the doc structure to fill the metafileprops struct
+   */
+  if(retval == 0) {
+    #if 0
+    typedef struct {
+      METAFILETYPE type;        // Tells what kind of meta file is presented
+      size_t pieces_length;     // Size of pieces
+      size_t size;              // Size of files enclosed
+      size_t file_nr;           // Number of files in meta-file
+    } metafileprops;
+    #endif
+
+    /*
+     * Allocate the metafileprops structure
+     */
+    *props = calloc(1, sizeof(metafileprops));
+
+    /*
+     * Provide type of content
+     */
+    (*props)->type = nzb;
+
+    /*
+     * Get size and pieces number.
+     * Use them to calculate the pieces length.
+     */
+    rc = getnzbsize(doc, &((*props)->size), &((*props)->file_nr));
+    (*props)->pieces_length = (*props)->size/(*props)->file_nr;
+  }
+
+  /*
+   * Clean up mess
+   */
+  free(nzburl);
+  rsstfreedownload(nzbbuffer);
+  free(nzbbuffer);
+  xmlFreeDoc(doc);
+
+  /*
+   * Done
+   */
+  return retval;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/nzbparse.h b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/nzbparse.h
new file mode 100644
index 0000000..beb7459
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/nzb/nzbparse.h
@@ -0,0 +1,51 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#ifndef NZBPARSE
+#define NZBPARSE
+
+/*
+ * Should be big enough for all interesting data
+ */
+#define DATALEN  1024
+
+#if 0
+/*
+ * Structure holding useful NZB properties.
+ */
+typedef struct {
+  unsigned int files;     // number of files in the NZB
+  size_t size;            // Size of files enclosed
+} nzbprops;
+#endif
+
+/*
+ * Provide the URL to the NZB,
+ * returns a structure containing some of the props of the NZB.
+ * free structure afterwards
+ * @arguments
+ * url URL to get NZB from
+ * props structure holding the NZB properties
+ * @return
+ * returns -1 on failure to parse URL, otherwise 0 is returned.
+ */
+int rsstgetnzbinfo(rsstor_handle *handle, char *url, metafileprops **props);
+
+#endif
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/CMakeLists.txt b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/CMakeLists.txt
new file mode 100644
index 0000000..e9758d9
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/CMakeLists.txt
@@ -0,0 +1,8 @@
+SET(TORRENT_PATH filehandler/torrent)
+
+SET(LIBSRC ${LIBSRC}
+    ${TORRENT_PATH}/findtorrent
+    ${TORRENT_PATH}/tbl
+		${TORRENT_PATH}/torrentparse)
+
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/findtorrent.c b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/findtorrent.c
new file mode 100644
index 0000000..c36ec14
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/findtorrent.c
@@ -0,0 +1,542 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sqlite3.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "regexp.h"
+#include "curlfile.h"
+#include "logfile.h"
+#include "findtorrent.h"
+
+/*
+ * MIME strings
+ */
+#define TORRENT_MIME  "application/x-bittorrent"
+#define SECONDARY_MIME "application/octet-stream"
+#define HTML_MIME     "text/html"
+#define HTTPPATTERN   "http://"
+#define HTTPSPATTERN   "https://"
+
+#define XPATH_TO_A    "//a[@href]"
+
+#define NODOWN_EXT  "\\.(gif|png|jpg|js|rss|css|xml|jsf|exe)$"
+#define NODOWN_TEXT  "(/faq/|/forum/|/login/|/showlist/|calendar|php[^?]|news)"
+
+
+/*
+ * This function returns 1 when the file matches one of the uninteresting formatting.
+ * Else 0 is returned.
+ */
+static int uninteresting(char *url)
+{
+  int rc=0;
+
+  /*
+   * Do the matching.
+   */
+  rc = rsstcomregexp(NODOWN_EXT, url);
+  rc |= rsstcomregexp(NODOWN_TEXT, url);
+
+  /*
+   * return result.
+   */
+  return rc;
+}
+
+
+/*
+ * This is an HTML document parser, that prints all <a href=".."/> values
+ */
+static xmlXPathObjectPtr htmlextacthrefs(xmlDocPtr doc, const xmlChar* xpathExpr)
+{
+  xmlXPathContextPtr xpathCtx;
+  xmlXPathObjectPtr xpathObj;
+
+  /* Create Xpath evaluation context */
+  xpathCtx = xmlXPathNewContext(doc);
+  if(xpathCtx == NULL) {
+    fprintf(stderr,"Error: unable to create new XPath context\n");
+    return(NULL);
+  }
+
+  /* Evaluate Xpath expression */
+  xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
+  if(xpathObj == NULL) {
+    fprintf(stderr,"Error: unable to evaluate Xpath expression \"%s\"\n", XPATH_TO_A);
+    xmlXPathFreeContext(xpathCtx);
+    return(NULL);
+  }
+
+  /* dump the resulting document */
+  //xmlDocDump(stdout, doc);
+
+  /*
+   * cleanup
+   */
+  xmlXPathFreeContext(xpathCtx);
+
+  /*
+   * gone well
+   */
+  return(xpathObj);
+}
+
+
+/*
+ * Extract base name from URL
+ * basename is the output string for the base name
+ * Don't forget to free after use.
+ */
+static void getbasename(char *url, char **basename)
+{
+  char    *cur=NULL;
+  size_t  basesize=0;
+  int     found=0;
+
+  *basename = NULL;
+
+  /*
+   * find 3th '/'
+   */
+  cur = strrchr(url, '/');
+
+  /*
+   * When not found check if the string starts with 'http://'
+   * then return whole string
+   */
+  if(found==1 &&
+     ( strncmp(HTTPPATTERN, url, strlen(HTTPPATTERN))==0 ||
+       strncmp(HTTPSPATTERN, url, strlen(HTTPSPATTERN))==0  ) ){
+    cur=url+strlen(url);
+  }
+
+  /*
+   * Copy the base name to the output buffer
+   */
+  basesize=cur-url;
+	rsstalloccopy(basename, url, basesize);
+}
+
+
+/*
+ * Resolve relative path
+ * when link is a relative link link is completed.
+ * (and reallocated)
+ */
+static void resolvrel(char *fullurl, char *link, char **fulllink)
+{
+  char *basename  = NULL;
+  //char *fulllink  = NULL;
+  size_t fullsize = 0;
+
+  /*
+   * Test if link starts with 'http://'
+   * If it does link is full link
+   */
+  if(strncmp( HTTPPATTERN, link, strlen(HTTPPATTERN)) == 0 ||
+    strncmp( HTTPSPATTERN, link, strlen(HTTPSPATTERN))==0){
+    fullsize = strlen(link);
+    *fulllink = calloc(1, fullsize+2);
+    snprintf(*fulllink, fullsize+1, "%s/", link);
+  }
+  else {
+    /*
+     * When a relative link is found, make sure
+     * Get base path
+     */
+    getbasename(fullurl, &basename);
+
+    /*
+     * append base path with link
+     * realloc into new space
+     */
+    fullsize = strlen(basename) + strlen(link);
+    *fulllink = calloc(1, fullsize+3);
+    snprintf(*fulllink, fullsize+2, "%s/%s/", basename, link);
+  }
+
+  //printf("Full link : '%s' '%s' '%s' '%s'\n", fullurl, basename, link, *fulllink);
+
+  /*
+   * clean up
+   */
+  free(basename);
+}
+
+
+/*
+ * Get value of href attribute from node
+ */
+static char *gethrefvalue(xmlNode *node)
+{
+  struct _xmlAttr *prop;
+
+  prop = node->properties;
+
+  /*
+   * find href or NULL
+   */
+  while(prop != NULL){
+    if(strcmp("href", (char*) prop->name) == 0){
+      return (char*) prop->children->content;
+    }
+
+    /*
+     * to next node
+     */
+    prop=prop->next;
+  }
+
+  /*
+   * Not found
+   */
+  return NULL;
+}
+
+
+/*
+ * Decide if a downloaded file is a torrent
+ * @Arguments
+ * url URL of the downloaded file
+ * mime the mime type of the file
+ * @returns
+ * 0 on no torrent
+ * 1 on torrent found
+ */
+static int testiftorrent(char *url, char *mimetype)
+{
+	/*
+	 * found torrent mime
+	 */
+	if(strncmp(mimetype, TORRENT_MIME, strlen(TORRENT_MIME)) == 0) {
+		return 1;
+	}
+
+	/*
+	 * Is a torrent but with generic mime type.
+	 */
+	if(strncmp(mimetype, SECONDARY_MIME, strlen(SECONDARY_MIME)) == 0 &&
+			strstr(url, ".torrent") != NULL) {
+		return 1;
+	}
+
+	/*
+	 * not a torrent
+	 */
+	return 0;
+}
+
+
+/*
+ * This is a recursive function.
+ * It scans for torrent files, and will return the first one it encounters.
+ * Note this might not be the correct torrent at all :)
+ * A counter prevents the recursing from getting out of hand.
+ * The torrent will be contained in torbuffer.
+ * The URL the torrent was found in torrenturl.
+ * Don't forget to free buffer and torrenturl !
+ */
+int rsstfindtorrent(rsstor_handle *handle, char *url, char **torrenturl, MemoryStruct **torbuffer, int recurse)
+{
+  int               rc = 0;
+  MemoryStruct      buffer;
+  char              *filetype=NULL;
+  char              *linkaddr=NULL;
+  char              *fulllink=NULL;
+  xmlXPathObjectPtr allas=NULL;
+  xmlDocPtr         html=NULL;
+  xmlNodeSetPtr     nodeset=NULL;
+  int               count=0;
+
+  /*
+   * When uninteresting stuff is found, ignore
+   */
+  if( uninteresting(url) != 0) {
+    return 0;
+  }
+
+  /*
+   * Initialize stuff
+   */
+  memset(&buffer, 0, sizeof(MemoryStruct));
+  rsstwritelog(LOG_DEBUG, "Scan URL: '%s'", url);
+
+  /*
+   * Make sure no garbage is in here
+   */
+  *torrenturl=NULL;
+  *torbuffer=NULL;
+
+  /*
+   * Download content
+   */
+  rc = rsstdownloadtobuffer(handle, url, &buffer);
+  if(rc != 0) {
+    //rsstwritelog(LOG_NORMAL,  "%s: Failed to download.", url);
+	  rsstfreedownload(&buffer);
+    return 0;
+  }
+
+  /*
+   * try to get the Content type from the header
+   */
+  rc = rsstgetheadersvalue(HTTP_CONTENTTYPE, &filetype, &buffer);
+  if(rc == -1) {
+    /*
+     * No header found ignore this link.
+     */
+		rsstfreedownload(&buffer);
+    free(filetype);
+		return 0;
+  }
+
+  /*
+   * When we find a torrent, return 1 and set buffer + url
+   */
+	rc = testiftorrent(url, filetype);
+  if(rc == 1) {
+    /*
+     * Copy and allocate the url + buffer
+     * Both should be freed after use !
+     */
+		rsstalloccopy(torrenturl, url, strlen(url));
+    *torbuffer = calloc(1, sizeof(MemoryStruct)+1);
+    memcpy(*torbuffer, &buffer, sizeof(MemoryStruct));
+
+    /*
+     * NO other way, clean up here
+     */
+    free(filetype);
+    return 1;
+  }
+
+  /*
+   * When recursion = 0
+   * We are not interested in other content then torrents, so returning 0
+   */
+  if(recurse <= 0) {
+		rsstfreedownload(&buffer);
+    free(filetype);
+    return 0;
+  }
+
+  /*
+   * When html, call this method again on every html and torrent link in the document.
+   * ignore : .gif, .jpg, .jpeg, .png
+   */
+  if(strncmp(filetype, HTML_MIME, strlen(HTML_MIME)) == 0){
+    /*
+     * Parse document through html parser
+     */
+    html =  htmlReadDoc((unsigned char*)(buffer.memory), "", NULL,
+        HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR | HTML_PARSE_NOBLANKS | HTML_PARSE_RECOVER);
+    if(html == NULL) {
+      rsstwritelog(LOG_NORMAL, "%s: failed to create reader, although MIME suggested html\n", url);
+      rsstfreedownload(&buffer);
+			free(filetype);
+      return 0;
+    }
+
+    /*
+     * Find all <a href=.. > nodes
+     */
+    allas = htmlextacthrefs(html,(unsigned const char*) XPATH_TO_A);
+    nodeset = allas->nodesetval;
+
+    /*
+     * Go through nodes and see which ones are interesting
+     */
+    while(count < nodeset->nodeNr) {
+      /*
+       * Get href value that seem relevant
+       */
+      linkaddr = gethrefvalue(nodeset->nodeTab[count]);
+
+      /*
+       * pass them through the recursion one by one
+       * If one returns 1, break the loop and return that pointer to the output buffer.
+       */
+      resolvrel(url, linkaddr, &fulllink);
+
+      if(strlen(fulllink) == 0) {
+        rsstwritelog(LOG_DEBUG, "url: '%s' linkaddr: '%s' fulllink: '%s'", url, linkaddr, fulllink);
+      }
+
+      switch(*fulllink){
+        case'?':
+        case'#':
+          xmlFreeDoc(html);
+          free(fulllink);
+          xmlXPathFreeObject(allas);
+          free(filetype);
+          rsstfreedownload(&buffer);
+          return 0;
+      }
+
+      /*
+       * recurse
+       * When one of the children returns 1, return 1 to.
+       */
+      rc = rsstfindtorrent(handle, fulllink, torrenturl, torbuffer, recurse-1);
+      if(rc == 1) {
+        /*
+         * We found the torrent !
+         * Clean up and return.
+         */
+        xmlFreeDoc(html);
+        free(fulllink);
+        xmlXPathFreeObject(allas);
+        free(filetype);
+        return 1;
+      }
+
+      /*
+       * Clean up in loop, and move on
+       */
+      free(fulllink);
+      count++;
+    }
+  }
+
+  rsstwritelog(LOG_NORMAL, "Nothing found at '%s'", url);
+
+  /*
+   * Clean up
+   */
+  xmlXPathFreeObject(allas);
+  xmlFreeDoc(html);
+  free(filetype);
+  rsstfreedownload(&buffer);
+
+  return 0;
+}
+
+/*
+ * Set up handlers structure and call torrent handler (When available)
+ */
+static int rsstcalltorrenthandle(rsstor_handle *handle, char *torurl, char *name, char *filtername, MemoryStruct *buffer)
+{
+  int retval=0;
+  struct_downedmetafile torrent;
+
+  /*
+   * Setup the callback structure
+   */
+  memset(&torrent, 0, sizeof(struct_downedmetafile));
+  torrent.name = name;
+  torrent.filtername = filtername;
+  torrent.metatype = "torrent";
+  torrent.url = torurl;
+  if(buffer != NULL) {
+    torrent.metadata = buffer->memory;
+    torrent.metasize = buffer->size;
+  } else {
+    rsstwritelog(LOG_ERROR, "No torrent-content for '%s' %s:%d", torurl, __FILE__, __LINE__);
+  }
+
+  /*
+   * Call the handler
+   */
+  retval = rsstexecallbacks(handle, handletorrentfile, &torrent);
+
+  /*
+   * Return the handler return code
+   */
+  return retval;
+}
+
+
+/*
+ * Finds and writes torrent to file
+ */
+int rsstfindtorrentwrite(rsstor_handle *handle, char *url, char *name, char *filtername)
+{
+  int             rc = 0;
+  int             rv = 0;
+  char            *torurl = NULL;
+  MemoryStruct    *buffer = NULL;
+
+  rsstwritelog(LOG_DEBUG, "Writing torrent '%s' to file '%s'", url, name);
+
+  /*
+   * Get the buffer and URL to the torrent in there
+   */
+  rc = rsstfindtorrent(handle, url, &torurl, &buffer, RECURSE);
+  if(rc != 1) {
+    rsstwritelog(LOG_NORMAL, "Torrent not found in %s", url);
+		rsstfreedownload(buffer);
+    rv=-1;
+  }
+
+  /*
+   * Print to result
+   */
+  //int rsstwritelog(int level, char *str,...);
+  if(rv == 0 && strcmp(url, torurl) != 0) {
+    rsstwritelog(LOG_NORMAL, "Original URL : %s", url);
+    rsstwritelog(LOG_NORMAL, "Torrent URL   : %s", torurl);
+  }
+
+  /*
+   * Call the front end handler, when this does not provide a
+   * stop_processing back, continue.
+   */
+  rc = rsstcalltorrenthandle(handle, torurl, name, filtername, buffer);
+  if(rc == stop_processing) {
+    // When the callback has done the handling do no more
+    rsstwritelog(LOG_NORMAL, "Callback handled torrent download '%s'.", name);
+    rv=-1;
+  }
+
+  /*
+   * Save file to name
+   */
+  if(rv == 0) {
+    rc = rsstwritebuffer(name, buffer);
+    if(rc != 0){
+      rsstwritelog(LOG_ERROR, "Writing torrent '%s' failed.", name);
+      rv = -1;
+    }
+  }
+
+  /*
+   * free the result
+   */
+  free(torurl);
+  rsstfreedownload(buffer);
+  free(buffer);
+
+  return rv;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/findtorrent.h b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/findtorrent.h
new file mode 100644
index 0000000..c3ba819
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/findtorrent.h
@@ -0,0 +1,60 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#ifndef FINDTORRENT
+#define FINDTORRENT
+
+/*
+ * The levels the htmlextrator will recurse to find the torrent.
+ * Please do not set above 2 because the resolvetime will be looong.
+ */
+#define RECURSE     1
+
+/*
+ * This is a recursive function.
+ * It scans for torrent files, and will return the first one it encounteres.
+ * Note this might not be the correct torrent at all :)
+ * A counter prevents the recursing from getting out of hand.
+ * The torrent wil be contained in torbuffer.
+ * The url the torrent was found in torrenturl.
+ * Don't forget to free buffer and torrenturl !
+ * @arguments
+ * url the url to start searching.
+ * torrenturl the url found containing the torrent.
+ * torbuffer the buffer the torrent is returned in when found.
+ * recurse the number of recursions to do to find the torrent.
+ * @return
+ * 0 when nothing is found
+ * 1 when the torrent was found
+ */
+int rsstfindtorrent(rsstor_handle *handle, char *url, char **torrenturl, MemoryStruct **torbuffer, int recurse);
+
+/*
+ * Finds and writes torrent to file
+ * @arguments
+ * url the url to start looking for a torrent.
+ * name the path to store the torrent on disk.
+ * @return
+ * 0 on success
+ * -1 when torrent was not found or could not be stored.
+ */
+int rsstfindtorrentwrite(rsstor_handle *handle, char *url, char *name, char *filtername);
+
+#endif
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/tbl.c b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/tbl.c
new file mode 100644
index 0000000..ea808bf
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/tbl.c
@@ -0,0 +1,165 @@
+/* This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it
+ * and/or modify it under the terms of the Do What The Fuck You Want
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/wtfpl/COPYING for more details. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "tbl.h"
+
+#define RET_ERR(errtype) do { handle->err = errtype; return; } while(0)
+
+struct tbl_handle {
+	tbl_error_t err;
+	const char *ptr;
+	const char *end;
+	void       *ctx;
+};
+
+/* "low level parsing", the callback is passed so parse_string can call either
+ * the string callback or the dict key callback */
+static void parse_integer(int(*event_fn)(void *ctx, long value),
+                          tbl_handle_t *handle);
+static void parse_string (int (*event_fn)(void *ctx, char *value, size_t length),
+                          tbl_handle_t *handle);
+/* fucntions to parse container types */
+static void parse_list(const tbl_callbacks_t *callbacks, tbl_handle_t *handle);
+static void parse_dict(const tbl_callbacks_t *callbacks, tbl_handle_t *handle);
+/* gets the first char of the buffer to decide which parse_* to called */
+static void parse_internal(const tbl_callbacks_t *callbacks,
+                           tbl_handle_t          *handle);
+
+void parse_integer(int(*event_fn)(void *ctx, long value),
+                   tbl_handle_t *handle)
+{
+	long value;
+	void *ptr;
+	char *endptr;
+
+	ptr = memchr(handle->ptr + 1, 'e', (handle->end - handle->ptr) - 1);
+	if (!ptr)
+		RET_ERR(TBL_E_INVALID_DATA);
+
+	value = strtol(handle->ptr + 1, &endptr, 10);
+	if (endptr != ptr)
+		RET_ERR(TBL_E_INVALID_DATA);
+	else if(value && *(handle->ptr + 1) == '0') /* i0e is still valid */
+		RET_ERR(TBL_E_INVALID_DATA);
+	else {
+		if (event_fn)
+			if (event_fn(handle->ctx, value))
+				RET_ERR(TBL_E_CANCELED_BY_USER);
+
+		handle->ptr = endptr + 1; /* skip 'e' */
+	}
+}
+
+void parse_string(int (*event_fn)(void *ctx, char *value, size_t length),
+                  tbl_handle_t *handle)
+{
+	size_t strlen;
+	void *ptr;
+	char *endptr;
+
+	ptr = memchr(handle->ptr, ':', handle->end - handle->ptr);
+	if (!ptr)
+		RET_ERR(TBL_E_INVALID_DATA);
+
+	strlen = strtol(handle->ptr, &endptr, 10);
+	if (endptr != ptr)
+		RET_ERR(TBL_E_INVALID_DATA);
+	else if (endptr + 1 + strlen > handle->end)
+		RET_ERR(TBL_E_INVALID_DATA);
+	else {
+		if (event_fn)
+			if (event_fn(handle->ctx, endptr + 1, strlen))
+				RET_ERR(TBL_E_CANCELED_BY_USER);
+
+		handle->ptr = endptr + 1 + strlen; /* jump to next token */
+	}
+}
+
+void parse_list(const tbl_callbacks_t *callbacks, tbl_handle_t  *handle)
+{
+	/* list start */
+	if (callbacks->tbl_list_start)
+		if (callbacks->tbl_list_start(handle->ctx))
+			RET_ERR(TBL_E_CANCELED_BY_USER);
+	/* entries */
+	handle->ptr++;
+	while(*handle->ptr != 'e') {
+		parse_internal(callbacks, handle);
+		if (handle->err != TBL_E_NONE)
+			return;
+	}
+	/* list end */
+	if (callbacks->tbl_list_end)
+		if (callbacks->tbl_list_end(handle->ctx))
+			RET_ERR(TBL_E_CANCELED_BY_USER);
+
+	handle->ptr++; /* skip 'e' */
+}
+
+void parse_dict(const tbl_callbacks_t *callbacks, tbl_handle_t  *handle)
+{
+	/* dict start */
+	if (callbacks->tbl_dict_start)
+		if (callbacks->tbl_dict_start(handle->ctx))
+			RET_ERR(TBL_E_CANCELED_BY_USER);
+
+	/* keys + entries */
+	handle->ptr++;
+	while(*handle->ptr != 'e') {
+		parse_string(callbacks->tbl_dict_key, handle);
+		if (handle->err != TBL_E_NONE)
+			return;
+		parse_internal(callbacks, handle);
+		if (handle->err != TBL_E_NONE)
+			return;
+	}
+	/* dict end */
+	if (callbacks->tbl_dict_end)
+		if (callbacks->tbl_dict_end(handle->ctx))
+			RET_ERR(TBL_E_CANCELED_BY_USER);
+
+	handle->ptr++; /* skip 'e' */
+}
+
+void parse_internal(const tbl_callbacks_t *callbacks, tbl_handle_t  *handle)
+{
+	char c = *handle->ptr;
+
+	if ((handle->ptr >= handle->end) || (!callbacks))
+		RET_ERR(TBL_E_INVALID_DATA);
+
+	/* get type of next entry */
+	if (c == 'i')
+		parse_integer(callbacks->tbl_integer, handle);
+	else if (isdigit(c) != 0)
+		parse_string(callbacks->tbl_string, handle);
+	else if (c == 'l')
+		parse_list(callbacks, handle);
+	else if (c == 'd')
+		parse_dict(callbacks, handle);
+	else
+		handle->err = TBL_E_INVALID_DATA;
+}
+
+TBL_API tbl_error_t tbl_parse(const tbl_callbacks_t *callbacks,
+                              void                  *ctx,
+                              const char            *buf,
+                              const char            *bufend)
+{
+	tbl_handle_t handle = { TBL_E_NONE, buf, bufend, ctx };
+	if ((handle.ptr >= handle.end) || (!callbacks))
+		return TBL_E_INVALID_DATA;
+
+	while (handle.ptr < handle.end && handle.err == TBL_E_NONE) {
+		parse_internal(callbacks, &handle);
+	}
+
+	return handle.err;
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/tbl.h b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/tbl.h
new file mode 100644
index 0000000..4543f4c
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/tbl.h
@@ -0,0 +1,67 @@
+/* This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it
+ * and/or modify it under the terms of the Do What The Fuck You Want
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/wtfpl/COPYING for more details. */
+
+#ifndef TBL_H
+#define TBL_H
+
+#include <stddef.h> /* size_t */
+
+#if defined(_WIN32) && defined(TBL_SHARED)
+#  ifdef TBL_BUILD
+#    define TBL_API __declspec(dllexport)
+#  else
+#    define TBL_API __declspec(dllimport)
+#  endif
+#else
+#  define TBL_API
+#endif
+
+#ifdef __cplusplus
+extern C {
+#endif
+
+typedef enum {
+	TBL_E_NONE,
+	TBL_E_INVALID_DATA,
+	TBL_E_CANCELED_BY_USER,
+	TBL_E_UNKNOWN
+} tbl_error_t;
+
+typedef struct tbl_handle tbl_handle_t;
+
+/* parsing is stopped if a callback returns something else than 0 */
+typedef struct tbl_callbacks {
+	int (*tbl_integer)   (void *ctx, long value);
+	int (*tbl_string)    (void *ctx, char *value, size_t length);
+
+	int (*tbl_list_start)(void *ctx);
+	int (*tbl_list_end)  (void *ctx);
+
+	int (*tbl_dict_start)(void *ctx);
+	int (*tbl_dict_key)  (void *ctx, char *key, size_t length);
+	int (*tbl_dict_end)  (void *ctx);
+} tbl_callbacks_t;
+
+TBL_API tbl_error_t tbl_parse(const tbl_callbacks_t *callbacks,
+                              void                  *ctx,
+                              const char            *buf,
+                              const char            *bufend);
+
+/* only prototypes; nothing of this is implemented yet */
+/*
+TBL_API int tbl_gen_integer(tbl_handle_t *handle, long value);
+TBL_API int tbl_gen_string(tbl_handle_t *handle, const char *str, size_t len);
+TBL_API int tbl_gen_dict_open(tbl_handle_t *handle);
+TBL_API int tbl_gen_dict_close(tbl_handle_t *handle);
+TBL_API int tbl_gen_list_open(tbl_handle_t *handle);
+TBL_API int tbl_gen_list_close(tbl_handle_t *handle);
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TBL_H */
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/torrentparse.c b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/torrentparse.c
new file mode 100644
index 0000000..501574a
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/torrentparse.c
@@ -0,0 +1,235 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <time.h>
+#include <sqlite3.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "curlfile.h"
+#include "tbl.h"
+#include "torrentparse.h"
+#include "findtorrent.h"
+#include "logfile.h"
+#include "regexp.h"
+
+typedef struct str { size_t len; char *str; } str_t;
+
+/*
+ * Find the key's we need and use them to fill the info
+ */
+static void setintstate(bencstate *state, long value){
+  /*
+   * no key ? nothing to do here
+   */
+  if(state->prevtype != 'k') {
+    return;
+  }
+
+  /*
+   * Add size to total
+   */
+  if(strcmp( "length", state->prevkey) == 0) {
+    state->props->size += value;
+  }
+
+  /*
+   * Get pieces lenght
+   */
+  if( strcmp("piece length", state->prevkey) == 0) {
+    state->props->pieces_length = value;
+  }
+}
+
+/*
+ * Parse int attributes
+ */
+static int tbl_integer(void *ctx, long value)
+{
+  bencstate *state = (bencstate *) ctx;
+
+  /*
+   * update state
+   */
+  setintstate(state, value);
+
+  /*
+   * update state for next round
+   */
+  state->prevtype='i';
+  state->prevint=value;
+
+	return 0;
+}
+
+/*
+ * Pars bencoded string atributes
+ */
+static int tbl_string(void *ctx, char *value, size_t length)
+{
+  if(length > 300) {
+    return 0;
+  }
+
+  /*
+   * set state
+   */
+  bencstate *state = (bencstate *) ctx;
+  state->prevtype='s';
+  strncpy(state->prevstring, value, DATALEN);
+
+	return 0;
+}
+
+/*
+ * Parse bencoded dictionary keys
+ */
+static int tbl_dictkey(void *ctx, char *value, size_t length)
+{
+  char *string;
+  bencstate *state = (bencstate *) ctx;
+
+  /*
+   * terminate string
+   */
+	rsstalloccopy(&string, value, length);
+
+  /*
+   * set state
+   */
+  state->prevtype='k';
+  strncpy(state->prevkey, string, DATALEN);
+
+  free(string);
+	return 0;
+}
+
+/*
+ * Callback structure used by tbl
+ */
+static tbl_callbacks_t callbacks = {
+	tbl_integer,
+	tbl_string,
+	NULL,
+	NULL,
+	NULL,
+	tbl_dictkey,
+	NULL
+};
+
+/*
+ * Allocate state struct
+ */
+static bencstate *allocbencstate(void){
+  bencstate *state=NULL;
+
+  state = calloc(1, sizeof(bencstate));
+  state->props = calloc(1, sizeof(metafileprops));
+
+  return state;
+}
+
+/*
+ * Do parsing and handling here
+ * Return a struct containing the fields we need.
+ * Do not forget to free the stuct after use.
+ */
+static int parsetorrent(MemoryStruct *buffer, metafileprops **props)
+{
+	tbl_error_t err;
+  bencstate *state;
+
+  /*
+   * allocate state object
+   */
+  state = allocbencstate();
+
+  /*
+   * parse bencoded data
+   */
+	err = tbl_parse(&callbacks, state, buffer->memory, buffer->memory+buffer->size);
+  if(err != TBL_E_NONE){
+    rsstwritelog(LOG_ERROR, "Error while parsing bencoded data.");
+    return -1;
+  }
+
+  /*
+   * Get the interesting part lose the rest
+   */
+  *props = state->props;
+  free(state);
+
+  return 0;
+}
+
+
+/*
+ * Provide the url to the torrent,
+ * returns a struct containing some of the props of the torrent.
+ * free struct afterwards
+ */
+int rsstgettorrentinfo(rsstor_handle *handle, char *url, metafileprops **props)
+{
+  MemoryStruct *buffer=NULL;
+  int           rc=0;
+  int           retval=0;
+  char         *torurl=NULL;
+
+  /*
+   * Download to buffer
+   */
+  rc = rsstfindtorrent(handle, url, &torurl, &buffer, RECURSE);
+  if(rc != 1){
+    rsstwritelog(LOG_NORMAL, "could not find torrent '%s' %s:%d", url, __FILE__, __LINE__);
+    *props=NULL;
+    retval=-1;
+  }
+  /*
+	 * Do nothing for now with the found url.
+	 */
+  free(torurl);
+
+  /*
+   * Parse torrent
+   */
+  if(retval == 0) {
+    rc = parsetorrent(buffer, props);
+    if(rc != 0){
+      rsstwritelog(LOG_ERROR, "could not parse torrent '%s' %s:%d", url, __FILE__, __LINE__);
+      *props=NULL;
+      retval=-1;
+    }
+  }
+
+  /*
+   * free buffer
+   */
+  rsstfreedownload(buffer);
+  free(buffer);
+
+  return retval;
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/torrentparse.h b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/torrentparse.h
new file mode 100644
index 0000000..acb2423
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filehandler/torrent/torrentparse.h
@@ -0,0 +1,62 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#ifndef TORRENTPARSE
+#define TORRENTPARSE
+
+/*
+ * Should be big enough for all interesting data
+ */
+#define DATALEN  1024
+
+#if 0
+/*
+ * Structure holding useful torrent properties.
+ */
+typedef struct {
+  size_t pieces_length;     // Size of pieces
+  size_t size;            // Size of files enclosed
+} torprops;
+#endif
+
+/*
+ * Structure to hold state info and torrent props
+ */
+typedef struct {
+  metafileprops  *props;       // Torrent properties found go here
+  char      prevtype;    // Can be 's' string, 'd' int or 'k' key
+  char      prevkey[DATALEN+1];     // Previously found key.
+  long      prevint;      // previous int val
+  char      prevstring[DATALEN+1];  // Previous string
+} bencstate;
+
+/*
+ * Provide the URL to the torrent,
+ * returns a structure containing some of the props of the torrent.
+ * free structure afterwards
+ * @arguments
+ * url URL to get torrent from
+ * props structure holding the torrent properties
+ * @return
+ * returns -1 on failure to parse URL, otherwise 0 is returned.
+ */
+int rsstgettorrentinfo(rsstor_handle *handle, char *url, metafileprops **props);
+
+#endif
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filesystem.c b/tags/swarmtv-0.9.2/libswarmtv/filesystem.c
new file mode 100644
index 0000000..5ebeed5
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filesystem.c
@@ -0,0 +1,306 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef __MINGW32__
+#include <sys/statvfs.h>
+#endif
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef __MINGW32__
+#include <windows.h>
+#define _WIN32_IE 0x0400
+#include "shlobj.h"
+#endif
+
+#include "regexp.h"
+
+#define TESTFILENAME "test.file"
+
+/*
+ * Complete path
+ * when the first char of filename is a ~ it gets replaced by
+ * the path to the home directory
+ * free destination path afterwards
+ * Arguments
+ * origpath	The path containing '~' and stuff
+ * destpath	The path completed and all
+ */
+void rsstcompletepath(const char *origpath, char **destpath)
+{
+  int   lenght=0;
+  #ifdef __MINGW32__
+  char homedir[MAX_PATH];
+  #else
+  char *homedir=NULL;
+  #endif
+
+	/*
+	 * Test input
+	 */
+	if(origpath == NULL) {
+		return;
+	}
+
+  /*
+   * Test if the string starts with a '~'
+   */
+  if(*origpath == '~') {
+#ifdef __MINGW32__
+    /* let's assume Windows gives me a folder
+     * and not check for 0 every step of the way
+     */
+
+#ifdef UNICODE
+    /* might need some UNICODE safety here !! */
+    LPWSTR homefolder=NULL;
+    SHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, 0, homefolder);
+    int cw=lstrlenW(homefolder);
+    int cc=WideCharToMultiByte(CP_ACP, 0, homefolder, cw, NULL, 0, NULL, NULL);
+    /* now we know how many chars */
+    cc=WideCharToMultiByte(CP_ACP, 0, homefolder, cw, homedir, cc, NULL, NULL);
+    homedir[cc]='\0';
+    //delete homefolder;
+#else
+    SHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, 0, homedir);
+#endif
+#else
+    homedir = getenv("HOME");
+#endif
+
+    /*
+     * if it does insert home path in place of '~'
+     */
+    lenght = strlen(origpath)-1;
+    lenght += strlen(homedir);
+    lenght++; // we add an extra '/' in the path
+
+    /*
+     * Allocate and build output
+     */
+    *destpath = calloc(lenght+1, 1);
+    sprintf(*destpath, "%s/%s", homedir, origpath+1);
+  } else {
+    /*
+     * if not copy origpath to destpath and allocate memory
+     */
+		rsstalloccopy(destpath, (char*) origpath, strlen(origpath));
+  }
+}
+
+
+/*
+ * Test if a file or directory exists
+ * return 0 when found, -1 if not found
+ * Arguments
+ * path
+ * returns
+ * 0 on success, -1 on error (or when not found).
+ */
+int rsstfsexists(const char *path)
+{
+  struct stat st;
+  int 		rc=0;
+	char 		*fullpath=NULL;
+
+	/*
+	 * Get full path
+	 */
+  rsstcompletepath(path, &fullpath);
+
+  /*
+   * Stat the file
+   */
+  rc = stat(fullpath, &st);
+
+	/*
+	 * Cleanup
+	 */
+	free(fullpath);
+
+  return rc;
+}
+
+/*
+ * Test if a directory is writable
+ * This is done by creating a test file named "test.file",
+ * and deleting it afterwards.
+ * Arguments
+ * path		Path to file to be tested.
+ * Return
+ * 0 on success, -1 on failure (not writable)
+ */
+int rssttestwrite(const char *path)
+{
+  int   rc=0;
+  int   fsock=0;
+  int   lenght=0;
+  char  *filename=NULL;
+	char	*fullpath=NULL;
+
+	/*
+	 * Full path
+	 */
+	rsstcompletepath(path, &fullpath);
+
+  /*
+   * Create path
+   */
+  lenght = strlen(fullpath);
+  lenght += strlen(TESTFILENAME);
+  lenght++; // we add an extra '/' in the path
+  filename = calloc(lenght+1, 1);
+  sprintf(filename, "%s/%s", fullpath, TESTFILENAME);
+
+  /*
+   * Create test file
+   */
+  fsock = creat(filename, S_IRWXU);
+  if(fsock != 0) {
+    /*
+     * Close the file.
+     */
+    close(fsock);
+
+    /*
+     * Delete file when creation was successful
+     */
+    rc = remove(filename);
+  }
+
+  free(filename);
+	free(fullpath);
+
+  /*
+   * check tests
+   */
+  if(fsock != 0 && rc == 0) {
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+
+/*
+ * Create directory
+ * Arguments
+ * path path to directory
+ * returns
+ * 0 on success, -1 on failure
+ */
+int rsstmakedir(char *path)
+{
+	int rc;
+
+	/*
+	 * Create directory depending on users umask.
+	 */
+	#ifdef __MINGW32__
+	rc = mkdir(path);
+	#else
+	rc = mkdir(path, 0777);
+	#endif
+
+	return rc;
+}
+
+/*
+ * Get the usage of the partition the pointed directory resides in
+ * @arguments
+ * path the path to get the usage for
+ * usage the usage in percents 0 - 100
+ * @returns
+ * 0 on success, -1 on failure
+ */
+int rsstdiskusage(char *path, int *usage)
+{
+  int rc=0;
+  int retval=0;
+#ifndef __MINGW32__
+  struct statvfs sbuf;
+#endif
+  long int left=0;
+  long int total=0;
+  char *exppath=NULL;
+
+  /*
+   * Init struct.
+   */
+#ifndef __MINGW32__
+  memset(&total, 0, sizeof(statvfs));
+#endif
+
+  /*
+   * Sanity check
+   */
+  if(strlen(path) == 0){
+    return 0;
+  }
+
+  /*
+   * Expand the current path
+   */
+  rsstcompletepath(path, &exppath);
+
+#ifndef __MINGW32__
+  rc = statvfs(exppath, &sbuf);
+  if (rc < 0){
+    retval = -1;
+  } else {
+    left=sbuf.f_bsize*sbuf.f_bavail;
+    total=sbuf.f_bsize*sbuf.f_blocks;
+  }
+#else
+  DWORD dwBytesPerSector, dwSectorsPerCluster, dwFreeClusters, dwTotalClusters;
+  #ifdef UNICODE
+  wchar_t *wexppath=NULL;
+  mbstowcs(wexppath, exppath, MAX_PATH);
+  rc = GetDiskFreeSpace(wexppath, &dwBytesPerSector,
+    &dwSectorsPerCluster, &dwFreeClusters, &dwTotalClusters);
+  #else
+  rc = GetDiskFreeSpace(exppath, &dwBytesPerSector,
+    &dwSectorsPerCluster, &dwFreeClusters, &dwTotalClusters);
+  #endif
+  if (rc < 0){
+    retval = -1;
+  } else {
+    left=dwBytesPerSector*dwSectorsPerCluster*dwFreeClusters;
+    total=dwBytesPerSector*dwSectorsPerCluster*dwTotalClusters;
+  }
+#endif
+  /*
+   * Calculate the usage percentage
+   */
+  *usage=(int) ((1.0-(float)left/total)*100.0);
+
+  /*
+   * Clean up
+   */
+  free(exppath);
+
+  return retval;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filesystem.h b/tags/swarmtv-0.9.2/libswarmtv/filesystem.h
new file mode 100644
index 0000000..55a062c
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filesystem.h
@@ -0,0 +1,69 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Complete path
+ * when the first char of filename is a ~ it gets replaced by
+ * the path to the homedir
+ * free destpath afterwards
+ * @arguments
+ * origpath the original path
+ * destpath the expanded (complete) path
+ */
+void rsstcompletepath(const char *origpath, char **destpath);
+
+/*
+ * Test if a file or directory exists
+ * @arguments
+ * path path to check
+ * @returns
+ * return 0 when found, -1 if not found
+ */
+int rsstfsexists(char *path);
+
+/*
+ * Test if a directory is writable
+ * This is done by creating a testfile named "test.file",
+ * and deleting it afterwards.
+ * @arguments
+ * path path to check
+ * @returns
+ * return 0 when found, -1 if not found
+ */
+int rssttestwrite(const char *path);
+
+/*
+ * Create directory
+ * @arguments
+ * path path to directory
+ * @returns
+ * 0 on succes, -1 on failure
+ */
+int rsstmakedir(char *path);
+
+/*
+ * Get the usage of the partition the pointed directory resides in
+ * @arguments
+ * path the path to get the usage for
+ * usage the usage in percents 0 - 100
+ * @returns
+ * 0 on success, -1 on failure
+ */
+int rsstdiskusage(char *path, int *usage);
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filter.c b/tags/swarmtv-0.9.2/libswarmtv/filter.c
new file mode 100644
index 0000000..0ff4369
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filter.c
@@ -0,0 +1,217 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pcre.h>
+#include <sqlite3.h>
+#include <time.h>
+
+#include "types.h"
+#include "curlfile.h"
+#include "database.h"
+#include "logfile.h"
+
+#define  MAXLENGHT 400
+
+
+/*
+ * Del all filters.
+ * Deletes all filters from filter table.
+ * On success 0 is returned.
+ */
+int rsstdelallfilters(rsstor_handle *handle)
+{
+	sqlite3	*db=NULL;
+  int      rc=0;
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+  /*
+   * Initialize query
+   */
+  const char* query = "delete from 'filters'";
+
+  printf("Attempting to delete all filters \n");
+
+  /*
+   * Execute query
+   * When name is all, delete all filters.
+   */
+  rc = rsstexecutequery(db, query, NULL);
+  switch(rc) {
+    case(ROWS_CHANGED):
+      return 0;
+      break;
+    case(ROWS_EMPTY):
+			printf("No filters left, delete all did nothing %s:%d\n", __FILE__, __LINE__);
+			rsstwritelog(LOG_ERROR, "No filters left, delete all did nothing %s:%d", __FILE__, __LINE__);
+			return -1;
+			break;
+		default:
+			rsstwritelog(LOG_ERROR, "Query error during delallfilters %s:%d",  __FILE__, __LINE__);
+			return -1;
+	}
+}
+
+/*
+ * Del filter item
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelfilter(rsstor_handle *handle, const char *name)
+{
+	sqlite3    *db=NULL;
+	int         rc=0;
+
+	/*
+	 * Get db pointer.
+	 */
+	db = handle->db;
+
+	/*
+	 * Initialize query
+	 */
+	const char* query = "delete from 'filters' where name=?1";
+
+	printf("Attempting to delete filter '%s'\n", name);
+
+	/*
+	 * Execute query
+	 * When name is all, delete all filters.
+	 */
+	rc = rsstexecutequery(db, query, "s", name);
+	switch(rc) {
+		case(ROWS_CHANGED):
+			return 0;
+			break;
+		case(ROWS_EMPTY):
+			fprintf(stderr, "Could not delete filter '%s' %s:%di\n", name,  __FILE__, __LINE__);
+			rsstwritelog(LOG_ERROR, "Could not delete filter '%s' %s:%d", name,  __FILE__, __LINE__);
+			return -1;
+			break;
+		default:
+			rsstwritelog(LOG_ERROR, "Query error during delfilter %s:%d",  __FILE__, __LINE__);
+			return -1;
+	}
+}
+
+/*
+ * Check Filter
+ * When the filter exists, return 1
+ * else 0
+ */
+static int checkfilter(sqlite3 *db, const char *name)
+{
+	int rc=0;
+
+	char *query = "select * from filters where name=?1";
+
+	/*
+	 * execute query
+	 */
+	rc = rsstexecutequery(db, query, "s", name);
+
+	return rc;
+}
+
+/*
+ * Add filter item
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstaddfilter(rsstor_handle *handle, const char *name, const char *filter, const char *doublefilter)
+{
+	int         rc=0;
+	const char *locdouble=NULL; // holds pointer to double filter or empty
+	char        query[MAXLENGHT+1];
+	sqlite3 	 *db=NULL;
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+	/*
+	 * No filters can be added that have the name all.
+	 */
+	if(strcmp(name, "all") == 0){
+		rsstwritelog(LOG_NORMAL, "No filter can be added with name 'all'");
+		fprintf(stderr, "No filter can be added with name 'all'\n");
+		return -1;
+	}
+
+	/*
+	 * Init query, to an insert when not found, to a update when existing
+	 */
+	memset(query, 0, MAXLENGHT+1);
+	rc = checkfilter(db, name);
+	switch(rc) {
+		case 0:
+			strncpy(query, "INSERT INTO 'filters' (name, filter, nodouble) VALUES(?1, ?2, ?3)", MAXLENGHT);
+			break;
+		case 1:
+			rsstwritelog(LOG_NORMAL, "filter '%s' exists, updating.", name);
+			printf("filter '%s' exists, updating.\n", name);
+			strncpy(query, "UPDATE 'filters' SET filter=?2, nodouble=?3 WHERE name=?1", MAXLENGHT);
+			break;
+		default:
+      rsstwritelog(LOG_ERROR, "Filter table corrupt !! %s:%d", __FILE__, __LINE__);
+      fprintf(stderr, "Filter table in database corrupt!\n");
+      return -1;
+  }
+
+  /*
+   * Debug
+   */
+  rsstwritelog(LOG_NORMAL, "new filter name : %s", name);
+  rsstwritelog(LOG_NORMAL, "filter : %s", filter);
+  rsstwritelog(LOG_NORMAL, "nodouble filter : %s", doublefilter);
+
+  /*
+   * if no 'no double' filter is provided insert an empty string
+   */
+  if(doublefilter == NULL){
+    locdouble = "";
+  } else {
+    locdouble = doublefilter;
+  }
+
+  /*
+   * Execute query to add filter
+   * When no rows are changed return error.
+   */
+  rc = rsstexecutequery(db, query, "sss", name, filter, doublefilter);
+  if(rc != ROWS_CHANGED) {
+    rsstwritelog(LOG_ERROR, "No rows changed, inserting filter failed. %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * All gone well.
+   */
+  return 0;
+}
+
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/filter.h b/tags/swarmtv-0.9.2/libswarmtv/filter.h
new file mode 100644
index 0000000..d89385c
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/filter.h
@@ -0,0 +1,56 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+
+
+/*
+ * Del all filters.
+ * Deletes all filters from filtertable.
+ * @returns
+ * On succes 0 is returned.
+ */
+int rsstdelallfilters(rsstor_handle *handle);
+
+/*
+ * del source item
+ * When allready existing -1 is returned.
+ * @arguments
+ * name the name of the SQL filter to delete
+ * @return
+ * On succes 0 is returned.
+ */
+int rsstdelfilter(rsstor_handle *handle, const char *name);
+
+
+/*
+ * Add source item
+ * @Arguments
+ * handle RSS-torrent handle
+ * name name of the filter
+ * filter SQL query to sort out the candidates
+ * doublefilter SQL query to root out the candidates that are already downloaded.
+ * @return
+ * When allready existing -1 is returned.
+ * On succes 0 is returned.
+ */
+int rsstaddfilter(rsstor_handle *handle, const char *name, const char *filter, const char *doublefilter);
+
+
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/lastdownloaded.c b/tags/swarmtv-0.9.2/libswarmtv/lastdownloaded.c
new file mode 100644
index 0000000..5242675
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/lastdownloaded.c
@@ -0,0 +1,304 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "types.h"
+#include "regexp.h"
+#include "logfile.h"
+
+#include "database.h"
+#include "databaseimpl.h"
+
+/*
+ * Free a last downloaded structure.
+ * @Arguments
+ * downed pointer to the downloaded structure
+ */
+void rsstfreelastdowned(lastdowned_struct *downed)
+{
+  /*
+   * Free the strings
+   */
+  free(downed->filtername);
+  free(downed->filtertype);
+  rsstfreedownloaded(downed->downloaded);
+  free(downed->downloaded);
+}
+
+/*
+ * Free the downloaded container and its contents
+ * When the container it self is allocated, it should be freed separately
+ * @Arguments
+ * container pointer to the downed container to be freed
+ */
+void rsstfreelastdownedcontainer(lastdowned_container *container)
+{
+  int count=0;
+
+  /*
+   * Free all elements
+   */
+  while(count < container->nr){
+    rsstfreelastdowned(container->lastdownloaded+count);
+    count++;
+  }
+  /*
+   * Free the container pointers
+   */
+  free(container->lastdownloaded);
+}
+
+
+/*
+ * Add an entrie to the last entry
+ */
+static int rsstaddlastdowned(sqlite3_stmt *ppStmt, int count, char *type, lastdowned_container *container)
+{
+  lastdowned_struct *lastdownload=NULL;
+  downloaded_struct *downloaded=NULL;
+  int   id=0;
+  char *name=NULL;
+  char *link=NULL;
+  char *title=NULL;
+  char *pubdate=NULL;
+  char *category=NULL;
+  char *metatype=NULL;
+  int season=0;
+  int episode=0;
+
+  /*
+   * Get the values from the query
+   */
+  id        = sqlite3_column_int(ppStmt, 0);
+  name      = (char*) sqlite3_column_text(ppStmt, 1);
+  link      = (char*) sqlite3_column_text(ppStmt, 2);
+  title     = (char*) sqlite3_column_text(ppStmt, 3);
+  pubdate   = (char*) sqlite3_column_text(ppStmt, 4);
+  category  = (char*) sqlite3_column_text(ppStmt, 5);
+  metatype  = (char*) sqlite3_column_text(ppStmt, 6);
+  season    =  sqlite3_column_int(ppStmt, 7);
+  episode   =  sqlite3_column_int(ppStmt, 8);
+
+  /*
+   * Allocate and reallocate the structures
+   */
+  container->nr=count+1;
+  container->lastdownloaded = realloc(container->lastdownloaded, sizeof(lastdowned_struct)*container->nr);
+
+  /*
+   * Allocate the downloaded structure
+   */
+  if(link == NULL) {
+    container->lastdownloaded[count].downloaded = NULL;
+  } else {
+    container->lastdownloaded[count].downloaded = calloc(1, sizeof(downloaded_struct));
+  }
+
+  /*
+   * Initialize the pointers
+   */
+  lastdownload = &(container->lastdownloaded[count]);
+
+
+  /*
+   * Add the data to the container
+   * int rsstalloccopy(char **dest, const char *src, const size_t size);
+   */
+  lastdownload->filterid = id;
+  rsstalloccopy(&(lastdownload->filtername), name, strlen(name));
+  rsstalloccopy(&(lastdownload->filtertype), type, strlen(type));
+  /*
+   * When the filter has downloaded something set the variables.
+   * In other cases NULL everting.
+   */
+  if(link != NULL) {
+    downloaded = lastdownload->downloaded;
+    rsstalloccopy(&(downloaded->link), link, strlen(link));
+    rsstalloccopy(&(downloaded->title), title, strlen(title));
+    rsstalloccopy(&(downloaded->pubdate), pubdate, strlen(pubdate));
+    rsstalloccopy(&(downloaded->category), category, strlen(category));
+    rsstalloccopy(&(downloaded->metatype), metatype, strlen(metatype));
+    downloaded->season = season;
+    downloaded->episode = episode;
+  }
+
+  /*
+   * All done
+   */
+  return 0;
+}
+
+
+/*
+ * Get information of the last downloads and the filters that produced them
+ * @Arguments
+ * handle RSS-torrent handle
+ * container the pointer pointer to the container
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rsstgetlastdownloaded(rsstor_handle *handle, lastdowned_container *container)
+{
+  int rc=0;
+  int count=0;
+  int retval=0;
+  sqlite3_stmt *ppstmtsimple=NULL;
+  sqlite3_stmt *ppstmtsql=NULL;
+
+  /*
+   * Initialize
+   */
+  memset(container, 0, sizeof(lastdowned_container));
+
+  /*
+   * Queries
+   * Get the following values
+   * name link title pubdate category metatype season episode
+   */
+#if 0
+  char *simplequery=
+    "SELECT spl.id, spl.name, dow.link, dow.title, dow.pubdate, dow.category, dow.metatype, dow.season, dow.episode "
+    "FROM simplefilters spl, downloaded as dow, lastdownload as last "
+    "WHERE spl.id = last.simple_id and dow.id = last.downloaded_id";
+#endif
+  char *simplequery=
+    "SELECT spl.id, spl.name, dow.link, dow.title, dow.pubdate, dow.category, dow.metatype, dow.season, dow.episode "
+    "FROM simplefilters spl LEFT JOIN lastdownload as last ON spl.id = last.simple_id LEFT JOIN downloaded as dow ON last.downloaded_id = dow.id "
+    "ORDER BY spl.name";
+  char *sqlquery=
+    "SELECT flt.id, flt.name, dow.link, dow.title, dow.pubdate, dow.category, dow.metatype, dow.season, dow.episode "
+    "FROM filters flt, downloaded as dow, lastdownload as last "
+    "WHERE flt.id = last.sql_id and dow.id = last.downloaded_id "
+    "ORDER BY flt.name";
+
+  /*
+   * Execute the query to get all simple filter last downloads
+   */
+  rc = rsstexecqueryresult(handle->db, &ppstmtsimple, simplequery, NULL);
+  if(rc != 0){
+    fprintf(stderr, "Query for retrieving simple filter last downloads. %s:%d\n", __FILE__, __LINE__);
+    retval=-1;
+  }
+
+  /*
+   * Execute the query to get all sql filter last downloads
+   */
+  if(retval == 0){
+    rc = rsstexecqueryresult(handle->db, &ppstmtsql, sqlquery, NULL);
+    if(rc != 0){
+      fprintf(stderr, "Query for retrieving sql filter last downloads.");
+      retval=-1;
+    }
+  }
+
+  /*
+   * Add the result numbers together and allocate the space.
+   */
+  if(retval == 0){
+    while( SQLITE_DONE != sqlite3_step(ppstmtsimple)) {
+      rc = rsstaddlastdowned(ppstmtsimple, count, "simple", container);
+      if(rc != 0){
+        rsstwritelog(LOG_ERROR, "Record '%d' type '%s' could not be added.", count, "simple" );
+        retval=-1;
+        break;
+      }
+      count++;
+    }
+  }
+
+  /*
+   * Add the resulting information into the structures
+   */
+  if(retval == 0){
+    while( SQLITE_DONE != sqlite3_step(ppstmtsql)) {
+      rc = rsstaddlastdowned(ppstmtsql, count, "sql", container);
+      if(rc != 0){
+        rsstwritelog(LOG_ERROR, "Record '%d' type '%s' could not be added.", count, "sql" );
+        retval=-1;
+        break;
+      }
+      count++;
+    }
+  }
+
+  /*
+   * Clean up
+   */
+  sqlite3_finalize(ppstmtsimple);
+  sqlite3_finalize(ppstmtsql);
+
+  return retval;
+}
+
+/*
+ * Add a downloaded record to the lastdownload table
+ * @arguments
+ * handle RSS-torrent handle
+ * filterid The id of the sql/simple filter
+ * downedid The id from the downloaded
+ * type simple or sql filter
+ * @return
+ * 0 in success, else -1
+ */
+int rsstaddlastdownload(rsstor_handle *handle, int filterid, int downedid, FILTER_TYPE type)
+{
+  int rc=0;
+  int retval=0;
+  char *query=NULL;
+
+  /*
+   * Queries used to update the SQL and SIMPLE lastdownload entries
+   */
+  char *simplequery = "INSERT OR REPLACE INTO lastdownload (simple_id, downloaded_id) VALUES (?1, ?2); COMMIT";
+  char *sqlquery = "INSERT OR REPLACE INTO lastdownload (sql_id, downloaded_id) VALUES (?1, ?2); COMMIT";
+
+  /*
+   * Test the type of filter we need to handle
+   */
+  switch(type) {
+    case simple:
+      query=simplequery;
+      break;
+    case sql:
+      query=sqlquery;
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "Last downloaded invoked with unknown type %s:%d\n", __FILE__, __LINE__);
+      return -1;
+  }
+
+  /*
+   * Execute the query to get all simple filter last downloads
+   */
+  rc = rsstexecutequery(handle->db, query, "dd", filterid, downedid);
+  if(rc < 0){
+    rsstwritelog(LOG_ERROR, "Query for retrieving simple filter last downloads. %s:%d\n", __FILE__, __LINE__);
+    retval=-1;
+  }
+
+  /*
+   * Done
+   */
+  return retval;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/lastdownloaded.h b/tags/swarmtv-0.9.2/libswarmtv/lastdownloaded.h
new file mode 100644
index 0000000..b3a98ee
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/lastdownloaded.h
@@ -0,0 +1,56 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Free a last downloaded structure.
+ * @Arguments
+ * downed pointer to the downloaded structure
+ */
+void rsstfreelastdowned(lastdowned_struct *downed);
+
+/*
+ * Free the downloaded container and its contents
+ * When the container it self is allocated, it should be freed separately
+ * @Arguments
+ * container pointer to the downed container to be freed
+ */
+void rsstfreelastdownedcontainer(lastdowned_container *container);
+
+/*
+ * Get information of the last downloads and the filters that produced them
+ * @Arguments
+ * handle RSS-torrent handle
+ * container the pointer pointer to the container
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rsstgetlastdownloaded(rsstor_handle *handle, lastdowned_container *container);
+
+/*
+ * Add a downloaded record to the lastdownload table
+ * @arguments
+ * handle RSS-torrent handle
+ * filterid The id of the sql/simple filter
+ * downedid The id from the downloaded
+ * type simple or sql filter
+ * @return
+ * 0 in success, else -1
+ */
+int rsstaddlastdownload(rsstor_handle *handle, int filterid, int downedid, FILTER_TYPE type);
diff --git a/tags/swarmtv-0.9.2/libswarmtv/libswarmtv.pc.template b/tags/swarmtv-0.9.2/libswarmtv/libswarmtv.pc.template
new file mode 100644
index 0000000..72243e6
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/libswarmtv.pc.template
@@ -0,0 +1,12 @@
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: Lib Swarmtv
+Description: Lib SwarmTv RSS television
+Version: 1.0.0
+Libs: -lswarmtv
+Cflags: -I${includedir}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/libswarmtv.pro b/tags/swarmtv-0.9.2/libswarmtv/libswarmtv.pro
new file mode 100644
index 0000000..70d1bd2
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/libswarmtv.pro
@@ -0,0 +1,126 @@
+######################################################################
+# JinXed Thu Mar 10 00:37:33 2011 Anne Jan Brouwer
+######################################################################
+
+TEMPLATE = lib
+win32{
+TARGET = libswarmtv
+}
+unix {
+TARGET = swarmtv
+}
+DEPENDPATH += . \
+              filehandler \
+              filehandler/nzb \
+              filehandler/torrent \
+              srcparser/defaultrss \
+              srcparser/twitter
+INCLUDEPATH += . \
+               srcparser/defaultrss \
+               srcparser/twitter \
+               filehandler \
+               filehandler/torrent \
+               filehandler/nzb
+CONFIG += dll link_pkgconfig
+PKGCONFIG += xml2po sqlite3 dbus-1 glib-2.0 dbus-glib-1
+LIBS += -lcurl -lpcre
+unix{
+LIBS += -lesmtp
+}
+win32{
+LIBS += -lsqlite3 -lxml2 -lcurldll -liconv -lwsock32
+}
+target.path = /usr/local/lib/
+headers.path = /usr/local/include/
+INSTALLS += target headers
+
+# Input
+HEADERS += baretitle.h \
+           callback.h \
+           config.h \
+           curlfile.h \
+           database.h \
+           databaseimpl.h \
+           filesystem.h \
+           filter.h \
+           lastdownloaded.h \
+           logfile.h \
+           regexp.h \
+           runloop.h \
+           sandboxdb.h \
+           setup.h \
+           simplefilter.h \
+           source.h \
+           stats.h \
+           swarmtv.h \
+           testfilter.h \
+           torrentdb.h \
+           torrentdownload.h \
+           types.h \
+           filehandler/filehandler.h \
+           filehandler/nzb/findnzb.h \
+           filehandler/nzb/nzbparse.h \
+           filehandler/torrent/findtorrent.h \
+           filehandler/torrent/tbl.h \
+           filehandler/torrent/torrentparse.h \
+           srcparser/defaultrss/defaultrss.h \
+           srcparser/defaultrss/disectdate.h \
+           srcparser/defaultrss/disectdescription.h \
+           srcparser/defaultrss/rsscategory.h \
+           srcparser/defaultrss/rsslink.h \
+           srcparser/defaultrss/rssparse.h \
+           srcparser/defaultrss/rsspubdate.h \
+           srcparser/defaultrss/rssseasonepisode.h \
+           srcparser/defaultrss/rssseedspeers.h \
+           srcparser/defaultrss/rsssize.h \
+           srcparser/defaultrss/rsstitle.h \
+           srcparser/twitter/parsedate.h \
+           srcparser/twitter/splittext.h \
+           srcparser/twitter/twitparse.h \
+           srcparser/twitter/twitter.h
+SOURCES += baretitle.c \
+           callback.c \
+           config.c \
+           curlfile.c \
+           database.c \
+           databaseimpl.c \
+           filesystem.c \
+           filter.c \
+           lastdownloaded.c \
+           logfile.c \
+           regexp.c \
+           runloop.c \
+           sandboxdb.c \
+           setup.c \
+           simplefilter.c \
+           source.c \
+           stats.c \
+           testfilter.c \
+           torrentdb.c \
+           torrentdownload.c \
+           filehandler/filehandler.c \
+           filehandler/nzb/findnzb.c \
+           filehandler/nzb/nzbparse.c \
+           filehandler/torrent/findtorrent.c \
+           filehandler/torrent/tbl.c \
+           filehandler/torrent/torrentparse.c \
+           srcparser/defaultrss/defaultrss.c \
+           srcparser/defaultrss/disectdate.c \
+           srcparser/defaultrss/disectdescription.c \
+           srcparser/defaultrss/rsscategory.c \
+           srcparser/defaultrss/rsslink.c \
+           srcparser/defaultrss/rssparse.c \
+           srcparser/defaultrss/rsspubdate.c \
+           srcparser/defaultrss/rssseasonepisode.c \
+           srcparser/defaultrss/rssseedspeers.c \
+           srcparser/defaultrss/rsssize.c \
+           srcparser/defaultrss/rsstitle.c \
+           srcparser/twitter/parsedate.c \
+           srcparser/twitter/splittext.c \
+           srcparser/twitter/twitparse.c \
+           srcparser/twitter/twitter.c
+
+win32 {
+HEADERS += workarounds.h
+SOURCES += workarounds.c
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/logfile.c b/tags/swarmtv-0.9.2/libswarmtv/logfile.c
new file mode 100644
index 0000000..c8077a9
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/logfile.c
@@ -0,0 +1,189 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+#include <sqlite3.h>
+
+#include "swarmtv.h"
+#include "types.h"
+#include "config.h"
+#include "filesystem.h"
+#include "callback.h"
+
+#define LOG_DEBUG   1
+#define LOG_NORMAL  2
+#define LOG_ERROR   3
+
+/*
+ * Define log levels
+ */
+#ifdef DEBUG
+  #define LOG_LEVEL 0
+#endif
+
+#ifdef ERROR
+  #define LOG_LEVEL 2
+#endif
+
+#ifndef DEBUG
+#ifndef ERROR
+  #define LOG_LEVEL 1
+#endif
+#endif
+
+
+
+int rsstinitlog(char *logpath);
+
+/*
+ * Open log file getting path from database
+ */
+int rsstinitlogdb(sqlite3 *db)
+{
+  char  *configpath = NULL;
+  int   rc=9;
+	rsstor_handle handle;
+
+	/*
+	 * REMOVE IN THE FUTURE
+	 */
+  memset(&handle, 0, sizeof(rsstor_handle));
+	handle.db = db;
+
+  /*
+   * Get path
+   * int configgetproperty(sqlite3 *db, char *prop, char **value);
+   */
+  rc =rsstconfiggetproperty(&handle, CONF_LOGFILE, &configpath);
+
+  /*
+   * open log file
+   */
+  if(rc == 0){
+    rc = rsstinitlog(configpath);
+  }
+
+  /*
+   * clean up
+   */
+  free(configpath);
+
+  /*
+   * Return rc
+   */
+  return rc;
+}
+
+
+/*
+ * Initialize log file
+ * @Arguments
+ * logpath path to the logfile
+ * @return Return 0 when success, Return -1 when fail
+ */
+int rsstinitlog(char *logpath)
+{
+	FILE *log=NULL;
+  char *fullpath=NULL;
+  int retval=0;
+
+  rsstcompletepath(logpath, &fullpath);
+
+  log = fopen(fullpath,"a+");
+  if(log != NULL) {
+    fclose(log);
+  } else {
+    fprintf(stderr, "Could not initiate logfile at '%s'\n", fullpath);
+    fprintf(stderr, "log to default out instead.\n");
+    log=stdout;
+  }
+
+  free(fullpath);
+
+  /*
+   * Return code.
+   */
+  return retval;
+}
+
+/*
+ * Log an entry
+ */
+int rsstwritelog(int level, char *str,...)
+{
+  char            s[30];
+  size_t          i=0;
+  struct tm       tim;
+  time_t          now=0;
+
+  if(level > LOG_LEVEL) {
+    /*
+     * What time is now ?
+     */
+    now = time(NULL);
+    tim = *(localtime(&now));
+    i = strftime(s,30,"%H:%M:%S",&tim);
+
+    /*
+     * Build string
+     */
+    printf("%s ",s);
+    switch(level) {
+      case LOG_DEBUG:
+        printf("(D)");
+        break;
+      case LOG_NORMAL:
+        printf("(N)");
+        break;
+      case LOG_ERROR:
+        printf("(E)");
+        break;
+    }
+    printf(" : ");
+
+    /*
+     * Put the error out there
+     */
+    va_list arglist;
+    va_start(arglist,str);
+    vprintf(str,arglist);
+    va_end(arglist);
+    printf(" \n");
+
+		fflush(stdout);
+  }
+
+  return 1;
+}
+
+
+/*
+ * Close log file
+ */
+void rsstcloselog()
+{
+  /*
+   * Closing log file.
+   */
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/logfile.h b/tags/swarmtv-0.9.2/libswarmtv/logfile.h
new file mode 100644
index 0000000..d0438f9
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/logfile.h
@@ -0,0 +1,63 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#define LOG_DEBUG   1
+#define LOG_NORMAL  2
+#define LOG_ERROR   3
+
+/*
+ * External include.
+ */
+#include <sqlite3.h>
+
+/*
+ * Open log file getting path from database
+ * @return
+ * 0 when successful
+ * !0 when fail
+ */
+int rsstinitlogdb(sqlite3 *db);
+
+/*
+ * Initialize log file
+ * @arguments
+ * logpath the path to store the log
+ * @return
+ * 0 when successful
+ * !0 when fail
+ */
+int rsstinitlog(char *logpath);
+
+/*
+ * Log an entry
+ * LOG_DEBUG, LOG_NORMAL, LOG_ERROR
+ * @arguments
+ * level the log level (see log level defines)
+ * str the string to log
+ * ... the arguments to fill out in the log line
+ * @return
+ * returns 1 for now in all cases
+ */
+int rsstwritelog(int level, char *str,...);
+
+/*
+ * Close log file
+ */
+void rsstcloselog();
diff --git a/tags/swarmtv-0.9.2/libswarmtv/regexp.c b/tags/swarmtv-0.9.2/libswarmtv/regexp.c
new file mode 100644
index 0000000..faf658d
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/regexp.c
@@ -0,0 +1,339 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <pcre.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "logfile.h"
+#include "regexp.h"
+
+/*
+ * Number of output vector items
+ */
+#define   OVECSIZE 20
+#define   MATCHSIZE 20
+
+
+
+/*
+ * This function copies and allocates the destination memory.
+ * don't forget to free the destination after use.
+ */
+int rsstalloccopy(char **dest, const char *src, const size_t size)
+{
+	/*
+	 * Allocate the memory
+	 */
+	*dest=calloc(1, size+1);
+
+	/*
+	 * Copy the string to it.
+	 */
+	memcpy(*dest, src, size);
+
+	/*
+	 * Return 0 on success, otherwise one-zero
+	 */
+	return !*dest;
+}
+
+
+/*
+ * Cleanup strings from XML
+ */
+void rsstcleanupstring(char *string)
+{
+  char *cur;
+
+  /*
+   * check if sane
+   */
+  if(strlen(string) == 0){
+    return;
+  }
+
+  /*
+   * translate unwanted chars to spaces.
+   */
+  cur = string;
+  while(*cur != '\0') {
+    switch(*cur){
+      case '.':
+      case '_':
+        *cur = ' ';
+        break;
+    }
+    cur++;
+  }
+
+  /*
+   * Remove spaces at begin
+   */
+  if(*string == ' ') {
+    memmove(string, string+1, strlen(string)-1);
+    *(string+strlen(string)-1) = '\0';
+  }
+}
+
+
+/*
+ * Simple routine to compare a string to a regexp
+ * @Arguments
+ * regexp   Regular expression to match.
+ * string   String to match regular expression on.
+ * @Returns
+ * 0 no match
+ * 1 match
+ * -1 error
+ */
+int rsstcomregexp(char *regexp, char *string)
+{
+  pcre *p;
+  const char *errmsg;
+  int   errpos;
+  int   ovector[MATCHSIZE];
+  int   rc;
+  int   outval = -1;
+
+  /*
+   * Compile the regexp to split the two strings.
+   */
+  p = pcre_compile(regexp, 0, &errmsg, &errpos, 0);
+  if (p == NULL) {
+    /*
+		 * Should not happen, because init has already tested and set to NULL on error
+		 */
+    rsstwritelog(LOG_ERROR, "Ouch! Can't compile regular expression: %s (char %i) %s:%d",
+        errmsg, errpos, __FILE__, __LINE__);
+  }
+
+  /*
+   * execute regexp
+   */
+  rc = pcre_exec (
+      p,                   /* the compiled pattern */
+      0,                    /* no extra data - pattern was not studied */
+      string,                  /* the string to match */
+      strlen(string),          /* the length of the string */
+      0,                    /* start at offset 0 in the subject */
+      0,                    /* default options */
+      ovector,              /* output vector for substring information */
+      MATCHSIZE);           /* number of elements in the output vector */
+  /*
+   * handle output
+   */
+  if(rc == PCRE_ERROR_NOMATCH) {
+    outval=0;
+  }
+  else if (rc == PCRE_ERROR_MATCHLIMIT) {
+    rsstwritelog(LOG_ERROR, "PCRE produced PCRE_ERROR_MATCHLIMIT for regexp '%s' and text '%s'", regexp, string);
+    outval=-1;
+  } else {
+    /*
+     * Found a match !
+     */
+    outval=1;
+  }
+
+  /*
+   * Clean up !
+   */
+  pcre_free(p);
+
+  return outval;
+}
+
+
+/*
+ * This routine returns a string pointing to the first captured string.
+ */
+int rsstcapturefirstmatch(char *regexp, int flag, char *string, char **match)
+{
+  pcre *p=NULL;
+  const char *errmsg=NULL;
+  int   errpos=0;
+  int   ovector[MATCHSIZE];
+  int   rc=0;
+  int   i=0;
+
+  /*
+   * Compile the regexp the split the two strings.
+   */
+  p = pcre_compile(regexp, 0, &errmsg, &errpos, 0);
+  if (p == NULL) {
+    /* should not happen, because init has already tested and set to NULL on error */
+    //rsstwritelog(LOG_ERROR, "Ouch! Can't compile regular expression: %s (char %i) %s:%d",
+    //    errmsg, errpos, __FILE__, __LINE__);
+    fprintf(stderr, "Ouch! Can't compile regular expression: %s (char %i) %s:%d", errmsg, errpos, __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * execute regexp
+   */
+  rc = pcre_exec (
+      p,                    /* the compiled pattern */
+      0,                    /* no extra data - pattern was not studied */
+      string,                /* the string to match */
+      strlen(string),        /* the length of the string */
+      0,                    /* start at offset 0 in the subject */
+      flag,                 /* default options */
+      ovector,              /* output vector for substring information */
+      MATCHSIZE);     /* number of elements in the output vector */
+  if (rc < 0) {
+    switch (rc) {
+      case PCRE_ERROR_NOMATCH:
+        //rsstwritelog(LOG_ERROR, "String could not be split. %s:%d", __FILE__, __LINE__);
+        //fprintf(stderr, "No match found '%s'. %s:%d", regexp, __FILE__, __LINE__);
+        break;
+
+      default:
+        fprintf(stderr, "Error in regexp matching '%s'. %s:%d\n", regexp, __FILE__, __LINE__);
+        //rsstwritelog(LOG_ERROR, "Error while matching: %d %s:%d", rc, __FILE__, __LINE__);
+        break;
+    }
+    free(p);
+    return rc;
+  }
+
+  /*
+   * extract both strings.
+   */
+  i = 1;
+  *match = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(*match, "%.*s", ovector[2*i+1] - ovector[2*i], string + ovector[2*i]);
+
+  //printf("o'%s' r'%s' b%d e%d s%d v'%s'\n", string, regexp,  ovector[2*i], ovector[2*i+1], ovector[2*i+1]-ovector[2*i], *match);
+
+  /*
+   * Get the 2 strings and put them in the output strings.
+   * Both need to be freed afterwards
+   */
+
+  pcre_free(p);
+
+  return 0;
+}
+
+
+/*
+ * Extract user name and password from URL
+ * Accepts passwords in the URL https://<user>:<password>@<host>:<port>/<path>
+ * returns 0 on no user name/passwd
+ * When returning 1 cleanurl and userpass are both set, and should be freed after use.
+ */
+int rsstgetusernamepassword(char *url, char **cleanurl, char **userpass)
+{
+  pcre 		*p=NULL;
+  int   	ovector[OVECSIZE];
+  const char *errmsg=NULL;
+  int   	errpos=0;
+	char 		*regexp="^(https?://)([^:]+:[^@]+)@(.*)$";
+	char 		*protocol=NULL;
+	char 		*hostpath=NULL;
+	int 		i=0;
+	size_t	urlsize=0;
+	int			rc=0;
+
+	/*
+	 * Init input variables.
+	 */
+	*cleanurl=NULL;
+	*userpass=NULL;
+
+  /*
+   * Compile the regexp to split the two strings.
+   */
+  p = pcre_compile(regexp, 0, &errmsg, &errpos, 0);
+  if (p == NULL) {
+    /* should not happen, because init has already tested and set to NULL on error */
+    fprintf(stderr, "Ouch! Can't compile regular expression: %s (char %i) %s:%d",
+        errmsg, errpos, __FILE__, __LINE__);
+		return -1;
+  }
+
+  /*
+   * execute regexp
+   */
+  rc = pcre_exec (
+      p,                   	/* the compiled pattern */
+      0,                    /* no extra data - pattern was not studied */
+      url,                  /* the string to match */
+      strlen(url),          /* the length of the string */
+      0,                    /* start at offset 0 in the subject */
+      0,                    /* default options */
+      ovector,              /* output vector for substring information */
+      OVECSIZE);           	/* number of elements in the output vector */
+
+	/*
+	 * No match is return 0
+	 */
+  if (rc < 0) {
+    switch (rc) {
+      case PCRE_ERROR_NOMATCH:
+				/*
+				 * no user name/password match
+				 */
+				pcre_free(p);
+				return 0;
+        break;
+      default:
+        rsstwritelog(LOG_ERROR, "Error while matching URL. %d %s:%d", rc, __FILE__, __LINE__);
+        break;
+    }
+    free(p);
+    return -1;
+  }
+
+	/*
+	 * Match, get URL and userpass
+	 */
+  i = 1;
+  protocol = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(protocol, "%.*s", ovector[2*i+1] - ovector[2*i], url + ovector[2*i]);
+  i = 2;
+  *userpass = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(*userpass, "%.*s", ovector[2*i+1] - ovector[2*i], url + ovector[2*i]);
+  i = 3;
+  hostpath = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(hostpath, "%.*s", ovector[2*i+1] - ovector[2*i], url + ovector[2*i]);
+
+	/*
+	 * Set cleanurl and userpass
+	 * return 1
+	 */
+	urlsize = strlen(protocol) + strlen(hostpath) + 1;
+  *cleanurl = calloc(1, urlsize);
+	snprintf(*cleanurl, urlsize, "%s%s", protocol, hostpath);
+
+	/*
+	 * free tempstuff
+	 */
+	pcre_free(p);
+	free(protocol);
+	free(hostpath);
+
+	return 1;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/regexp.h b/tags/swarmtv-0.9.2/libswarmtv/regexp.h
new file mode 100644
index 0000000..05be488
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/regexp.h
@@ -0,0 +1,81 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#define   BUFSIZE 20
+
+/*
+ * This function copies and allocates the destination memory.
+ * don't forget to free the destination after use.
+ * @arguments
+ * dest pointer to the destination the string is copied to
+ * src pointer to the source string
+ * size the size of the source string
+ * @return
+ * 0 when okay, otherwise !0
+ */
+int rsstalloccopy(char **dest, const char *src, const size_t size);
+
+/*
+ * Cleanup strings from XML
+ * @arguments
+ * string pointer to string to clean up
+ */
+void rsstcleanupstring(char *string);
+
+/*
+ * Simple routine to compare a string to a regexp
+ * @arguments
+ * regexp regexp to match to.
+ * string string to be matched.
+ * @returns
+ * 1 when match
+ * 0 when no match
+ * -1 on error
+ */
+int rsstcomregexp(char *regexp, char *string);
+
+/*
+ * This routine returns a string pointing to the first captured string.
+ * @arguments
+ * regexp regexp to capture
+ * flag regexp flag to set match mode (look at pcre_exec)
+ * string string to capture match from
+ * match pointer to store match, should be freed after use
+ * @return
+ * 0 on success
+ * -1 on error
+ */
+int rsstcapturefirstmatch(char *regexp, int flag, char *string, char **match);
+
+/*
+ * Extract user name and password from URL
+ * Accepts passwords in the URL https://<user>:<password>@<host>:<port>/<path>
+ * returns 0 on no user name/password
+ * When returning 1 cleanurl and userpass are both set, and should be freed.
+ * @arguments
+ * url the URL to split
+ * cleanurl the URL without the user name and password
+ * userpass user name and password in <user name>:<password> format.
+ * @return
+ * return 1 when user name and password are found
+ * else return 0
+ */
+int rsstgetusernamepassword(char *url, char **cleanurl, char **userpass);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/runloop.c b/tags/swarmtv-0.9.2/libswarmtv/runloop.c
new file mode 100644
index 0000000..3116dc1
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/runloop.c
@@ -0,0 +1,362 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sqlite3.h>
+#include <time.h>
+#include <string.h>
+
+#include "types.h"
+#include "curlfile.h"
+#include "config.h"
+#include "filter.h"
+#include "runloop.h"
+#include "torrentdownload.h"
+#include "simplefilter.h"
+#include "logfile.h"
+#include "torrentdb.h"
+#include "callback.h"
+#include "database.h"
+
+#ifdef __MINGW32__
+#include <windows.h>
+#define sleep(n) Sleep(1000 * n)
+#endif
+
+/*
+ * Parser includes
+ */
+#include "srcparser/defaultrss/defaultrss.h"
+#include "srcparser/twitter/twitter.h"
+
+#define true (1==1)
+#define ERRORLEN 1024
+
+/*
+ * Query to get sources to download.
+ */
+const char *query="select name, url, parser, metatype, id from sources";
+
+/*
+ * Apply a filter to the downloaded RSS code.
+ * This routine holds the references to different kind of filters.
+ * (For now only RSS-torrent.com format)
+ * Return
+ * 0 when okay, on error -1
+ */
+static int parserdownload(rsstor_handle *handle, struct_download *downed, MemoryStruct *rssfile)
+{
+  int rc;
+
+  /*
+   * compare the filter string and pass the downloaded file to the correct filtering routine.
+   */
+  if(strcmp(downed->parser, "defaultrss") == 0) {
+    //printf("Found a file for filter %s\n", filter);
+    rc = defaultrss(handle, downed->name, downed->url, downed->parser, downed->metatype, rssfile);
+    return 0;
+  }
+
+  if(strcmp(downed->parser, "twitter") == 0) {
+    //printf("Found a file for filter %s\n", filter);
+    rc = twitter(handle, downed->name, downed->url, downed->parser, downed->metatype, rssfile);
+
+    return 0;
+  }
+
+  /*
+   * When no filter found.
+   */
+  rsstwritelog(LOG_ERROR, "No filter found '%s', ignoring file %s:%d", downed->parser, __FILE__, __LINE__);
+  return -1;
+}
+
+/*
+ * Get the config value for the amount of time we want to retain data.
+ * Delete the older data.
+ * Exits status 1 on error
+ */
+static void deleteold(rsstor_handle *handle)
+{
+	int rc;
+	int days;
+
+	/*
+	 * Get the config value.
+	 */
+	rc = rsstconfiggetint(handle, CONF_RETAIN, &days);
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Config value %s not set ! %s:%d", __FILE__, __LINE__);
+		exit(1);
+	}
+
+
+	/*
+	 * Delete the content.
+	 */
+	rc = rsstdeloldnewtorents(handle, (unsigned int) days);
+	if(rc == -1) {
+		rsstwritelog(LOG_ERROR, "Database inconsistent, could not remove old newtorrent entries!", __FILE__, __LINE__);
+		exit(1);
+	}
+}
+
+
+/*
+ * Do the main work here
+ * Download the feeds and pars them.
+ */
+static void dowork(rsstor_handle *handle){
+  /*
+   * Use the database query to get the sources.
+   */
+  sqlite3_stmt            *ppStmt=NULL;
+  const char              *pzTail=NULL;
+  int                     rc=0;
+  int                     step_rc=0;
+  char                    *zErrMsg=NULL;
+  char           					*name=NULL;
+  char           					*url=NULL;
+  //char                    *metatype=NULL;
+  //char           					*parser=NULL;
+	char										errstr[ERRORLEN+1];
+	//int											id=0;
+  MemoryStruct            rssfile;
+  struct_download         downed;
+
+  /*
+   * Prepare the Sqlite statement
+   */
+  rc = rsst_sqlite3_prepare(
+      handle->db,                 /* Database handle */
+      query,            /* SQL statement, UTF-8 encoded */
+      strlen(query),    /* Maximum length of zSql in bytes. */
+      &ppStmt,             /* OUT: Statement handle */
+      &pzTail              /* OUT: Pointer to unused portion of zSql */
+      );
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return;
+  }
+
+  /*
+   * loop until the end of the dataset is found
+   */
+  while( SQLITE_DONE != (step_rc = sqlite3_step(ppStmt))) {
+
+    /*
+     * Get the values
+     */
+    memset(&downed, 0, sizeof(downed));
+    downed.name     = (char *) sqlite3_column_text(ppStmt, 0);
+    downed.url      = (char *) sqlite3_column_text(ppStmt, 1);
+    downed.parser   = (char *) sqlite3_column_text(ppStmt, 2);
+    downed.metatype = (char *) sqlite3_column_text(ppStmt, 3);
+		downed.id       = 				 sqlite3_column_int (ppStmt, 4);
+
+    rc = rsstdownloadtobuffer(handle, downed.url, &rssfile);
+    if(rc == 0) {
+      /*
+       * Download succeeded.
+       */
+      rsstwritelog(LOG_DEBUG, "Download succeeded for %s : %s : %s", downed.name, downed.url, downed.metatype);
+
+      /*
+       * Filter the stuff and add it to the database.
+       * rc = parserdownload(handle, name, url, metatype, parser, &rssfile);
+       */
+      rc = parserdownload(handle, &downed, &rssfile);
+      if(rc == 0) {
+				/*
+				 * Callback RSS download is okay
+				 */
+        downed.status=0;
+        rsstexecallbacks(handle, rssdownload, &downed);
+
+			} else {
+				/*
+				 * Call RSS download has failed because the content could not be parsed
+				 */
+				snprintf(errstr, ERRORLEN, "RSS source '%s' '%s' failed to parse.", name, url);
+        downed.errstr=errstr;
+        downed.status=-1;
+        rsstexecallbacks(handle, rssdownload, &downed);
+        rsstwritelog(LOG_ERROR, "Filtering failed for %s : %s %s:%d", name, url, __FILE__, __LINE__);
+      }
+
+    } else {
+			/*
+			 * Call RSS download has failed, because file could not be retrieved.
+			 */
+      snprintf(errstr, ERRORLEN, "RSS source '%s' '%s' failed to parse.", name, url);
+      downed.errstr=errstr;
+      downed.status=-1;
+      rsstexecallbacks(handle, rssdownload, &downed);
+      rsstwritelog(LOG_ERROR, "Download failed for %s : %s %s:%d", name, url, __FILE__, __LINE__);
+    }
+    rsstfreedownload(&rssfile);
+  }
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppStmt);
+}
+
+/*
+ * Do a cycle of workload
+ * @Arguments
+ * handle
+ * @return
+ * 0 for now
+ */
+int runcycle(rsstor_handle *handle)
+{
+  /*
+   * Call callback to signal start of update
+   */
+  rsstexecallbacks(handle, startcycle, NULL);
+
+
+  /*
+   * work through the sources and process them
+   */
+  dowork(handle);
+
+  /*
+   * Execute SQL and simple filters on new entries.
+   */
+  rsstdownloadtorrents(handle);
+  rsstdownloadsimple(handle, 0);
+
+  /*
+   * Torrents are no longer new
+   */
+  rsstnonewtorrents(handle);
+  deleteold(handle);
+
+  /*
+   * Call callback to signal start of update, -1 as parameter, as we don't know anything about time
+   */
+  rsstexecallbacks(handle, endcycle, NULL);
+
+  return 0;
+}
+
+/*
+ * Main loop, dispatches tasks
+ * When onetime != 0 run once then exit
+ * @Argument
+ * onetime when ! 0 runloop only runs one time.
+ * @Return
+ * 0 for now.
+ */
+int rsstrunloop(rsstor_handle *handle, LOOPMODE onetime)
+{
+  int 			rc=0;
+  int				timewait=0;
+  time_t 		before=0;
+  time_t 		after=0;
+  int    		timeleft=0;
+
+  rc = rsstconfiggetint(handle, CONF_REFRESH, &timewait);
+  if(onetime == 0) {
+    rsstwritelog(LOG_NORMAL, "Starting daemon, refresh %ds", timewait);
+  } else {
+    rsstwritelog(LOG_NORMAL, "Running once.");
+  }
+
+  /*
+   * Keep running until...
+   */
+  while(true){
+    /*
+     * Call callback to signal start of update
+     */
+    rc = rsstexecallbacks(handle, startcycle, NULL);
+    if(rc != 0){
+      rsstwritelog(LOG_ERROR, "Error returned by 'startup' callback. %s:%d", __FILE__, __LINE__);
+    }
+
+    before = time(NULL);
+    /*
+     * work through the sources and process them
+     */
+    rsstwritelog(LOG_DEBUG,"Downloading RSS feed(s)");
+    dowork(handle);
+
+
+		/*
+		 * Execute SQL and simple filters on new entries.
+		 */
+    rsstwritelog(LOG_DEBUG,"Checking for new torrents to download.");
+    rsstdownloadtorrents(handle);
+    rsstdownloadsimple(handle, 0);
+
+    /*
+     * Torrents are no longer new
+     */
+    rsstnonewtorrents(handle);
+		deleteold(handle);
+
+    /*
+     * Calculate sleep time left.
+     */
+    after = time(NULL);
+    timeleft = timewait - (after - before);
+    if(timeleft < 0) {
+      timeleft = timewait;
+    }
+
+		/*
+		 * Call callback to signal start of update
+		 * Time left is also given when run once
+		 */
+    rc = rsstexecallbacks(handle, endcycle, NULL);
+		if(rc != 0){
+			rsstwritelog(LOG_ERROR, "Error returned by 'endup' callback. %s:%d", __FILE__, __LINE__);
+		}
+
+    /*
+     * Run once.
+     */
+    if(onetime == (LOOPMODE) once) {
+      break;
+    }
+
+		/*
+		 * Inform user
+		 */
+    rsstwritelog(LOG_NORMAL,"Refresh done, sleeping %d seconds.", timeleft);
+
+    /*
+     * Sleep timeout
+     */
+    sleep(timeleft);
+  }
+
+  /*
+   * done.
+   */
+  return 0;
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/runloop.h b/tags/swarmtv-0.9.2/libswarmtv/runloop.h
new file mode 100644
index 0000000..7928cc9
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/runloop.h
@@ -0,0 +1,39 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Main loop, dispatches tasks
+ * @arguments
+ * handle RSS-torrent handle
+ * onetime When onetime != 0 run once then exit
+ * @return
+ * 0 for now.
+ */
+int rsstrunloop(rsstor_handle *handle, LOOPMODE onetime);
+
+/*
+ * Do a cycle of workload
+ * @Arguments
+ * handle
+ * @return
+ * 0 for now
+ */
+int runcycle(rsstor_handle *handle);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/sandboxdb.c b/tags/swarmtv-0.9.2/libswarmtv/sandboxdb.c
new file mode 100644
index 0000000..f98aa3b
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/sandboxdb.c
@@ -0,0 +1,195 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2010
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sqlite3.h>
+
+#include "types.h"
+#include "sandboxdb.h"
+#include "logfile.h"
+//#include "database.h"
+#include "databaseimpl.h"
+#include "filesystem.h"
+
+
+/*
+ * Create a filecopy of the database.
+ * Arguments
+ * outfile		Destination path
+ * infile			Source path
+ * returns
+ * 0 on success -1 on failure
+ */
+static int copyfile(char *outfile, char *infile)
+{
+  int inF, ouF;
+  char line[512];
+  char *fullinfile=NULL;
+  char *fulloutfile=NULL;
+  int bytes;
+  int rc;
+
+  rsstcompletepath(outfile, &fulloutfile);
+  rsstcompletepath(infile, &fullinfile);
+
+  /*
+   * Open input and output file.
+   */
+  if((inF = open(fullinfile, O_RDONLY)) == -1) {
+    rsstwritelog(LOG_ERROR, "Could not open read file '%s' %s:%d", infile, __FILE__, __LINE__);
+    free(fulloutfile);
+    free(fullinfile);
+    return -1;
+  }
+
+  if((ouF = open(fulloutfile, O_WRONLY | O_CREAT, S_IRWXU )) == -1) {
+    rsstwritelog(LOG_ERROR, "Could not open write file '%s' %s:%d", outfile, __FILE__, __LINE__);
+    close(inF);
+    free(fulloutfile);
+    free(fullinfile);
+    return -1;
+  }
+
+  /*
+   * free temp filenames
+   */
+  free(fulloutfile);
+  free(fullinfile);
+
+  /*
+   * Do the copying
+   */
+  while((bytes = read(inF, line, sizeof(line))) > 0){
+    rc = write(ouF, line, bytes);
+    if(rc == -1) {
+      rsstwritelog(LOG_ERROR, "Error writing to file '%s' %s:%d", outfile, __FILE__, __LINE__);
+      break;
+    }
+  }
+  if(bytes == -1){
+    rsstwritelog(LOG_ERROR, "Error reading from file '%s' %s:%d", infile, __FILE__, __LINE__);
+  }
+
+  /*
+   * Do the cleanup
+   */
+  close(inF);
+  close(ouF);
+
+  return 0;
+}
+
+
+/*
+ * Create copy of database
+ * and create a sqlite3 pointer to the database copy.
+ * arguments
+ * sourcedbname		path to source database
+ * sandboxdbname	path to destination database
+ * return
+ * returns pointer to sandbox db.
+ */
+sandboxdb *rsstcreatesandbox(char *sourcedbname, char *sandboxdbname)
+{
+  int       		 rc=0;
+  sandboxdb 		*sandbox=NULL;
+	rsstor_handle	 handle;
+
+  /*
+   * Init struct
+   */
+  sandbox = calloc(sizeof(sandboxdb), 1);
+  sandbox->filename = calloc(strlen(sandboxdbname)+1, 1);
+  strcpy(sandbox->filename, sandboxdbname);
+
+  /*
+   * Create copy of database.
+   */
+  rc = copyfile(sandboxdbname, sourcedbname);
+  if(rc == -1) {
+    return NULL;
+  }
+
+  /*
+   * create pointer to database
+   */
+  rc = rsstinitdatabase(sandboxdbname, &handle);
+  if(rc != SQLITE_OK) {
+    rsstwritelog(LOG_ERROR, "Sandbox database initialization failed %s:%d", __FILE__, __LINE__);
+    return NULL;
+  }
+
+	/*
+	 * Get db pointer to sandbox
+	 */
+	sandbox->db = handle.db;
+
+  /*
+   * Done !
+   */
+  return sandbox;
+}
+
+
+/*
+ * Close the database.
+ * delete the sandboxed database.
+ * Arguments
+ * Sandbox	Pointer the sandbox database
+ * Return
+ * 0 on succes otherwise -1
+ */
+int rsstclosesandbox(sandboxdb *sandbox)
+{
+  int   rc=0;
+  char *fullpath=NULL;
+
+  rsstcompletepath(sandbox->filename, &fullpath);
+
+  /*
+   * Close the sqlite database.
+   * No way to get dbpointer here
+   */
+  sqlite3_close(sandbox->db);
+
+  /*
+   * Delete file
+   */
+  rc = remove(fullpath);
+  if(rc != 0) {
+    rsstwritelog(LOG_ERROR, "Removing sandbox db file '%s' failed %s:%d", sandbox->filename, __FILE__, __LINE__);
+  }
+
+  /*
+   * Free struct
+   */
+  free(sandbox->filename);
+  free(sandbox);
+
+  free(fullpath);
+  return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/sandboxdb.h b/tags/swarmtv-0.9.2/libswarmtv/sandboxdb.h
new file mode 100644
index 0000000..97f6519
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/sandboxdb.h
@@ -0,0 +1,41 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2010
+ */
+
+/*
+ * Create copy of database
+ * and create a sqlite3 pointer to the database copy.
+ * @arguments
+ * sourcedbname source path to database
+ * sandboxdbname detination path to database
+ * @return
+ * pointer not sandbox database
+ */
+sandboxdb *rsstcreatesandbox(char *sourcedbname, char *sandboxdbname);
+
+/*
+ * Close the database.
+ * delete the sandboxed database.
+ * @arguments
+ * db pointer to sandbox db
+ * @returns
+ * 0 on succes otherwise -1
+ */
+int rsstclosesandbox(sandboxdb *db);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/setup.c b/tags/swarmtv-0.9.2/libswarmtv/setup.c
new file mode 100644
index 0000000..4c35300
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/setup.c
@@ -0,0 +1,276 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sqlite3.h>
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+#include <libxml/parser.h>
+
+#include "swarmtv.h"
+#include "types.h"
+#include "logfile.h"
+#include "filesystem.h"
+#include "setup.h"
+#include "database.h"
+#include "databaseimpl.h"
+#include "callback.h"
+
+/*
+ * Test if rsstorrentdir exists
+ * @returns
+ * return 0 when found, -1 if not found
+ */
+static int testrsstorrentdir()
+{
+	int 	rc=0;
+	char 	*fullpath=NULL;
+
+	rsstcompletepath(RSS_BASEDIR, &fullpath);
+
+	rc = rsstfsexists(fullpath);
+
+	free(fullpath);
+
+	return rc;
+}
+
+
+/*
+ * Create the torrent dir if rsstorrentdir does not exist
+ * @returns
+ * return 0 when found, -1 if not found
+ */
+static int makersstorrentdir()
+{
+	int 	rc=0;
+	char 	*fullpath=NULL;
+
+	/*
+	 * Resolv path and create directory
+	 */
+	rsstcompletepath(RSS_BASEDIR, &fullpath);
+	rc = rsstmakedir(fullpath);
+
+	free(fullpath);
+	return rc;
+}
+
+
+/*
+ * Initialize the callback structures
+ * @Arguments
+ * callbacks Structure holding the callback structures to be initialized.
+ * @return
+ * 0 when all was initialized well
+ */
+static int rsstinitcallbacks(struct_callbacks *callbacks)
+{
+  unsigned int count=0;
+	int retval=0;
+  struct_callback **deref;
+  struct_callback **walk;
+
+  /*
+   * Do a dirty cast
+   */
+  deref = (struct_callback**) callbacks;
+
+  /*
+   * Walk through the callbackstruct until all is initialized
+   */
+  for(count=0; count < (enum_callbacks) lastelement; count++)
+  {
+    walk = deref+count;
+    retval |= rsstinitcallback(walk);
+  }
+
+	/*
+	 * When all did go well, 0 is returned
+	 */
+	return retval;
+}
+
+
+/*
+ * Free the callback structures
+ * @Arguments
+ * callbacks Structure holding the callback structures to be Freed.
+ * @return
+ * 0 when all was initialized well
+ */
+void rsstfreecallbacks(struct_callbacks *callbacks)
+{
+  unsigned int count=0;
+  struct_callback **deref;
+  struct_callback *walk;
+
+  /*
+   * Do a dirty cast
+   */
+  deref = (struct_callback**) callbacks;
+
+  /*
+   * Walk through the callbackstruct until all is initialized
+   */
+  for(count=0; count < (enum_callbacks) lastelement; count++)
+  {
+    walk = deref[count];
+    rsstfreecallback(walk);
+  }
+}
+
+/*
+ * Check if the database is build with thread safe code.
+ * print a warning message
+ * @Arguments
+ * handle rsstorrent handle
+ * @return
+ * 0 when no thread support else !0
+ */
+static void rssfcheckthreadsafe()
+{
+#if SQLITE_VERSION_NUMBER >= 3003009
+  int rc=0;
+  rc = sqlite3_threadsafe();
+  if(rc == 0){
+    fprintf(stderr, "libSQLite3 was not built with thread support, make sure no instances of the library run at the same time.\n");
+  }
+#else
+  #warning SQlite3 library too old can not detect threadsafety
+#endif
+}
+
+
+/*
+ * Initialize RSS-torrent handle
+ * and make sure we have all subsystems operational
+ * @Return
+ * Pointer to handle on success, NULL on failure
+ */
+rsstor_handle *initrsstor()
+{
+	int rc=0;
+	rsstor_handle *handle=NULL;
+
+	/*
+	 * Retrieve complete path
+	 */
+	rc = testrsstorrentdir();
+	if(rc != 0) {
+		rc= makersstorrentdir();
+		if(rc != 0) {
+      return NULL;
+		}
+	}
+
+	/*
+	 * Allocate structure
+	 */
+	handle = calloc(1, sizeof(rsstor_handle));
+
+  /*
+   * Initialize the database
+   */
+  rc = rsstinitdatabase(RSST_DBFILE, handle);
+  if( rc!=SQLITE_OK ){
+    fprintf(stderr, "Initializing db : \'%s\' failed %s:%d\n", RSST_DBFILE, __FILE__, __LINE__);
+    return NULL;
+  }
+
+  /*
+   * Initialize lib curl
+   */
+  curl_global_init(CURL_GLOBAL_ALL);
+
+  /*
+   * open logfile
+   */
+  rc = rsstinitlogdb(handle->db);
+  if(rc != 0) {
+    return NULL;
+  }
+
+	/*
+	 * Initialize the callbackstructures
+	 */
+	rc = rsstinitcallbacks(&(handle->callback));
+	if(rc != 0) {
+    fprintf(stderr, "Allocation callbacks failed! %s:%d\n", __FILE__, __LINE__);
+		exit(1);
+	}
+
+  /*
+   * Check thread-safeness of database
+   */
+  rssfcheckthreadsafe();
+
+	/*
+	 * Return handle to struct
+	 */
+	return handle;
+}
+
+
+/*
+ * Free RSS-torrent handle
+ * @Arguments
+ * handle pointer to RSS-torrent structure
+ */
+void freersstor(rsstor_handle *handle)
+{
+  if(handle == NULL){
+    return;
+  }
+
+	/*
+	 * Free the callback structures
+	 */
+	rsstfreecallbacks(&(handle->callback));
+
+  /*
+   * Cleanup function for the XML library.
+   */
+  xmlCleanupParser();
+
+  /*
+   * we're done with libcurl, so clean it up
+   */
+  curl_global_cleanup();
+
+  /*
+   * Close the sqlite database.
+   * No way to get dbpointer here
+   */
+  sqlite3_close(handle->db);
+
+  /*
+   * Close logfile.
+   */
+  rsstcloselog();
+	/*
+	 * Free the handle struct
+	 */
+	free(handle);
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/setup.h b/tags/swarmtv-0.9.2/libswarmtv/setup.h
new file mode 100644
index 0000000..bbedd74
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/setup.h
@@ -0,0 +1,50 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Defines The basic places of RSS-Torrent files.
+ */
+#define RSS_BASEDIR 	"~/.swarmtv"
+#define RSS_LOGFILE 	"~/.swarmtv/swarmtv.log"
+//#define RSS_LOCKFILE	"~/.swarmtv/lockfile.pid"
+
+#if 0
+/*
+ * Call this function to test if rsstorrent needs setting up to do.
+ * When it does the function initializes the files that need to be in place in order to run rsstorrent.
+ * @Arguments none
+ * @returns 	0 when succes otherwise -1
+ */
+int rsstinitrsstorrent();
+#endif
+
+/*
+ * Initialize RSS-torrent handle
+ * @Return
+ * Pointer to handle on success, NULL on failure
+ */
+rsstor_handle *initrsstor();
+
+/*
+ * Free RSS-torrent handle
+ * @Arguments
+ * handle pointer to RSS-torrent structure
+ */
+void freersstor(rsstor_handle *handle);
diff --git a/tags/swarmtv-0.9.2/libswarmtv/simplefilter.c b/tags/swarmtv-0.9.2/libswarmtv/simplefilter.c
new file mode 100644
index 0000000..ea1fce6
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/simplefilter.c
@@ -0,0 +1,554 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sqlite3.h>
+
+#include "types.h"
+#include "logfile.h"
+#include "regexp.h"
+#include "database.h"
+#include "torrentdownload.h"
+#include "testfilter.h"
+#include "simplefilter.h"
+
+/*
+ * Nodup filter names
+ */
+#define NODUP_NONE_NAME           "none"
+#define NODUP_LINK_NAME           "link"
+#define NODUP_UNIQUE_NAME         "unique"
+#define NODUP_NEWER_NAME          "newer"
+#define NODUP_UNIQUE_TITLE_NAME   "unique-title"
+#define NODUP_NEWER_TITLE_NAME    "newer-title"
+
+/*
+ * Nodup filters are defined here
+ */
+#define NODUP_NONE          ""
+#define NODUP_LINK          "SELECT title FROM downloaded WHERE link=?1"
+#define NODUP_UNIQUE        "SELECT title FROM downloaded WHERE link=?1 OR (season=?2 AND episode=?3 AND IREGEXP(?4, title))"
+#define NODUP_NEWER         "SELECT title FROM downloaded WHERE link=?1 OR ((season=?2 AND episode>=?3) OR season>?2) AND IREGEXP(?4, title)"
+#define NODUP_UNIQUE_TITLE  "SELECT title FROM downloaded WHERE link=?1 OR (season=?2 AND episode=?3 AND IREGEXP(?5, title))"
+#define NODUP_NEWER_TITLE   "SELECT title FROM downloaded WHERE link=?1 OR ((season=?2 AND episode>=?3) OR season>?2) AND IREGEXP(?5, title)"
+
+/*
+ * Filter that is used to convert the simple filter into SQL.
+ */
+static char *sqlfilter="SELECT id, link, title, pubdate, category, metatype, season, episode FROM newtorrents WHERE "
+		"IREGEXP(?1, title) AND "
+		"(size < ?2 OR ?2 = 0) AND "
+		"(size > ?3 OR ?3 = 0) AND "
+		"(season >= ?4 OR ?4 = 0) AND "
+		"(season > ?4 OR episode >= ?5 OR ?5 = 0) AND "
+		"(NOT IREGEXP(?6, title) OR ?6 = '') AND "
+		"IREGEXP(?7, category) AND "
+		"IREGEXP(?8, source) AND "
+		"new = 'Y'";
+
+/*
+ * name is name of the nodup filter
+ * title is the titlefilter to insert
+ * **nodup is the allocated buffer that is returned.
+ * Nohup *nodup should be passed with value NULL
+ * Returns 0 on success, -1 when no fitting filter was found.
+ */
+static int findnodup(char *name, char **nodup)
+{
+  *nodup=NULL;
+
+  /*
+   * Find the correct filter.
+   */
+  if(strcmp(name, NODUP_NONE_NAME) == 0)
+  {
+    rsstalloccopy(nodup, NODUP_NONE, strlen(NODUP_NONE));
+  }
+  if(strcmp(name, NODUP_LINK_NAME) == 0)
+  {
+    rsstalloccopy(nodup, NODUP_LINK, strlen(NODUP_LINK));
+  }
+  if(strcmp(name, NODUP_UNIQUE_NAME) == 0)
+  {
+    rsstalloccopy(nodup, NODUP_UNIQUE, strlen(NODUP_UNIQUE));
+  }
+  if(strcmp(name, NODUP_NEWER_NAME) == 0)
+  {
+    rsstalloccopy(nodup, NODUP_NEWER, strlen(NODUP_NEWER));
+  }
+  if(strcmp(name, NODUP_UNIQUE_TITLE_NAME) == 0)
+  {
+    rsstalloccopy(nodup, NODUP_UNIQUE_TITLE, strlen(NODUP_UNIQUE_TITLE));
+  }
+  if(strcmp(name, NODUP_NEWER_TITLE_NAME) == 0)
+  {
+    rsstalloccopy(nodup, NODUP_NEWER_TITLE, strlen(NODUP_NEWER_TITLE));
+  }
+
+  /*
+   * When no valid nodup name is provided, return -1
+   */
+  if(*nodup == NULL){
+    return -1;
+  }
+
+	/*
+	 * All done.
+	 */
+  return 0;
+}
+
+
+/*
+ * Validate Arguments
+ * takes opts_struct struct as argument
+ * return on correct arguments, -1 on invalid arguments
+ */
+static int validearguments(simplefilter_struct *filter)
+{
+  int   rc=0;
+  int   retval=0;
+  char  *nodup=NULL;
+
+  /*
+   * Validate nodup argument
+   */
+  rc = findnodup(filter->nodup, &nodup);
+  free(nodup);
+  if(rc == -1) {
+    rsstwritelog(LOG_ERROR, "Nodup name '%s' is not valid. %s:%d", filter->nodup, __FILE__, __LINE__);
+    fprintf(stderr, "Nodup name '%s' is not valid.", filter->nodup);
+    retval=-1;
+  }
+
+  return retval;
+}
+
+
+/*
+ * Edit simple filter function, pointed by Id
+ * @Arguments
+ * handle SwarmTv handle
+ * simple structure holding simple filter informaion
+ * @returns
+ * returns 0 when edited successfully ,returns -1 when editing failed
+ */
+int rssteditsimplefilter(rsstor_handle *handle, simplefilter_struct *simple)
+{
+  int 			rc=0;
+
+  /*
+   * Check if values are sane
+   */
+  if(simple->id <= 0){
+    rsstwritelog(LOG_ERROR, "Id must be set when updating a simple filter! %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Query and format used to insert the simple filter into the database
+   */
+  static char *query = "UPDATE 'simplefilters' "
+		"SET name=?1, title=?2, exclude=?3, category=?4, maxsize=?5, minsize=?6, nodup=?7, fromseason=?8, fromepisode=?9, source=?10 "
+		"WHERE id=?11";
+  static char *fmt   = "ssssffsddsd";
+
+  /*
+   * Call database execute query function
+   */
+  rc = rsstexecutequery(handle->db, query, fmt,
+      simple->name,
+      simple->title,
+			simple->exclude,
+			simple->category,
+      simple->maxsize,
+      simple->minsize,
+      simple->nodup,
+      simple->fromseason,
+      simple->fromepisode,
+			simple->source,
+      simple->id);
+
+  /*
+   * Handle output
+   */
+  if(rc < 1) {
+    rsstwritelog(LOG_ERROR, "Editing of simple failed, execute query returned %d! %s:%d", rc, __FILE__, __LINE__);
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+
+/*
+ * Add simple filter adds the filter to the database
+ * Arguments  : simplefilter_struct *
+ * returns    : 0 when added successfully
+ * returns    : -1 when adding failed
+ */
+int rsstinsertsimplefilter(rsstor_handle *handle, simplefilter_struct *simple)
+{
+  int 			rc=0;
+	sqlite3  *db=NULL;
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+  /*
+   * Query and format used to insert the simple filter into the database
+   */
+  static char *query = "insert into 'simplefilters' "
+		"(name, title, exclude, category, maxsize, minsize, nodup, fromseason, fromepisode, source) "
+		"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)";
+  static char *fmt   = "ssssffsdds";
+
+  /*
+   * Call database execute query function
+   */
+  rc = rsstexecutequery(db, query, fmt,
+      simple->name,
+      simple->title,
+			simple->exclude,
+			simple->category,
+      simple->maxsize,
+      simple->minsize,
+      simple->nodup,
+      simple->fromseason,
+      simple->fromepisode,
+			simple->source);
+
+  /*
+   * Handle output
+   */
+  if(rc < 1) {
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+
+/*
+ * Check Filter
+ * When the filter exists, return 1
+ * else 0
+ */
+static int checksimple(sqlite3 *db, const char *name)
+{
+  int rc;
+
+  char *query = "select * from simplefilters where name=?1";
+
+  /*
+   * execute query
+   */
+  rc = rsstexecutequery(db, query, "s", name);
+
+  return rc;
+}
+
+
+/*
+ * Add simple filter
+ * returns 0 on success, else -1
+ */
+int rsstaddsimplefilter(rsstor_handle *handle, simplefilter_struct *simple)
+{
+  int rc=0;
+	sqlite3 *db=NULL;
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+  /*
+   * Make sure the entries are valid.
+   */
+  rc = validearguments(simple);
+  if(rc != 0){
+    return -1;
+  }
+
+  /*
+   * When already there delete the previous simple filter
+   */
+  rc = checksimple(db, simple->name);
+  if(rc == 1){
+    rsstdelsimplename(handle, simple->name);
+  }
+
+  /*
+   * Add Record
+   */
+  rsstinsertsimplefilter(handle, simple);
+
+	/*
+	 * Done
+	 */
+  return 0;
+}
+
+
+/*
+ * Delete all simple filters
+ * When the name is not found -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelallsimple(rsstor_handle *handle)
+{
+  int         rc=0;
+	sqlite3    *db=NULL;
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+  /*
+   * Init query
+   */
+  const char* query = "delete from 'simplefilters'";
+
+  /*
+   * Execute query
+   * When name is all, delete all filters.
+   */
+  rc = rsstexecutequery(db, query, NULL);
+  switch(rc) {
+    case(ROWS_CHANGED):
+      return 0;
+      break;
+    case(ROWS_EMPTY):
+      fprintf(stderr, "No simple filters in list.\n");
+      rsstwritelog(LOG_ERROR, "No simple filters in list.");
+      return -1;
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "Query error during delallfilter %s:%d",  __FILE__, __LINE__);
+      return -1;
+  }
+}
+
+
+/*
+ * Delete single simple filter
+ * When the name is not found -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelsimpleid(rsstor_handle *handle, const int id)
+{
+  int         rc=0;
+	sqlite3		 *db=NULL;
+
+  /*
+   * Init query
+   */
+  const char* query = "delete from simplefilters where id=?1";
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+  /*
+   * Execute query
+   * When name is all, delete all filters.
+   */
+  rc = rsstexecutequery(db, query, "d", id);
+  switch(rc) {
+    case(ROWS_CHANGED):
+      return 0;
+      break;
+    case(ROWS_EMPTY):
+      fprintf(stderr, "Could not delete filter '%d' %s:%di\n", id,  __FILE__, __LINE__);
+      rsstwritelog(LOG_ERROR, "Could not delete filter '%d' %s:%d", id,  __FILE__, __LINE__);
+      return -1;
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "Query error during delfilter, returned: '%d' '%s' ?2 = '%d' %s:%d", rc, query, id,  __FILE__, __LINE__);
+      return -1;
+  }
+}
+
+
+/*
+ * Delete single simple filter
+ * When the name is not found -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelsimplename(rsstor_handle *handle, const char *name)
+{
+  int         rc=0;
+	sqlite3		 *db=NULL;
+
+  /*
+   * Init query
+   */
+  const char* query = "delete from simplefilters where name=?1";
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+  /*
+   * Execute query
+   * When name is all, delete all filters.
+   */
+  rc = rsstexecutequery(db, query, "s", name);
+  switch(rc) {
+    case(ROWS_CHANGED):
+      return 0;
+      break;
+    case(ROWS_EMPTY):
+      fprintf(stderr, "Could not delete filter '%s' %s:%di\n", name,  __FILE__, __LINE__);
+      rsstwritelog(LOG_ERROR, "Could not delete filter '%s' %s:%d", name,  __FILE__, __LINE__);
+      return -1;
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "Query error during delfilter, returned: '%d' '%s' ?2 = '%s' %s:%d", rc, query, name,  __FILE__, __LINE__);
+      return -1;
+  }
+}
+
+
+/*
+ * Apply filters
+ * Runs through all filters in simple filters table.
+ * Calls SQL filters routines for further handling.
+ * arguments :
+ * db pointer to db to use
+ * simulate 0 for real behaviour, 1 for simulation mode.
+ */
+int rsstdownloadsimple(rsstor_handle *handle, SIM simulate)
+{
+  sqlite3_stmt  *ppStmt=NULL;
+  const char    *pzTail=NULL;
+  int           rc=0;
+  int           step_rc=0;
+  char          *zErrMsg = 0;
+  char          *sqlnodup=NULL;
+  simplefilter_struct simple_data;
+
+	/*
+	 * Query to retrieve filters from simple filters table.
+	 */
+	char *query = "select id, name, title, maxsize, minsize, nodup, fromseason, fromepisode, exclude, category, source from simplefilters";
+
+  /*
+   * clear simple struct
+   */
+  memset(&simple_data, 0, sizeof(simplefilter_struct));
+
+	/*
+	 * Prepare the Sqlite statement
+	 */
+	rc = rsst_sqlite3_prepare(
+			handle->db,         /* Database handle */
+      query,            	/* SQL statement, UTF-8 encoded */
+      strlen(query),    	/* Maximum length of zSql in bytes. */
+      &ppStmt,            /* OUT: Statement handle */
+      &pzTail             /* OUT: Pointer to unused portion of zSql */
+      );
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return -1;
+  }
+
+  /*
+   * loop until the end of the dataset is found
+   */
+  while( SQLITE_DONE != (step_rc = sqlite3_step(ppStmt))) {
+    sqlnodup=NULL;
+
+		/*
+		 * Get name and query of the filters
+     */
+    simple_data.id       =         sqlite3_column_int   (ppStmt, 0);
+    simple_data.name     = (char*) sqlite3_column_text  (ppStmt, 1);
+    simple_data.title    = (char*) sqlite3_column_text  (ppStmt, 2);
+    simple_data.maxsize  =         sqlite3_column_double(ppStmt, 3);
+    simple_data.minsize  =         sqlite3_column_double(ppStmt, 4);
+    simple_data.nodup    = (char*) sqlite3_column_text  (ppStmt, 5);
+    simple_data.fromseason   =     sqlite3_column_int   (ppStmt, 6);
+    simple_data.fromepisode  =     sqlite3_column_int   (ppStmt, 7);
+    simple_data.exclude  = (char*) sqlite3_column_text  (ppStmt, 8);
+    simple_data.category = (char*) sqlite3_column_text  (ppStmt, 9);
+    simple_data.source   = (char*) sqlite3_column_text  (ppStmt, 10);
+
+    /*
+     * Generate SQL-filter and SQL-nodup
+     */
+    rc = findnodup(simple_data.nodup, &sqlnodup);
+    if(rc != 0) {
+      free(sqlnodup);
+      rsstwritelog(LOG_ERROR, "Simple filter '%s' does not have a valid nodup value. %s:%d", simple_data.name, __FILE__, __LINE__);
+      continue;
+    }
+
+		/*
+		 * Log SQL used for handling filters.
+		 */
+		rsstwritelog(LOG_DEBUG, "%s : %s", simple_data.name, sqlfilter);
+		rsstwritelog(LOG_DEBUG, "%s : %s", simple_data.name, sqlnodup);
+
+    /*
+     * Emit callback
+     */
+    if(simulate ==  real) {
+      rsstexecallbacks(handle, applysimplefilt, &simple_data);
+    }
+
+    /*
+     * call apply filter (Should be put in a struct in the future
+     */
+    rsstapplyfilter(handle, simple_data.name, simple, sqlnodup, simple_data.title, simulate, sqlfilter,
+				"sffddsss", simple_data.title,
+        simple_data.maxsize, simple_data.minsize,
+        simple_data.fromseason, simple_data.fromepisode,
+        simple_data.exclude, simple_data.category,
+        simple_data.source);
+
+    /*
+     * Cleanup
+     */
+    free(sqlnodup);
+  }
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppStmt);
+
+  /*
+   * All gone well
+   */
+  return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/simplefilter.h b/tags/swarmtv-0.9.2/libswarmtv/simplefilter.h
new file mode 100644
index 0000000..0327536
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/simplefilter.h
@@ -0,0 +1,93 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Add simple filter
+ * @variables
+ * opts structure holding the options
+ * @returns
+ * 0 on success, else -1
+ */
+int rsstaddsimplefilter(rsstor_handle *handle, simplefilter_struct *filter);
+
+/*
+ * Edit simple filter function, pointed by Id
+ * @Arguments
+ * handle SwarmTv handle
+ * simple structure holding simple filter informaion
+ * @returns
+ * returns 0 when edited successfully ,returns -1 when editing failed
+ */
+int rssteditsimplefilter(rsstor_handle *handle, simplefilter_struct *simple);
+
+#if 0
+/*
+ * Print filter in shell format
+ * Prints the names of the simple filters + a header.
+ */
+void rsstlistsimple(rsstor_handle *handle);
+#endif
+
+/*
+ * Del filter item
+ * When the name is not found -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelallsimple(rsstor_handle *handle);
+
+/*
+ * Del filter item
+ * When already existing -1 is returned.
+ * @variables
+ * id filter id to delete
+ * @returns
+ * On success 0 is returned.
+ */
+int rsstdelsimplename(rsstor_handle *handle, const char *id);
+
+/*
+ * Del filter item
+ * When already existing -1 is returned.
+ * @variables
+ * name filter name to delete
+ * @returns
+ * On success 0 is returned.
+ */
+int rsstdelsimplename(rsstor_handle *handle, const char *name);
+
+/*
+ * Apply filters
+ * Runs through all filters in simple filters table.
+ * Calls SQL filters routines for further handling.
+ * @variables
+ * simulate 0 for real behaviour, 1 for simulation mode.
+ * @return
+ * -1 on error, 0 on success
+ */
+int rsstdownloadsimple(rsstor_handle *handle, SIM simulate);
+
+/*
+ * Add simple filter adds the filter to the database
+ * Arguments  : simplefilter_struct *
+ * returns    : 0 when added successfully
+ * returns    : -1 when adding failed
+ */
+int rsstinsertsimplefilter(rsstor_handle *handle, simplefilter_struct *simple);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/source.c b/tags/swarmtv-0.9.2/libswarmtv/source.c
new file mode 100644
index 0000000..071f431
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/source.c
@@ -0,0 +1,229 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <pcre.h>
+#include <sqlite3.h>
+
+#include "types.h"
+#include "config.h"
+#include "database.h"
+#include "logfile.h"
+#include "regexp.h"
+
+#define  MAXLENGHT 400
+
+/*
+ * Delete source item by name
+ * @arguments
+ * handle RSS-torrent handle
+ * id source id to delete
+ * @return
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelsourceid(rsstor_handle *handle, const int id)
+{
+  int         rc=0;
+	sqlite3    *db=NULL;
+
+	/*
+	 * Get database pointer
+	 */
+	db = handle->db;
+
+  /*
+   * Init query
+   */
+  const char* query = "DELETE FROM 'sources' WHERE id=?1";
+
+  /*
+   * Execute query
+   * When name is all, delete all filters.
+   */
+  rc = rsstexecutequery(db, query, "d", id);
+  switch(rc) {
+    case(ROWS_CHANGED):
+      printf("Source '%d' deleted.\n", id);
+      rsstwritelog(LOG_DEBUG, "Source '%d' deleted.", id);
+      return 0;
+      break;
+    case(ROWS_EMPTY):
+      printf("Source '%d' not found, could not delete.\n", id);
+      rsstwritelog(LOG_DEBUG, "Source '%d' not found, could not delete.", id);
+      return -1;
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "Query error during deletesource '%s':%d",  __FILE__, __LINE__);
+      return -1;
+  }
+
+}
+
+/*
+ * Delete source item
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelsourcename(rsstor_handle *handle, const char *name)
+{
+  int         rc=0;
+	sqlite3    *db=NULL;
+
+	/*
+	 * Get database pointer
+	 */
+	db = handle->db;
+
+  /*
+   * Init query
+   */
+  const char* query = "DELETE FROM 'sources' WHERE name=?1";
+
+  /*
+   * Execute query
+   * When name is all, delete all filters.
+   */
+  rc = rsstexecutequery(db, query, "s", name);
+  switch(rc) {
+    case(ROWS_CHANGED):
+      printf("Source '%s' deleted.\n", name);
+      rsstwritelog(LOG_DEBUG, "Source '%s' deleted.", name);
+      return 0;
+      break;
+    case(ROWS_EMPTY):
+      printf("Source '%s' not found, could not delete.\n", name);
+      rsstwritelog(LOG_DEBUG, "Source '%s' not found, could not delete.", name);
+      return -1;
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "Query error during deletesource '%s':%d",  __FILE__, __LINE__);
+      return -1;
+  }
+}
+
+
+/*
+ * Test the metatype string.
+ * @arguments
+ * metatype string holding the metatype to be entered
+ * @return
+ * 0 when supported, -1 when not found
+ */
+static int rssttestmetatype(char *metatype)
+{
+  int count=0;
+  char **supported;
+
+  /*
+   * Get supported type from library
+   */
+  supported = getsupportedmetatypes();
+
+  /*
+   * Is the metatype valid ?
+   */
+  while(supported[count] != NULL) {
+    if(!strcmp(supported[count], metatype)) {
+      return 0;
+    }
+    count++;
+  }
+
+  return -1;
+}
+
+
+/*
+ * Add source item
+ * When already existing the source is updated.
+ * On success 0 is returned.
+ */
+int rsstaddsource(rsstor_handle *handle, source_struct *source)
+{
+  int         rc=0;
+  char       *localparser=NULL;
+	sqlite3    *db=NULL;
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+  /*
+   * Init query
+   */
+  const char* query = "INSERT OR REPLACE INTO 'sources' (name, url, parser, metatype) VALUES(?2, ?1, ?3, ?4)";
+
+  /*
+   * Test the metatype is supported
+   */
+  rc = rssttestmetatype(source->metatype);
+  if(rc == -1) {
+    rsstwritelog(LOG_ERROR, "Adding source failed, metatype '%s' is not supported.", source->metatype);
+    return -1;
+  }
+
+  /*
+   * When parser type is not set use the default.
+   */
+  if(source->parser == NULL){
+    rsstconfiggetproperty(handle, CONF_DEFPARSER, &localparser);
+  } else {
+		rsstalloccopy(&localparser, source->parser, strlen(source->parser));
+  }
+
+  //printf("Adding:%s, url:%s, parser type:%s\n", source->name, source->url, localparser);
+  rsstwritelog(LOG_DEBUG, "Adding:%s, url:%s, parsertype:%s", source->name, source->url, localparser);
+
+  /*
+   * Execute query
+   */
+  rc = rsstexecutequery(db, query, "ssss", source->url, source->name, localparser, source->metatype);
+
+  /*
+   * free parser type.
+   */
+  free(localparser);
+
+  /*
+   * Act on add filter
+   */
+  switch(rc) {
+    case(ROWS_CHANGED):
+      printf("Source '%s' added succesfully.\n", source->name);
+      rsstwritelog(LOG_DEBUG, "Source '%s' added succesfully.", source->name);
+      return 0;
+      break;
+    case(ROWS_CONSTRAINT):
+    case(ROWS_EMPTY):
+      fprintf(stderr, "Could not add source '%s', does the source allready exist?\n", source->name);
+      rsstwritelog(LOG_ERROR, "Could not add source '%s'. %s:%d", source->name, __FILE__, __LINE__);
+      return -1;
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "Query error during addsource '%s'. %s:%d", source->name,  __FILE__, __LINE__);
+      return -1;
+  }
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/source.h b/tags/swarmtv-0.9.2/libswarmtv/source.h
new file mode 100644
index 0000000..1c291fc
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/source.h
@@ -0,0 +1,55 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Add source item
+ * @arguments
+ * name filtername
+ * url source url
+ * parsertype parser type
+ * metatype meta file type (torrent/nzb)
+ * @return
+ * When allready existing -1 is returned.
+ * On succes 0 is returned.
+ */
+int rsstaddsource(rsstor_handle *handle, source_struct *source);
+//int rsstaddsource(rsstor_handle *handle, const char *name, const char *url, char *parsertype, char *metatype);
+
+/*
+ * Delete source item by name
+ * @arguments
+ * handle RSS-torrent handle
+ * name source id to delete
+ * @return
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelsourceid(rsstor_handle *handle, const int *id);
+
+/*
+ * del source item
+ * @arguments
+ * name sourcename to delete
+ * @return
+ * When allready existing -1 is returned.
+ * On succes 0 is returned.
+ */
+int rsstdelsourcename(rsstor_handle *handle, const char *name);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/CMakeLists.txt b/tags/swarmtv-0.9.2/libswarmtv/srcparser/CMakeLists.txt
new file mode 100644
index 0000000..a10bcea
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/CMakeLists.txt
@@ -0,0 +1,4 @@
+# The plugins should be inserted here.
+# When adding parsers here, make sure to add the parser in parser.c to.
+INCLUDE(srcparser/defaultrss/CMakeLists.txt)
+INCLUDE(srcparser/twitter/CMakeLists.txt)
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/CMakeLists.txt b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/CMakeLists.txt
new file mode 100644
index 0000000..0d020eb
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/CMakeLists.txt
@@ -0,0 +1,15 @@
+SET(DEFAULTRSS_PATH srcparser/defaultrss)
+
+SET(LIBSRC ${LIBSRC}
+		${DEFAULTRSS_PATH}/defaultrss
+		${DEFAULTRSS_PATH}/rssparse
+		${DEFAULTRSS_PATH}/disectdate
+		${DEFAULTRSS_PATH}/disectdescription
+		${DEFAULTRSS_PATH}/rsslink
+		${DEFAULTRSS_PATH}/rsstitle
+		${DEFAULTRSS_PATH}/rsspubdate
+		${DEFAULTRSS_PATH}/rsscategory
+		${DEFAULTRSS_PATH}/rssseedspeers
+		${DEFAULTRSS_PATH}/rsssize
+		${DEFAULTRSS_PATH}/rssseasonepisode)
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/defaultrss.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/defaultrss.c
new file mode 100644
index 0000000..d828e8b
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/defaultrss.c
@@ -0,0 +1,540 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <time.h>
+#include <stdlib.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "curlfile.h"
+#include "regexp.h"
+#include "torrentdb.h"
+#include "defaultrss.h"
+#include "disectdate.h"
+#include "rssparse.h"
+#include "rsslink.h"
+#include "rsstitle.h"
+#include "rsspubdate.h"
+#include "rsscategory.h"
+#include "rssseasonepisode.h"
+#include "rssseedspeers.h"
+#include "rsssize.h"
+
+/*
+ * Free all allocated strings in structure.
+ */
+static void	freerssdata(rssdatastruct *rssdata)
+{
+	free(rssdata->title);
+	free(rssdata->link);
+	free(rssdata->torrentlink);
+	free(rssdata->category);
+	free(rssdata->description);
+	free(rssdata->comments);
+	free(rssdata->guid);
+	free(rssdata->enclosuretype);
+	free(rssdata->enclosureurl);
+}
+
+/*
+ * Handle title
+ */
+static int handletitle(void *data, char *string)
+{
+	int rc = 0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Store into the struct
+	 */
+	rc = rsstalloccopy(&(rssdata->title), string, strlen(string));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Handle link
+ */
+static int handlelink(void *data, char *string)
+{
+	int rc = 0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Store into the struct
+	 */
+	rc = rsstalloccopy(&(rssdata->link), string, strlen(string));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Handle toorent link
+ */
+static int handletorrentlink(void *data, char *string)
+{
+	int rc = 0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Store into the struct
+	 */
+	rc = rsstalloccopy(&(rssdata->torrentlink), string, strlen(string));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Handle category
+ */
+static int handlecategory(void *data, char *string)
+{
+	int rc = 0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Store into the struct
+	 */
+	rc = rsstalloccopy(&(rssdata->category), string, strlen(string));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Handle pubdate
+ */
+static int handlepubdate(void *data, char *string)
+{
+	int rc = 0;
+	time_t pubdate=0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Decode date
+	 */
+	rc = rssdisectdate(string, &pubdate);
+	if(rc != 0){
+		rsstwritelog(LOG_ERROR, "pubdate '%s' could not be decoded.", string);
+	}
+
+	/*
+	 * Set pubdate
+	 */
+	rssdata->pubdate = pubdate;
+
+	/*
+	 * Done.
+	 */
+	return 0;
+}
+
+/*
+ * Handle description
+ */
+static int handledescription(void *data, char *string)
+{
+	int rc = 0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Store into the struct
+	 */
+	rc = rsstalloccopy(&(rssdata->description), string, strlen(string));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Handle comments
+ */
+static int handlecomments(void *data, char *string)
+{
+	int rc = 0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Store into the struct
+	 */
+	rc = rsstalloccopy(&(rssdata->comments), string, strlen(string));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Handle guid
+ */
+static int handleguid(void *data, char *string)
+{
+	int rc = 0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Store into the struct
+	 */
+	rc = rsstalloccopy(&(rssdata->guid), string, strlen(string));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Handle start
+ */
+static int handlestart(void *data)
+{
+	rsstor_handle *handle=NULL;
+	char    *source=NULL;
+  char    *metatype=NULL;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * store statics
+	 */
+	handle=rssdata->handle;
+	source=rssdata->source;
+  metatype=rssdata->metatype;
+
+	/*
+	 * NULL all pointers
+	 */
+	memset(rssdata, 0, sizeof(rssdatastruct));
+
+	/*
+	 * Restore statics.
+	 */
+	rssdata->handle=handle;
+	rssdata->source=source;
+  rssdata->metatype=metatype;
+
+	return 0;
+}
+
+
+static int handleenclosurelength(void *data, size_t newtor)
+{
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+	/*
+	 * set length in structure
+	 */
+	rssdata->enclosurelength = newtor;
+
+	/*
+	 * Dummy for now.
+	 */
+	return 0;
+}
+
+static int handlecontentlength(void *data, size_t newtor)
+{
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+	/*
+	 * set length in structure
+	 */
+	rssdata->contentlength = newtor;
+
+	/*
+	 * Dummy for now.
+	 */
+	return 0;
+}
+
+
+static int handleenclosuretype(void *data, char *string)
+{
+	int rc=0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Set the onclosure type
+	 */
+	rc = rsstalloccopy(&(rssdata->enclosuretype), string, strlen(string));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	return 0;
+}
+
+static int handleenclosereurl(void *data, char *string)
+{
+	int rc=0;
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Set enclosure url
+	 */
+	rc = rsstalloccopy(&(rssdata->enclosureurl), string, strlen(string));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Handle seeds
+ */
+static int handleseeds(void *data, int seeds)
+{
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Set the seeds value.
+	 */
+	rssdata->seeds=seeds;
+
+	/*
+	 * Dummy
+	 */
+	return 0;
+}
+
+/*
+ * Handle peers
+ */
+static int handlepeers(void *data, int peers)
+{
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+
+	/*
+	 * Set the peers value.
+	 */
+	rssdata->peers=peers;
+
+	/*
+	 * Dummy
+	 */
+	return 0;
+}
+
+/*
+ * Handle end
+ */
+static int handleend(void *data)
+{
+	int 								rc 		 = 0;
+	int									ignore = 0;
+	newtorrents_struct 	newtor;
+
+	/*
+	 * init structs
+	 */
+	rssdatastruct *rssdata = (rssdatastruct *) data;
+	memset(&newtor, 0, sizeof(newtorrents_struct));
+
+	/*
+	 * Set source
+	 */
+	rc = rsstalloccopy(&(newtor.source), rssdata->source, strlen(rssdata->source));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+	rc = rsstalloccopy(&(newtor.metatype), rssdata->metatype, strlen(rssdata->metatype));
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "Alloc failed at %s:%d", __FILE__, __LINE__);
+		return  -1;
+	}
+
+	/*
+	 * Disect the data.
+	 */
+	newtor.pubdate = rssdata->pubdate;
+
+	/*
+	 * Fill out title
+	 */
+	rc = rsstitle(&newtor, rssdata);
+	if(rc != 0){
+		ignore=1;
+	}
+
+	/*
+	 * Fill out link
+	 */
+	if(ignore == 0) {
+		rc = rsslink(&newtor, rssdata);
+		if(rc != 0){
+			ignore=1;
+		}
+	}
+
+	/*
+	 * Fill out pubdate
+	 */
+	if(ignore == 0) {
+		rc = rsspubdate(&newtor, rssdata);
+	}
+
+	/*
+	 * Category
+	 */
+	if(ignore == 0) {
+		rc = rsscategory(&newtor, rssdata);
+	}
+
+	/*
+	 * Set season and episode
+	 */
+	if(ignore == 0) {
+		rc = rssseasonepisode(&newtor, rssdata);
+	}
+
+	/*
+	 * Set seeds and peers
+	 */
+	if(ignore == 0) {
+		rc = rssseedspeers(&newtor, rssdata);
+	}
+
+	/*
+	 * Set size
+	 */
+	if(ignore == 0) {
+		rc = rsssize(&newtor, rssdata);
+		if(rc != 0){
+			//ignore=1;
+			rsstwritelog(LOG_ERROR, "Could not verify size of '%s'.", newtor.link);
+		}
+	}
+
+	/*
+	 * enter the new record.
+	 */
+	if(ignore == 0) {
+		rc = rsstaddnewtorrent(rssdata->handle, &newtor);
+		if(rc != 0) {
+			rsstwritelog(LOG_ERROR, "Failed to add newtorrent %s:%d", __FILE__, __LINE__);
+			return -1;
+		}
+	}
+
+	/*
+	 * Free all stored strings
+	 */
+	freerssdata(rssdata);
+
+	/*
+	 * Free newtorrents strings
+	 */
+	rsstfreenewtor(&newtor);
+
+	/*
+	 * All gone well !
+	 */
+	return 0;
+}
+
+/*
+ * filter to handle incomming files from http://www.rsstorrents.com
+ */
+int defaultrss(rsstor_handle *handle, char *name, char *url, char *filter, char *metatype, MemoryStruct *rssfile)
+{
+	int								retval=0;
+	int								rc=0;
+	rssparse_callback callback;
+	rssdatastruct			data;
+
+	/*
+	 * Make sure all pointers are set to NULL by default.
+	 */
+	memset(&callback, 0, sizeof(rssparse_callback));
+	memset(&data, 0, sizeof(rssdatastruct));
+
+	/*
+	 * Add statics to data
+	 */
+	data.handle = handle;
+	data.source = name;
+  data.metatype = metatype;
+
+	/*
+	 * Initialize the callback struct.
+	 */
+	callback.data							= &data;
+	callback.start 						= handlestart;
+	callback.title 						= handletitle;
+	callback.link	 						= handlelink;
+	callback.torrentlink	 		= handletorrentlink;
+	callback.category					= handlecategory;
+	callback.pubdate					= handlepubdate;
+	callback.description			= handledescription;
+	callback.enclosurelength 	= handleenclosurelength;
+  callback.contentlength    = handlecontentlength;
+	callback.enclosuretype		= handleenclosuretype;
+	callback.enclosureurl			=	handleenclosereurl;
+	callback.comments					= handlecomments;
+	callback.seeds						= handleseeds;
+	callback.peers						= handlepeers;
+	callback.guid							= handleguid;
+	callback.end							= handleend;
+
+	/*
+	 * Call the parser
+	 */
+	rc = rssparse(&callback, url, rssfile);
+	if(rc != 0) {
+		rsstwritelog(LOG_ERROR, "RSS could not be parsed '%s' '%s' '%s'", url, name, filter);
+		retval=-1;
+	}
+
+	/*
+	 * When we reach here all gone well.
+	 */
+	return retval;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/defaultrss.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/defaultrss.h
new file mode 100644
index 0000000..c00b631
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/defaultrss.h
@@ -0,0 +1,50 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * RSS data structure
+ */
+typedef struct {
+	rsstor_handle *handle;
+	char 		*source;
+	char 		*title;
+	char		*link;
+	char		*torrentlink;
+	char		*category;
+	time_t	 pubdate;
+	char		*description;
+	char		*comments;
+	char		*guid;
+	int			 seeds;
+	int			 peers;
+	size_t	 size;
+	size_t	 enclosurelength;
+  size_t   contentlength;
+	char		*enclosuretype;
+	char		*enclosureurl;
+  char    *metatype;
+	int			 verified;
+} rssdatastruct;
+
+/*
+ * filter to handle incomming files from http://www.rsstorrents.com
+ */
+int defaultrss(rsstor_handle *handle, char *name, char *url, char *filter, char *metatype, MemoryStruct *rssfile);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdate.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdate.c
new file mode 100644
index 0000000..b4e0f53
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdate.c
@@ -0,0 +1,151 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#define _XOPEN_SOURCE /* glibc2 needs this */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sqlite3.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "rssparse.h"
+#include "defaultrss.h"
+
+#ifdef __MINGW32__
+#include "workarounds.h"
+#endif
+
+/*
+ * Standard date decoding
+ */
+static int disectdate(char *date, struct tm *pubtm)
+{
+	char *rc=NULL;
+
+  // %a, %d %b %Y %H:%M:%S
+  // When all failes use time 'now'
+  rc = strptime(date, "%a, %d %b %Y %H:%M:%S", pubtm);
+	if(rc != NULL) {
+		rsstwritelog(LOG_DEBUG, "Converted date '%s'.", date);
+	}
+
+	return !rc;
+}
+
+/*
+ * Simple date decoding
+ */
+static int simpledisectdate(char *date, struct tm *pubtm)
+{
+	char *rc=NULL;
+
+  // 2009-10-05
+  // %Y-%m-%d
+	rc = strptime(date, "%Y-%m-%d", pubtm);
+	if(rc != NULL) {
+		rsstwritelog(LOG_DEBUG, "Converted date '%s'.", date);
+	}
+
+	return !rc;
+}
+
+/*
+ * Get current time
+ */
+static void nowdate(struct tm *pubtm)
+{
+	time_t    now=0;
+
+	/*
+	 * Get time now.
+	 */
+	now = time ( NULL );
+	localtime_r ( &now, pubtm );
+}
+
+/*
+ * Gets the timestring.
+ * Exports time_t value
+ */
+int rssdisectdate(char *date, time_t *pubdate)
+{
+  int    rc=0;
+	int		 retval=0;
+  struct tm pubtm;
+
+  /*
+   * init struct.
+   */
+  memset(&pubtm, 0, sizeof(pubtm));
+  mktime(&pubtm);
+
+	/*
+	 * Disect the date
+	 */
+	if(date == NULL){
+		rsstwritelog(LOG_DEBUG, "NULL passed to rssdisectdate using now.");
+		nowdate(&pubtm);
+		retval=1;
+	}
+  if(retval == 0) {
+		rc = disectdate(date, &pubtm);
+		if(rc == 0){
+			retval=1;
+		}
+	}
+  if(retval == 0) {
+		rc = simpledisectdate(date, &pubtm);
+		if(rc == 0){
+			retval=1;
+		}
+  }
+  if(retval == 0) {
+    /*
+     * When all else fails it's a safe bet to set the date to 'now'
+     */
+    rsstwritelog(LOG_DEBUG, "Converting date '%s' failed, used 'now' as substitute.", date);
+		nowdate(&pubtm);
+  }
+
+	/*
+	 * Not set by strptime(); tells mktime()
+	 * to determine whether daylight saving time
+	 * is in effect
+	 */
+  pubtm.tm_isdst = -1;
+
+  /*
+   * struct tm to time_t
+   */
+  *pubdate = mktime(&pubtm);
+
+  rsstwritelog(LOG_DEBUG, "Converted ctime: %s", ctime(pubdate));
+
+  /*
+   * success
+   */
+  return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdate.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdate.h
new file mode 100644
index 0000000..2a583f0
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdate.h
@@ -0,0 +1,26 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Gets the timestring.
+ * Exports time_t value
+ */
+int rssdisectdate(char *date, time_t *pubdate);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdescription.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdescription.c
new file mode 100644
index 0000000..af3d91b
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdescription.c
@@ -0,0 +1,125 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sqlite3.h>
+
+#include "types.h"
+#include "logfile.h"
+#include "regexp.h"
+
+/*
+ * disectdescription
+ * Arguments
+ * description	Description string
+ * key					Keyword to extract
+ * retrieved		Retrieved string (free after usage)
+ * return values
+ * return 0 when found, -1 when not found
+ */
+int disectdescription(char *description, char *key, char **retrieved)
+{
+	int 	rc=0;
+	char *desc=NULL;
+	char *token=NULL;
+	char *split=NULL;
+	char *fkey=NULL;
+	char *fvalue=NULL;
+
+	*retrieved=NULL;
+
+	/*
+	 * When not set return -1
+	 */
+	if(description == NULL){
+		return -1;
+	}
+
+	/*
+	 * Move description to local buffer
+	 */
+	rsstalloccopy(&desc, description, strlen(description));
+
+
+	/*
+	 * Getopt through the string
+	 */
+	token = strtok(desc, ";");
+	while (token != NULL)
+	{
+		rc=0;
+		fkey=NULL;
+		fvalue=NULL;
+
+		/*
+		 * Split key and value.
+		 */
+		split = strchr(token, ':');
+		if(split == NULL) {
+			token = strtok (NULL, ";");
+			continue;
+		}
+
+		/*
+		 * Get both values
+		 */
+		rc =  rsstalloccopy(&fkey, token,	split-token);
+		if(rc != 0){
+			rsstwritelog(LOG_ERROR, "Alloc failed on %s:%d", __FILE__, __LINE__);
+			exit(1);
+		}
+		rc |= rsstalloccopy(&fvalue, split+1, strlen(split+1));
+		if(rc != 0){
+			rsstwritelog(LOG_ERROR, "Alloc failed on %s:%d", __FILE__, __LINE__);
+			exit(1);
+		}
+		rsstcleanupstring(fkey);
+		rsstcleanupstring(fvalue);
+
+		/*
+		 * When found copyalloc to retrieved
+		 */
+		if(fkey != NULL && strcmp(fkey, key) == 0){
+			rc = rsstalloccopy(retrieved, split+1, strlen(split+1));
+
+			free(fkey);
+			free(fvalue);
+			free(desc);
+
+			return 0;
+		}
+
+		/*
+		 * Clean up for next cycle
+		 */
+		free(fkey);
+		free(fvalue);
+		token = strtok (NULL, ";");
+	}
+
+	/*
+	 * failed return -1 after cleanup.
+	 */
+	free(desc);
+	return -1;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdescription.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdescription.h
new file mode 100644
index 0000000..9a109c0
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/disectdescription.h
@@ -0,0 +1,31 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * disectdescription
+ * Arguments
+ * description	Description string
+ * key					Keyword to extract
+ * retrieved		Retrieved string (free after usage)
+ * return values
+ * return 0 when found, -1 when not found
+ */
+int disectdescription(char *description, char *key, char **retrieved);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsscategory.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsscategory.c
new file mode 100644
index 0000000..81499f0
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsscategory.c
@@ -0,0 +1,61 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#include <stdio.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <time.h>
+#include <stdlib.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "defaultrss.h"
+#include "regexp.h"
+
+#define CATEGORY_UNKNOWN "unknown"
+
+/*
+ * Use the rss data to fill out the category field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsscategory(newtorrents_struct *newtor, rssdatastruct *rssdata)
+{
+	/*
+	 * Try to get a value from the category tag
+	 */
+	if(rssdata->category != NULL) {
+		rsstalloccopy(&(newtor->category), rssdata->category, strlen(rssdata->category));
+		return 0;
+	}
+
+	/*
+	 * When not found, put in "unknown"
+	 */
+	rsstalloccopy(&(newtor->category), CATEGORY_UNKNOWN, strlen(CATEGORY_UNKNOWN));
+	return 0;
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsscategory.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsscategory.h
new file mode 100644
index 0000000..363f788
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsscategory.h
@@ -0,0 +1,31 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Use the rss data to fill out the category field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsscategory(newtorrents_struct *newtor, rssdatastruct *rssdata);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsslink.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsslink.c
new file mode 100644
index 0000000..ab500a2
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsslink.c
@@ -0,0 +1,132 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "regexp.h"
+#include "filehandler/torrent/findtorrent.h"
+#include "defaultrss.h"
+#include "disectdescription.h"
+
+/*
+ * Use the rss data to fill out the link field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsslink(newtorrents_struct *newtor, rssdatastruct *rssdata)
+{
+	int 	rc=0;
+	char *link=NULL;
+
+	/*
+	 * when link and enclosureurl are NULL
+	 */
+	if( rssdata->link == NULL &&
+			rssdata->enclosureurl == NULL &&
+			rssdata->torrentlink == NULL)
+	{
+		return -1;
+	}
+
+	/*
+	 *    * Get the link from the enclosureurl.
+	 *       */
+	if(rssdata->torrentlink != NULL) {
+		rc = rsstalloccopy(&link, rssdata->torrentlink, strlen(rssdata->torrentlink));
+		if(rc != 0) {
+			rsstwritelog(LOG_ERROR, "Alloc failed %s:%d", __FILE__, __LINE__);
+			exit(1);
+		}
+	}
+
+	/*
+	 * Get the link from the enclosureurl.
+	 */
+	if(link == NULL){
+		if(rssdata->enclosureurl != NULL) {
+			rc = rsstalloccopy(&link, rssdata->enclosureurl, strlen(rssdata->enclosureurl));
+			if(rc != 0) {
+				rsstwritelog(LOG_ERROR, "Alloc failed %s:%d", __FILE__, __LINE__);
+				exit(1);
+			}
+		}
+	}
+
+	/*
+	 * Get the link from the link node
+	 */
+	if(link == NULL){
+		if(rssdata->link != NULL && strlen(rssdata->link) != 0)
+		{
+			rc = rsstalloccopy(&link, rssdata->link, strlen(rssdata->link));
+			if(rc != 0){
+				rsstwritelog(LOG_ERROR, "Alloc failed %s:%d", __FILE__, __LINE__);
+				exit(1);
+			}
+		}
+	}
+
+	/*
+	 * Last resort, use the guid
+	 */
+	if(link == NULL){
+		if(rssdata->guid != NULL) {
+			rc = rsstalloccopy(&link, rssdata->guid, strlen(rssdata->guid));
+			if(rc == 0) {
+				rsstwritelog(LOG_ERROR, "Alloc failed %s:%d", __FILE__, __LINE__);
+				exit(1);
+			}
+		}
+	}
+
+	/*
+	 * not found
+	 */
+	if(link == NULL){
+		return -1;
+	}
+
+	/*
+	 * When enclosure type is nog 'application/x-bittorrent' get real torrent link.
+	 */
+
+
+	/*
+	 * Store value in struct
+	 */
+	newtor->link = link;
+
+	return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsslink.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsslink.h
new file mode 100644
index 0000000..5b94dcf
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsslink.h
@@ -0,0 +1,31 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Use the rss data to fill out the link field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsslink(newtorrents_struct *newtor, rssdatastruct *rssdata);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssparse.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssparse.c
new file mode 100644
index 0000000..c9e4a9f
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssparse.c
@@ -0,0 +1,514 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#define _XOPEN_SOURCE /* glibc2 needs this */
+
+#include <stdio.h>
+#include <sqlite3.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <pcre.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+
+#include "rssparse.h"
+
+/*
+ * Xpath queries.
+ */
+static char *toitems				= "/rss/channel/item";
+static char *totitle				= "title";
+static char *tolink					= "link";
+static char *totorrentlink	= "torrentLink";
+static char *tocategory			= "category";
+static char *topubdate			= "pubDate";
+static char *todescription	= "description";
+static char *toenclosure		= "enclosure";
+static char *tocomments			= "comments";
+static char *topeers				= "peers";
+static char *toseeds				= "seeds";
+static char *tosize					= "size";
+static char *tocontentlength= "eztv:torrent/eztv:contentLength";
+static char *toguid					= "guid";
+
+
+/*
+ * Same as xmlXPathEvalExpression, but preserves current node.
+ * This enables relative xpaths.
+ */
+static xmlXPathObjectPtr myXmlXPathEval( const xmlChar * str, xmlXPathContextPtr ctxt)
+{
+  xmlNode *temp;
+  xmlXPathObjectPtr xpathObj;
+
+  temp = ctxt->node;
+
+  xpathObj = xmlXPathEvalExpression(str, ctxt);
+
+  ctxt->node = temp;
+
+  return xpathObj;
+}
+
+
+/*
+ * Execute the xpath query and return the pointer to the string in that node.
+ * return 0 when okay, -1 when failed.
+ */
+static xmlNode *getxpathnode(const xmlChar * str, xmlXPathContextPtr ctxt)
+{
+  xmlXPathObjectPtr xpathObj;
+  xmlNode *node;
+
+  /*
+   * Evaluate xpath
+   */
+  xpathObj = myXmlXPathEval(str, ctxt);
+
+  /*
+   * When no results are found fail.
+   */
+  if( xpathObj->nodesetval->nodeNr == 0) {
+    xmlXPathFreeObject(xpathObj);
+    return NULL;
+  }
+
+  /*
+   * get the pointer to the first node.
+   */
+  node = xpathObj->nodesetval->nodeTab[0];
+
+  /*
+   * Clean up
+   */
+  xmlXPathFreeObject(xpathObj);
+
+  /*
+   * All gone well
+   */
+  return node;
+}
+
+
+/*
+ * Execute the xpath query and return the pointer to the string in that node.
+ * return 0 when okay, -1 when failed.
+ */
+static int getxpathstring(const xmlChar * str, xmlXPathContextPtr ctxt, unsigned char **string)
+{
+  xmlXPathObjectPtr xpathObj;
+  xmlNode *node;
+
+  *string = NULL;
+
+  /*
+   * Evaluate xpath
+   */
+  xpathObj = myXmlXPathEval(str, ctxt);
+
+  /*
+   * When no results are found fail.
+   */
+  if(xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr == 0) {
+    xmlXPathFreeObject(xpathObj);
+    return -1;
+  }
+
+  /*
+   * get the pointer to the first node.
+   */
+  node = xpathObj->nodesetval->nodeTab[0];
+
+  /*
+   * Set pointer to contentstring in child
+   */
+	if(node->children == NULL) {
+    xmlXPathFreeObject(xpathObj);
+		return -1;
+	}
+  *string = BAD_CAST node->children->content;
+
+  /*
+   * Clean up
+   */
+  xmlXPathFreeObject(xpathObj);
+
+  /*
+   * All gone well
+   */
+  return 0;
+}
+
+
+/*
+ * Get the properties of this node.
+ * <enclosure url="http://torrent.zoink.it/Conan.O.Brien.2009.09.28.Drew.Barrymore.HDTV.XViD-YesTV.[eztv].torrent" length="367366144" type="application/x-bittorrent" />
+ */
+static int disectenclosure(xmlNode *encnode, rssparse_callback *call)
+{
+  struct 	_xmlAttr *prop=NULL;
+  char   	*name=NULL;
+  char   	*attr=NULL;
+	size_t 	torsize=0;
+
+  /*
+   * when no enclosure is not found return
+   */
+  if(encnode == NULL) {
+    /*
+     * warn about no enclosure
+     */
+    rsstwritelog(LOG_DEBUG, "No enclosure found %s:%d", __FILE__, __LINE__);
+    return 0;
+  }
+
+  /*
+   * set pointer to properties
+   */
+  prop = encnode->properties;
+  while(prop != NULL) {
+    /*
+     * get the name
+     */
+    name = (char*) prop->name;
+    attr = (char*) prop->children->content;
+
+    /*
+     * Get the content
+     */
+    if(!strcmp(name, "url")) {
+      /*
+       * ignore for now, we have the link-node
+       */
+			if(call->enclosureurl != NULL){
+				call->enclosureurl(call->data, attr);
+			}
+    }
+    else if(!strcmp(name, "length")) {
+      /*
+       * transform to size_t
+       */
+      torsize = atol(attr);
+      rsstwritelog(LOG_DEBUG, "length : %s %ld", attr, torsize);
+			if(call->enclosurelength != NULL){
+				call->enclosurelength(call->data, torsize);
+			}
+    }
+    else if(!strcmp(name, "type")) {
+      /*
+       * copy type to string
+       */
+      rsstwritelog(LOG_DEBUG, "Type : '%s'", attr);
+			if(call->enclosuretype != NULL){
+				call->enclosuretype(call->data, attr);
+			}
+    }
+    else {
+      rsstwritelog(LOG_ERROR, "unknown enclosuretype: '%s' : ,%s'", name, attr);
+    }
+
+    prop = prop->next;
+  }
+
+  return 0;
+}
+
+
+/*
+ * Routine to call parser
+ * Arguments
+ * call		Pointer to a struct holding the callback routines, all unused should be NULL
+ * url		the URL of the RSS feed.
+ * buffer	The buffer holding the RSS content.
+ */
+int rssparse(rssparse_callback *call, char *url, MemoryStruct *buffer)
+{
+  xmlDocPtr           doc=NULL; /* the resulting document tree */
+  xmlNode             *root_element=NULL;
+  xmlNode             *encnode;
+  xmlXPathContextPtr  xpathCtx=NULL;
+  xmlXPathObjectPtr   xpathObj=NULL;
+  xmlNodeSetPtr       nodeset=NULL;
+	unsigned char			 *value=NULL;
+	long								filesize=0;
+	int									integer=0;
+	int									count=0;
+	int 								rc=0;
+
+  /*
+   * Use the imput to feed libxml2
+   */
+  doc = xmlReadMemory(buffer->memory, buffer->size, url, NULL, 0);
+  if (doc == NULL) {
+    rsstwritelog(LOG_ERROR, "Failed to parse RSS document: '%s' %s:%d", url, __FILE__, __LINE__);
+    return -1;
+  }
+  root_element = xmlDocGetRootElement(doc);
+
+  /* Create xpath evaluation context */
+  xpathCtx = xmlXPathNewContext(doc);
+  if(xpathCtx == NULL) {
+    rsstwritelog(LOG_ERROR, "Error: unable to create new XPath context %s:%d", __FILE__, __LINE__);
+    xmlFreeDoc(doc);
+    return(-1);
+  }
+
+  /*
+   * Get the item nodes in channel.
+   */
+  xpathObj = myXmlXPathEval(BAD_CAST toitems, xpathCtx);
+  if(xpathObj == NULL) {
+    rsstwritelog(LOG_ERROR, "Error: unable to evaluate xpath expression \"%s\" %s:%d", toitems, __FILE__, __LINE__);
+    xmlXPathFreeContext(xpathCtx);
+    xmlFreeDoc(doc);
+    return(-1);
+  }
+
+  /*
+   * Get the nodeset returned from the query
+   */
+  nodeset = xpathObj->nodesetval;
+
+  /*
+   * Loop through the nodes we need.
+   */
+  for(count = 0; count < nodeset->nodeNr; count++) {
+
+    /*
+     * Set current node for XPath queries.
+     */
+    xpathCtx->node = nodeset->nodeTab[count];
+
+		/*
+		 * new record
+		 */
+		if(call->start != NULL) {
+			call->start(call->data);
+		}
+
+		/*
+		 * Get node op enclosure
+		 * toenclosure
+		 */
+		encnode = getxpathnode(BAD_CAST toenclosure, xpathCtx);
+		rc = disectenclosure(encnode, call);
+		if(rc != 0) {
+			/*
+			 * When an error occures ignore record
+			 */
+			rsstwritelog(LOG_ERROR, "enclosure failed not found");
+			continue;
+		}
+
+
+		/*
+		 * Look for title
+		 */
+		rc = getxpathstring(BAD_CAST totitle, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No title found");
+    } else {
+			if(call->title != NULL){
+				call->title(call->data, (char*) value);
+			}
+		}
+		value=NULL;
+
+		/*
+		 * Look for link
+		 */
+    rc = getxpathstring(BAD_CAST tolink, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_ERROR, "No link found");
+    } else {
+			if(call->link != NULL){
+				call->link(call->data, (char*) value);
+			}
+		}
+		value=NULL;
+
+		/*
+		 * Look for torrentlink
+		 */
+    rc = getxpathstring(BAD_CAST totorrentlink, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No torrentlink found");
+    } else {
+			if(call->torrentlink != NULL){
+				call->torrentlink(call->data, (char*) value);
+			}
+		}
+		value=NULL;
+
+		/*
+		 * Look for category
+		 */
+    rc = getxpathstring(BAD_CAST tocategory, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No categorystr found");
+    } else {
+			if(call->category != NULL){
+				call->category(call->data, (char*) value);
+			}
+		}
+		value=NULL;
+
+		/*
+		 * Look for pubdate
+		 */
+    rc = getxpathstring(BAD_CAST topubdate, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No pubdatestr found");
+    } else {
+			if(call->pubdate != NULL){
+				call->pubdate(call->data, (char*) value);
+			}
+		}
+		value=NULL;
+
+    /*
+     * Look for desciption
+     */
+    rc = getxpathstring(BAD_CAST todescription, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No description found");
+    } else {
+			if(call->description != NULL){
+				call->description(call->data, (char*) value);
+			}
+		}
+		value=NULL;
+
+		/*
+		 * Look for comments
+		 */
+    rc = getxpathstring(BAD_CAST tocomments, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No commentsstr found");
+    } else {
+			if(call->comments != NULL){
+				call->comments(call->data, (char*) value);
+			}
+		}
+		value=NULL;
+
+		/*
+		 * Look for guid
+		 */
+    rc = getxpathstring(BAD_CAST toguid, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No guidstr found");
+    } else {
+			if(call->guid != NULL){
+				call->guid(call->data, (char*) value);
+			}
+		}
+		value=NULL;
+
+		/*
+		 * Look for seeds
+		 */
+    rc = getxpathstring(BAD_CAST toseeds, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No seedsstr found");
+    } else {
+			if(call->seeds != NULL){
+				integer=atoi((const char*) value);
+				call->seeds(call->data, integer);
+			}
+		}
+		value=NULL;
+
+		/*
+		 * Look for peers
+		 */
+    rc = getxpathstring(BAD_CAST topeers, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No peersstr found");
+    } else {
+			if(call->peers != NULL){
+				integer=atoi((const char*) value);
+				call->peers(call->data, integer);
+			}
+		}
+		value=NULL;
+
+
+		/*
+		 * Look for size
+		 */
+    rc = getxpathstring(BAD_CAST tosize, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No sizestr found");
+    } else {
+			if(call->size != NULL){
+				filesize = atol((const char*) value);
+				call->size(call->data, filesize);
+			}
+		}
+		value=NULL;
+
+		/*
+		 * Look for content length
+		 */
+    if(xmlXPathRegisterNs(xpathCtx,  BAD_CAST "eztv", BAD_CAST "http://xmlns.ezrss.it/0.1/") != 0) {
+      rsstwritelog(LOG_DEBUG, "Error: unable to register NS with prefix");
+    }
+    rc = getxpathstring(BAD_CAST tocontentlength, xpathCtx, &value);
+    if( rc < 0 ) {
+      rsstwritelog(LOG_DEBUG, "No contentlength found");
+    } else {
+			if(call->contentlength != NULL){
+				filesize = atol((const char*) value);
+				call->contentlength(call->data, filesize);
+			}
+		}
+		value=NULL;
+
+    /*
+     * Add gatered data to the database avoiding duplicates.
+     */
+		if(call->end != NULL) {
+			call->end(call->data);
+		}
+  }
+
+	/*
+   * When done cleanup the our mess.
+   */
+  xmlXPathFreeObject(xpathObj);
+  xmlXPathFreeContext(xpathCtx);
+  xmlFreeDoc(doc);
+
+	/*
+	 * All gone well.
+	 */
+  return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssparse.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssparse.h
new file mode 100644
index 0000000..3fea2ae
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssparse.h
@@ -0,0 +1,56 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Struct with callback functions.
+ */
+typedef struct {
+	int (*category)(void *data, char *string); // Called if the category is found
+	int (*comments)(void *data, char *string); // Called if the comments is found
+	void *data; // Data struct pointer
+	int (*description)(void *data, char *string); // Called if the description is found
+	int (*enclosurelength)(void *data, size_t torsize); // Called if enclosure
+	int (*enclosuretype)(void *data, char *string); // Called if enclosure
+	int (*enclosureurl)(void *data, char *string); // Called if the enclosure url is found
+	int (*end)(void *data); // End of RSS entry
+	int (*guid)(void *data, char *string); // Called if the guid is found
+	int (*leechs)(void *data, char *string); // Called when a number of leechs is found
+	int (*link)(void *data, char *string); // Called if the link is found
+	int (*torrentlink)(void *data, char *string); // Called if the link is found
+	int (*peers)(void *data, int peers); // Called when a number of peers is found
+	int (*pubdate)(void *data, char *string); // Called if the pubdate is found
+	int (*seeds)(void *data, int seeds); // Called when a number of seeds is found
+	int (*size)(void *data, size_t size); // Called when a number of size is found
+	int (*contentlength)(void *data, size_t size); // Called when a number of size is found
+	int	(*start)(void *data); // Start new RSS entry
+	int (*title)(void *data, char *string); // Called if the title is found
+	int (*verified)(void *data, char *string); // Called if verified node is found
+} rssparse_callback;
+
+/*
+ * Routine to call parser
+ * Arguments
+ * call		Pointer to a struct holding the callback routines, all unused should be NULL
+ * url		the URL of the RSS feed.
+ * buffer	The buffer holding the RSS content.
+ * returns 0 on succes, else -1
+ */
+int rssparse(rssparse_callback *call, char *url, MemoryStruct *buffer);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsspubdate.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsspubdate.c
new file mode 100644
index 0000000..b75e8bd
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsspubdate.c
@@ -0,0 +1,85 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#include <stdio.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <time.h>
+#include <stdlib.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "disectdate.h"
+#include "disectdescription.h"
+#include "defaultrss.h"
+
+/*
+ * Use the rss data to fill out the pubdate field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsspubdate(newtorrents_struct *newtor, rssdatastruct *rssdata)
+{
+	int 		rc=0;
+	char 		*retdate=NULL;
+	time_t	founddate=0;
+
+	/*
+	 * Get the pubdate from the pubdate node.
+	 */
+	if(rssdata->pubdate != 0){
+		newtor->pubdate=rssdata->pubdate;
+
+		return 0;
+	}
+
+	/*
+	 * Get the date from description. "Episode Date:"
+	 */
+	rc = disectdescription(rssdata->description, "Episode Date", &retdate);
+	if(rc == 0){
+		/*
+		 * Disect date and store
+		 */
+		rc = rssdisectdate(retdate, &founddate);
+		free(retdate);
+		newtor->pubdate=founddate;
+
+		return 0;
+	}
+
+  /*
+   * If all else fails, use the date of today
+   */
+  newtor->pubdate=time(NULL);
+
+	/*
+	 * Not found
+	 */
+	return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsspubdate.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsspubdate.h
new file mode 100644
index 0000000..e95ef4e
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsspubdate.h
@@ -0,0 +1,31 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Use the rss data to fill out the pubdate field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsspubdate(newtorrents_struct *newtor, rssdatastruct *rssdata);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseasonepisode.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseasonepisode.c
new file mode 100644
index 0000000..81b90ec
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseasonepisode.c
@@ -0,0 +1,209 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#include <stdio.h>
+#include <sqlite3.h>
+#include <string.h>
+#include <time.h>
+#include <pcre.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "defaultrss.h"
+#include "disectdescription.h"
+
+#define OVECTSIZE 20
+
+/*
+ * Gets season and episode from string using regexp
+ * Arguments
+ * regexp 	regexp string.
+ * season		variable to store season in.
+ * episode	variable to srore episode in.
+ * Returns
+ * 0 on match, -1 on nomatch.
+ */
+static int titleregexp(char *regexp, char *title, int *season, int *episode)
+{
+  /*
+   * Example description.
+   * Category: Anime, Seeds: 20, Peers: 103, Size: 353.3 MBs
+   * extract: Category, seeds, peers, size
+   * execute regexp /Category: ([^,]*), Seeds: ([^,]*), Peers: ([^,]*), Size: (.*)$/
+   */
+  pcre *p;
+  const char *errmsg;
+  int   errpos;
+  int   ovector[OVECTSIZE];
+  int   rc;
+  int   i;
+  char *s_season;
+  char *s_episode;
+
+  /*
+   * Compile the regexp to retrieve name, season and episode
+   * try :
+   * ^(.*)(([sS]([0-9][0-9]?)))?[eE]([0-9][0-9]?))?   name, season, episode
+   */
+  p = pcre_compile((char*) regexp, 0, &errmsg, &errpos, 0);
+  if (p == NULL) {
+    /* should not happen, because init1 has already tested and set to NULL on error */
+    rsstwritelog(LOG_ERROR, "Ouch! Can't compile regular expression: %s (char %i)", errmsg, errpos);
+    exit(1);
+  }
+
+  /*
+   * execute regexp
+   */
+  rc = pcre_exec (
+      p,                   /* the compiled pattern */
+      0,                    /* no extra data - pattern was not studied */
+      (char*)title,                  /* the string to match */
+      strlen((char*)title),          /* the length of the string */
+      0,                    /* start at offset 0 in the subject */
+      0,                    /* default options */
+      ovector,              /* output vector for substring information */
+      OVECTSIZE);           /* number of elements in the output vector */
+  if (rc < 0) {
+    switch (rc) {
+      case PCRE_ERROR_NOMATCH:
+        break;
+
+      default:
+        rsstwritelog(LOG_ERROR, "Error while matching: %d %s:%d", rc, __FILE__, __LINE__);
+        exit(1);
+    }
+    free(p);
+    return -1;
+  }
+
+  /*
+   * extract both strings.
+   */
+  i = 1;
+  s_season = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(s_season, "%.*s", ovector[2*i+1] - ovector[2*i], title + ovector[2*i]);
+  i = 2;
+  s_episode = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(s_episode, "%.*s", ovector[2*i+1] - ovector[2*i], title + ovector[2*i]);
+
+  /*
+   * postprocess information.
+   */
+  *season = atoi(s_season);
+  *episode = atoi(s_episode);
+
+  rsstwritelog(LOG_DEBUG, "number of strings found '%d', season '%d' episode '%d'", rc, *season, *episode);
+
+  /*
+   * Get the 3 strings and put them in the output strings.
+   * Both need to be freed afterwards
+   */
+  free(s_season);
+  free(s_episode);
+  pcre_free(p);
+
+  return 0;
+}
+
+
+/*
+ * Get season from title
+ * Arguments
+ * season 	pointer to season int
+ * rssdata	RAW rssdata
+ * returns
+ * 0 on success, otherwise -1
+ */
+int rssseasonepisode(newtorrents_struct *newtor, rssdatastruct *rssdata)
+{
+	int rc=0;
+	int foundseason=0;
+	int foundepisode=0;
+	char *s_season=NULL;
+	char *s_episode=NULL;
+	int	i_season=0;
+	int i_episode=0;
+
+	/*
+	 * Try to get the season en episode nummer from the description
+	 */
+	foundseason  = disectdescription(rssdata->description, "Season", &s_season);
+	foundepisode = disectdescription(rssdata->description, "Episode", &s_episode);
+	if(foundepisode == 0 && foundseason == 0){
+		i_season = atoi(s_season);
+		i_episode = atoi(s_episode);
+
+		newtor->season = i_season;
+		newtor->episode = i_episode;
+
+		/*
+		 * cleanup
+		 */
+		free(s_season);
+		free(s_episode);
+
+		return 0;
+	}
+	/*
+	 * Free anyway to prevent any memoryleaks
+	 */
+	free(s_season);
+	free(s_episode);
+
+	/*
+	 * Match S[0-9]E[0-9]
+	 */
+	rc = titleregexp("^.*[sS]([0-9][0-9]?) ?[eE] ?([0-9][0-9]?)", rssdata->title, &i_season, &i_episode);
+  if(rc == 0) {
+    rsstwritelog(LOG_DEBUG, "Found title match at specific regexp %s:%d", __FILE__, __LINE__);
+		newtor->season 	= i_season;
+		newtor->episode = i_episode;
+    return 0;
+  }
+
+	/*
+	 * Match [0-9][0-9]x[0-9][0-9]
+	 */
+	rc = titleregexp("^.*[^0-9]([0-9][0-9]?) ?[xX] ?([0-9][0-9]?)", rssdata->title, &i_season, &i_episode);
+  if(rc == 0) {
+    rsstwritelog(LOG_DEBUG, "Found title match at specific regexp %s:%d", __FILE__, __LINE__);
+		newtor->season 	= i_season;
+		newtor->episode = i_episode;
+    return 0;
+  }
+
+	/*
+	 * if that failes try any pair of numbers seperated by a charakter
+	 */
+	rc = titleregexp("^[^0-9]+[Ss][[:space:]]*([0-9][0-9]?)[^0-9]+([0-9][0-9]?)[^0-9]*$", rssdata->title, &i_season, &i_episode);
+  if(rc == 0) {
+    rsstwritelog(LOG_DEBUG, "Found title match at specific regexp %s:%d", __FILE__, __LINE__);
+		newtor->season 	= i_season;
+		newtor->episode = i_episode;
+    return 0;
+  }
+
+	return -1;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseasonepisode.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseasonepisode.h
new file mode 100644
index 0000000..af70584
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseasonepisode.h
@@ -0,0 +1,30 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Get season from description
+ * Arguments
+ * season 	pointer to season int
+ * rssdata	RAW rssdata
+ * returns
+ * 0 on success, otherwise -1
+ */
+int rssseasonepisode(newtorrents_struct *newtor, rssdatastruct *rssdata);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseedspeers.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseedspeers.c
new file mode 100644
index 0000000..4827ea8
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseedspeers.c
@@ -0,0 +1,58 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#include <stdio.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <time.h>
+#include <stdlib.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "defaultrss.h"
+
+#define CATEGORY_UNKNOWN "unknown"
+
+/*
+ * Use the rss data to fill out the seeds and peers field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rssseedspeers(newtorrents_struct *newtor, rssdatastruct *rssdata)
+{
+	/*
+	 * Get seeds and peers from the nodes.
+	 */
+	newtor->seeds = rssdata->seeds;
+	newtor->peers = rssdata->peers;
+
+	/*
+	 * Otherwise do nothing
+	 */
+	return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseedspeers.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseedspeers.h
new file mode 100644
index 0000000..eecc8e2
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rssseedspeers.h
@@ -0,0 +1,31 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Use the rss data to fill out the seeds and peers field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rssseedspeers(newtorrents_struct *newtor, rssdatastruct *rssdata);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsssize.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsssize.c
new file mode 100644
index 0000000..36332fe
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsssize.c
@@ -0,0 +1,414 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#include <stdio.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <time.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "config.h"
+#include "regexp.h"
+#include "defaultrss.h"
+#include "filehandler/filehandler.h"
+#include "disectdescription.h"
+#include "database.h"
+
+#ifdef __MINGW32__
+#include "workarounds.h"
+#endif
+
+/*
+ * Used for unit conversion see humantosize and sizetohuman
+ */
+#define BUFSIZE  20
+//static const char* units[]    = {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
+static const char* unitmatch  = "BKMGTPEZY";
+
+/*
+ * Remove any XML strings from the string
+ * free **out after use.
+ * @Arguments
+ * in
+ * out
+ * @return
+ */
+static int rsstremoveescaped(char *in, double *size, char **out)
+{
+  char *cread=NULL;
+  char *cwrite=NULL;
+  char *cout=NULL;
+  int copy=1; // 1 is copy, 0 is don't
+
+  cread=in;
+  cwrite=calloc(1, ((size_t)*size) +1);
+  cout=cwrite;
+  if(cwrite == NULL)
+  {
+    return 0;
+  }
+
+  while(*cread != '\0'){
+    // Copy off on start escape
+    if(*cread == '&')
+    {
+      copy=0;
+    }
+
+    // When copy is on, copy the data
+    if(copy == 1)
+    {
+      *cwrite=*cread;
+      cwrite++;
+    }
+
+    // Copy on end of escape
+    if(*cread == ';')
+    {
+      copy=1;
+    }
+
+    cread++;
+  }
+
+  *out=cout;
+
+  return 0;
+}
+
+/*
+ * buf must be a pre-allocated buffer with size BUFSIZE+1
+ * returns 0 and -1 on error
+ * size in bytes is returned in argument size
+ */
+int rssthumantosize(char *buf, double *size)
+{
+  char    upcasenum[BUFSIZE+1];
+  char    *unit=NULL;
+  char    *stripped=NULL;
+  int     i=0;
+  long double  tempsize=0.0;
+  int     power=0;
+  int     rc=0;
+
+  /*
+   * When buf or size = NULL, return -1
+   */
+  if( buf == NULL || size == NULL){
+    rsstwritelog(LOG_ERROR, "Invalid pointer passed to humantosize function. %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Remove any XML escaped characters.
+   */
+  rc = rsstremoveescaped(buf, size, &stripped);
+  if(rc != 0){
+    rsstwritelog(LOG_ERROR, "Could not parse escaped strings.k%s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Initialize stuff
+   */
+  memset(upcasenum, 0, BUFSIZE+1);
+  strncpy(upcasenum, stripped, BUFSIZE);
+  free(stripped);
+
+  /*
+   * transform the human readable string to a power of 1024
+   */
+  for( i = 0; upcasenum[ i ]; i++)
+  {
+    upcasenum[ i ] = toupper( upcasenum[ i ] );
+  }
+
+  /*
+   * returns a pointer to the first occurrence in string s1 of any character from string s2, or a null pointer if no character from s2 exists in s1
+   */
+  unit = strpbrk(upcasenum, unitmatch);
+
+  /*
+   * Get size
+   */
+  tempsize = atof(upcasenum);
+
+  /*
+   * when no unit is found use a power of 1024^0
+   * Otherwise calculate number of bytes
+   */
+  if(unit != NULL){
+    /*
+     * Calculate the number of bytes out.
+     */
+    while(*(unitmatch + power) != '\0'){
+      if(*unit == *(unitmatch + power)) {
+        break;
+      }
+      power++;
+    }
+  }
+
+  /*
+   * Calculate response
+   */
+  *size = (double) tempsize * pow(1024, power);
+
+  return 0;
+}
+
+
+/*
+ * Get the size from the description
+ * @Arguments
+ * rssdata Structure containing data from record.
+ * size found size from description
+ * @Return
+ * returns 0 on success, otherwise -1
+ */
+static int rsstsizefromdesription(rssdatastruct *rssdata, size_t *foundsize)
+{
+  int retval=-1;
+  int rc=0;
+  char *descstr=NULL;
+  char *token=NULL;
+  char *origptr=NULL;
+  char *sizestr=NULL;
+  double descsize=0.0;
+
+  const char *sizetoken="size";
+  const char *delim="\n";
+
+  /*
+   * Sanity check
+   */
+  if(rssdata->description == NULL){
+    return -1;
+  }
+
+  /*
+   * Copy description
+   */
+  rsstalloccopy(&descstr, rssdata->description, strlen(rssdata->description));
+  token=descstr;
+  origptr=descstr;
+
+  /*
+   * Look at description, find size
+   */
+  token = strsep(&descstr, delim);
+  while(token != NULL){
+    /*
+     * Find a line starting with "Size"
+     */
+    if(strncasecmp(token, sizetoken, strlen(sizetoken)) == 0) {
+
+      /*
+       * When found, put into size to human.
+       */
+      sizestr=token+strlen(sizetoken);
+      rc = rssthumantosize(sizestr, &descsize);
+      if(rc == 0){
+        retval=0;
+        *foundsize = descsize;
+      } else {
+        rsstwritelog(LOG_ERROR, "Could not get size from '%s' %s:%d", sizestr, __FILE__, __LINE__);
+     }
+
+      break;
+    }
+
+    token = strsep(&descstr, delim);
+  }
+
+  /*
+   * Clean up
+   */
+  free(origptr);
+
+  /*
+   * All done
+   */
+  return retval;
+}
+
+static int rsstsizefromdatabase(rssdatastruct *rssdata, size_t *size)
+{
+  int rc=0;
+  char *result=NULL;
+  rsstor_handle *handle=NULL;
+  char *link=NULL;
+
+  /*
+   * Query to retrieve the size from the database
+   */
+  char *query="select size from newtorrents where link=?1";
+
+  /*
+   * Get the handle
+   */
+  handle = rssdata->handle;
+
+  /*
+   * Choose between link and torrentlink
+   */
+  if(rssdata->torrentlink != NULL) {
+    link=rssdata->torrentlink;
+  } else {
+    link=rssdata->link;
+  }
+
+  /*
+   * execute query to retrieve the size stored in the database
+   */
+  rc = rsstdosingletextquery(handle->db, (unsigned char const**) &result, query, "s", link);
+  if(rc != 0 || result == NULL) {
+    /*
+     * not yet in database.
+     */
+    return -1;
+  }
+
+  /*
+   * When found set the new size
+   */
+  *size = (size_t) atol(result);
+  free(result);
+
+  /*
+   * Success !
+   */
+  return 0;
+}
+
+/*
+ * Use the rss data to fill out the seeds and peers field in the new torrent struct.
+ * @Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * @Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsssize(newtorrents_struct *newtor, rssdatastruct *rssdata)
+{
+	int				    rc=0;
+	size_t 		    i_size=0;
+	size_t 		    i_length=0;
+  size_t        i_contlength=0;
+	long			    min_config=0;
+	metafileprops	*props=NULL;
+  char          *torlink=NULL;
+	int				    retval=0;
+  METAFILETYPE  type=undefined;
+  rsstor_handle *handle=rssdata->handle;
+
+	/*
+	 * Get from size node.
+	 */
+	i_size = rssdata->size;
+
+	/*
+	 * Get size from enclosure length
+	 */
+	i_length = rssdata->enclosurelength;
+
+  /*
+   * Get the content length
+   */
+  i_contlength = rssdata->contentlength;
+
+	/*
+	 * Pick the biggest.
+	 */
+	if(i_size > i_length) {
+		newtor->size = i_size;
+	} else {
+		newtor->size = i_length;
+	}
+  if(newtor->size < i_contlength) {
+    newtor->size = i_contlength;
+  }
+
+  /*
+   * convert metafile type
+   */
+  rc = metafilestrtotype(newtor->metatype, &type);
+  if(rc != 0){
+		rsstwritelog(LOG_ERROR, "Not corrent meta type '%s' %s:%d",
+      newtor->metatype, __FILE__, __LINE__ );
+		return -1;
+  }
+
+	/*
+	 * When smaller than 'min_size'
+	 */
+	rc = rsstconfiggetlong(rssdata->handle, CONF_MIN_SIZE , &min_config);
+	if(rc != 0){
+		rsstwritelog(LOG_ERROR, "Configuration variable '%s' not set!", CONF_MIN_SIZE);
+		return -1;
+	}
+
+  /*
+   * When smaller than min_size get size from the database
+   */
+	if( newtor->size < (size_t) min_config) {
+    rsstsizefromdatabase(rssdata, &(newtor->size));
+  }
+
+  /*
+   * Get the size from the description
+   */
+	if( newtor->size < (size_t) min_config) {
+    rc = rsstsizefromdesription(rssdata, &(newtor->size));
+  }
+
+  /*
+   * When still smaller than size resort to downloading the metafile and getting the size that way.
+   */
+	if( newtor->size < (size_t) min_config) {
+    if(rssdata->torrentlink != NULL){
+      torlink = rssdata->torrentlink;
+    } else {
+      torlink = rssdata->link;
+    }
+    printf("Downloading to double check: '%s'\n", torlink);
+		/*
+		 * Download the torrent to verify the length
+		 */
+		rc = rsstgetmetafileinfo(handle, type, torlink, &props);
+		if(rc == 0) {
+			newtor->size = props->size;
+		} else {
+			retval = -1;
+		}
+		rsstfreemetafileprops(props);
+	}
+
+	return retval;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsssize.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsssize.h
new file mode 100644
index 0000000..2c17a3f
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsssize.h
@@ -0,0 +1,31 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Use the rss data to fill out the seeds and peers field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsssize(newtorrents_struct *newtor, rssdatastruct *rssdata);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsstitle.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsstitle.c
new file mode 100644
index 0000000..bc549f0
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsstitle.c
@@ -0,0 +1,78 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <sqlite3.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "regexp.h"
+#include "defaultrss.h"
+#include "disectdescription.h"
+
+/*
+ * Use the rss data to fill out the title field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsstitle(newtorrents_struct *newtor, rssdatastruct *rssdata)
+{
+	int 	rc=0;
+	char 	*temp=NULL;
+
+	/*
+	 * Get title from title field
+	 */
+	if(rssdata->title != NULL && strlen(rssdata->title) != 0) {
+		rsstalloccopy(&(newtor->title), rssdata->title, strlen(rssdata->title));
+		rsstcleanupstring(newtor->title);
+	}
+
+	/*
+	 * Try to get the title from the description first
+	 */
+	if(newtor->title ==NULL){
+		rc = disectdescription(rssdata->description, "Show Name", &temp);
+		if(rc == 0) {
+			newtor->title = temp;
+		}
+	}
+
+	if(newtor->title != NULL){
+		rsstcleanupstring(newtor->title);
+		return 0;
+	}
+
+	/*
+	 * Not found
+	 */
+	return -1;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsstitle.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsstitle.h
new file mode 100644
index 0000000..b121254
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/defaultrss/rsstitle.h
@@ -0,0 +1,31 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Use the rss data to fill out the title field in the new torrent struct.
+ * Arguments
+ * newtor		: New torrent structure.
+ * rssdata	: The struct holding the raw rssdata.
+ * Returns
+ * 0 on succes, -1 on failure.
+ * Errors are logged.
+ */
+int rsstitle(newtorrents_struct *newtor, rssdatastruct *rssdata);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/CMakeLists.txt b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/CMakeLists.txt
new file mode 100644
index 0000000..35a5950
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/CMakeLists.txt
@@ -0,0 +1,5 @@
+#rsstorrentfilter
+SET(RSSTORRENT_PATH srcparser/twitter)
+
+SET(LIBSRC ${LIBSRC} ${RSSTORRENT_PATH}/twitter ${RSSTORRENT_PATH}/twitparse ${RSSTORRENT_PATH}/splittext
+		${RSSTORRENT_PATH}/parsedate)
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/parsedate.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/parsedate.c
new file mode 100644
index 0000000..176851e
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/parsedate.c
@@ -0,0 +1,84 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+#define _XOPEN_SOURCE /* glibc2 needs this */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "logfile.h"
+
+#ifdef __MINGW32__
+#include "workarounds.h"
+#endif
+
+/*
+ * Gets the timestring.
+ * Exports time_t value
+ */
+int disectdate(char *date, time_t *pubdate)
+{
+  char      *rc;
+  struct tm pubtm;
+  time_t    now;
+
+  /*
+   * init struct.
+   */
+  memset(&pubtm, 0, sizeof(pubtm));
+  mktime(&pubtm);
+
+  // char *strptime(const char *buf, const char *format, struct tm *tm);
+  // Fri, 02 Oct 2009 17:23:06 -0500
+  // %a, %d %b %Y %H:%M:%S
+  // 2009-10-05
+  // %Y-%m-%d
+  // When all failes use time 'now'
+  rc = strptime(date, "%a, %d %b %Y %H:%M:%S", &pubtm);
+  if(rc == NULL) {
+    rsstwritelog(LOG_DEBUG, "Converting date '%s'.\n", date);
+    rc = strptime(date, "%Y-%m-%d", &pubtm);
+  }
+  if(rc == NULL) {
+    /*
+     * When all else fails it's a safe bet to set the date to 'now'
+     */
+    rsstwritelog(LOG_DEBUG, "Converting date '%s' failed, used 'now' as substitute.", date);
+    now = time ( NULL );
+    localtime_r ( &now, &pubtm );
+
+  }
+
+  pubtm.tm_isdst = -1;      /* Not set by strptime(); tells mktime()
+                               to determine whether daylight saving time
+                               is in effect */
+
+  /*
+   * struct tm to time_t
+   */
+  *pubdate = mktime(&pubtm);
+
+  rsstwritelog(LOG_DEBUG, "Converted ctime: %s\n", ctime(pubdate));
+
+  /*
+   * success
+   */
+  return 0;
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/parsedate.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/parsedate.h
new file mode 100644
index 0000000..34d806c
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/parsedate.h
@@ -0,0 +1,26 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Gets the timestring.
+ * Exports time_t value
+ * Allways returns 0, returnvalue not used yet.
+ */
+int disectdate(char *date, time_t *pubdate);
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/splittext.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/splittext.c
new file mode 100644
index 0000000..a9962d3
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/splittext.c
@@ -0,0 +1,256 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <pcre.h>
+#include <sqlite3.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "curlfile.h"
+#include "logfile.h"
+#include "twitparse.h"
+
+#define   OVECSIZE 20
+
+/*
+ * Get data and link.
+ */
+int getdataandlink(char *text, char **data, char **link)
+{
+  pcre 		*p=NULL;
+  int   	ovector[OVECSIZE];
+  const char *errmsg=NULL;
+  int   	errpos=0;
+	static char *splitregexp="^(.*) - (https?://[^ ]*).*$";
+	int 		i=0;
+	int			rc=0;
+
+	/*
+	 * Init input variables.
+	 */
+	*data=NULL;
+	*link=NULL;
+
+  /*
+   * Compile the regexp te split the two strings.
+   */
+  p = pcre_compile(splitregexp, 0, &errmsg, &errpos, 0);
+  if (p == NULL) {
+    /* should not happen, because init1 has already tested and set to NULL on error */
+    fprintf(stderr, "Ouch! Can't compile regular expression: %s (char %i) %s:%d",
+        errmsg, errpos, __FILE__, __LINE__);
+		return -1;
+  }
+
+  /*
+   * execute regexp
+   */
+  rc = pcre_exec (
+      p,                   	/* the compiled pattern */
+      0,                    /* no extra data - pattern was not studied */
+      text,                  /* the string to match */
+      strlen(text),          /* the length of the string */
+      0,                    /* start at offset 0 in the subject */
+      0,                    /* default options */
+      ovector,              /* output vector for substring information */
+      OVECSIZE);           	/* number of elements in the output vector */
+
+	/*
+	 * No match is return 0
+	 */
+  if (rc < 0) {
+    switch (rc) {
+      case PCRE_ERROR_NOMATCH:
+				/*
+				 * no username/password match
+				 */
+				pcre_free(p);
+				return 0;
+        break;
+      default:
+        rsstwritelog(LOG_ERROR, "Error while matching url. %d %s:%d", rc, __FILE__, __LINE__);
+        break;
+    }
+    free(p);
+    return -1;
+  }
+
+	/*
+	 * Match, get data and url
+	 */
+  i = 1;
+  *data = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(*data, "%.*s", ovector[2*i+1] - ovector[2*i], text + ovector[2*i]);
+  i = 2;
+  *link = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(*link, "%.*s", ovector[2*i+1] - ovector[2*i], text + ovector[2*i]);
+
+	/*
+	 * free tempstuff
+	 */
+	pcre_free(p);
+
+	return 1;
+}
+
+/*
+ * Extract data from text.
+ */
+int getnamelinkepisode(char *data, char **name, int *season, int *episode)
+{
+  pcre 		*p=NULL;
+  int   	ovector[OVECSIZE];
+  const char *errmsg=NULL;
+  int   	errpos=0;
+	static char *dataregexp="(.*) ?[sS ]([0-9]?[0-9])[eExX ]([0-9]?[0-9])";
+	char   	*seasonstr=NULL;
+	char		*episodestr=NULL;
+	int 		i=0;
+	int			rc=0;
+
+	/*
+	 * Init input variables.
+	 */
+	*name=NULL;
+	*season=0;
+	*episode=0;
+
+  /*
+   * Compile the regexp te split the two strings.
+   */
+  p = pcre_compile(dataregexp, 0, &errmsg, &errpos, 0);
+  if (p == NULL) {
+    /* should not happen, because init1 has already tested and set to NULL on error */
+    fprintf(stderr, "Ouch! Can't compile regular expression: %s (char %i) %s:%d",
+        errmsg, errpos, __FILE__, __LINE__);
+		return -1;
+  }
+
+  /*
+   * execute regexp
+   */
+  rc = pcre_exec (
+      p,                   	/* the compiled pattern */
+      0,                    /* no extra data - pattern was not studied */
+      data,                  /* the string to match */
+      strlen(data),          /* the length of the string */
+      0,                    /* start at offset 0 in the subject */
+      0,                    /* default options */
+      ovector,              /* output vector for substring information */
+      OVECSIZE);           	/* number of elements in the output vector */
+
+	/*
+	 * No match is return 0
+	 */
+  if (rc < 0) {
+    switch (rc) {
+      case PCRE_ERROR_NOMATCH:
+				/*
+				 * no username/password match
+				 */
+				pcre_free(p);
+				return 0;
+        break;
+      default:
+        rsstwritelog(LOG_ERROR, "Error while matching url. %d %s:%d", rc, __FILE__, __LINE__);
+        break;
+    }
+    free(p);
+    return -1;
+  }
+
+	/*
+	 * Match, get data and url
+	 */
+  i = 1;
+  *name = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(*name, "%.*s", ovector[2*i+1] - ovector[2*i], data + ovector[2*i]);
+  i = 2;
+  seasonstr = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(seasonstr, "%.*s", ovector[2*i+1] - ovector[2*i], data + ovector[2*i]);
+  i = 3;
+  episodestr = calloc(1, ovector[2*i+1]-ovector[2*i]+1);
+  sprintf(episodestr, "%.*s", ovector[2*i+1] - ovector[2*i], data + ovector[2*i]);
+
+	/*
+	 * translate to int.
+	 */
+	*episode = atoi(episodestr);
+	*season = atoi(seasonstr);
+
+	/*
+	 * free tempstuff
+	 */
+	free(seasonstr);
+	free(episodestr);
+	pcre_free(p);
+
+	return 1;
+}
+
+
+/*
+ * Examines the tweet, and splits it into
+ * name
+ * link
+ * season
+ * episode
+ * returns 0 on succes -1 on fail.
+ */
+int splittext(char *text, char **name, char **link, int *season, int *episode)
+{
+	char *data=NULL;
+	int		rc=0;
+  int   retval=0;
+
+	/*
+	 * Split the initial data and link.
+	 */
+	rc = getdataandlink(text, &data, link);
+	if(rc != 1) {
+		rsstwritelog(LOG_DEBUG, "Tweet does not hold and url: '%s'", text);
+		retval = -1;
+	}
+
+	/*
+	 * Split the data, into name, season, episode.
+	 */
+  if(retval == 0) {
+    rc = getnamelinkepisode(data, name, season, episode);
+    if(rc != 1) {
+      rsstwritelog(LOG_DEBUG, "Tweet does not contain season and episode info: '%s'", text);
+      retval = -1;
+    }
+  }
+
+  /*
+	 * free stuff.
+	 */
+	free(data);
+
+	return retval;
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/splittext.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/splittext.h
new file mode 100644
index 0000000..0dd510f
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/splittext.h
@@ -0,0 +1,30 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Examines the tweet, and splits it into
+ * name
+ * link
+ * season
+ * episode
+ * returns 0 on succes -1 on fail.
+ */
+int splittext(char *text, char **name, char **link, int *season, int *episode);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitparse.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitparse.c
new file mode 100644
index 0000000..45706db
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitparse.c
@@ -0,0 +1,230 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <curl/curl.h>
+#include <sqlite3.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "logfile.h"
+#include "curlfile.h"
+#include "twitparse.h"
+
+
+static char *tostatus="/statuses/status";
+static char *totext="text";
+static char *tocreatedat="created_at";
+
+/*
+ * Same as xmlXPathEvalExpression, but preserves current node.
+ * This enables relative xpaths.
+ */
+static xmlXPathObjectPtr myXmlXPathEval( const xmlChar * str, xmlXPathContextPtr ctxt)
+{
+  xmlNode *temp;
+  xmlXPathObjectPtr xpathObj;
+
+  temp = ctxt->node;
+
+  xpathObj = xmlXPathEvalExpression(str, ctxt);
+
+  ctxt->node = temp;
+
+  return xpathObj;
+}
+
+/*
+ * Execute the xpath query and return the pointer to the string in that node.
+ * 'string' should not be freed, as it is pointing to a string inside the DOM-tree.
+ * return 0 when okay, -1 when failed.
+ */
+static int getxpathstring(const xmlChar * str, xmlXPathContextPtr ctxt, unsigned char **string)
+{
+  xmlXPathObjectPtr xpathObj;
+  xmlNode *node;
+
+  *string = NULL;
+
+  /*
+   * Evaluate xpath
+   */
+  xpathObj = myXmlXPathEval(str, ctxt);
+
+  /*
+   * When no results are found fail.
+   */
+  if( xpathObj->nodesetval->nodeNr == 0) {
+    xmlXPathFreeObject(xpathObj);
+    return -1;
+  }
+
+  /*
+   * get the pointer to the first node.
+   */
+  node = xpathObj->nodesetval->nodeTab[0];
+
+  /*
+   * Set pointer to contentstring in child
+   */
+  *string = BAD_CAST node->children->content;
+
+  /*
+   * Clean up
+   */
+  xmlXPathFreeObject(xpathObj);
+
+  /*
+   * All gone well
+   */
+  return 0;
+}
+
+/*
+ * filter to handle incomming files from http://www.rsstorrents.com
+ */
+int twitparse(twitparse_callback *call, char *url, MemoryStruct *buffer)
+{
+  xmlDocPtr           doc = NULL; /* the resulting document tree */
+  xmlNode             *root_element = NULL;
+  //xmlNode *cur_node = NULL;
+  xmlXPathContextPtr  xpathCtx;
+  xmlXPathObjectPtr   xpathObj;
+  xmlNodeSetPtr       nodeset;
+  int                 count = 0;
+	unsigned char				*text;
+	unsigned char				*date;
+  int                 rc = 0;
+
+  /*
+   * Use the imput to feed libxml2
+   */
+  doc = xmlReadMemory(buffer->memory, buffer->size, url, NULL, 0);
+  if (doc == NULL) {
+    //rsstwritelog(LOG_ERROR, "Failed to parse document %s:%d\n", __FILE__, __LINE__);
+    fprintf(stderr, "Failed to parse document %s:%d\n", __FILE__, __LINE__);
+    return -1;
+  }
+  root_element = xmlDocGetRootElement(doc);
+
+  /* Create xpath evaluation context */
+  xpathCtx = xmlXPathNewContext(doc);
+  if(xpathCtx == NULL) {
+    //rsstwritelog(LOG_ERROR, "Error: unable to create new XPath context %s:%d\n", __FILE__, __LINE__);
+    fprintf(stderr, "Error: unable to create new XPath context %s:%d\n", __FILE__, __LINE__);
+    xmlFreeDoc(doc);
+    return(-1);
+  }
+
+  /*
+   * Get the item nodes in channel.
+   */
+  xpathObj = myXmlXPathEval(BAD_CAST tostatus, xpathCtx);
+  if(xpathObj == NULL) {
+    //rsstwritelog(LOG_ERROR, "Error: unable to evaluate xpath expression \"%s\" %s:%d\n", toitems, __FILE__, __LINE__);
+    fprintf(stderr, "Error: unable to evaluate xpath expression \"%s\" %s:%d\n", tostatus, __FILE__, __LINE__);
+    xmlXPathFreeContext(xpathCtx);
+    xmlFreeDoc(doc);
+    return(-1);
+  }
+
+  /*
+   * Get the nodeset returned from the query
+   */
+  nodeset = xpathObj->nodesetval;
+
+  /*
+   * Loop through the nodes we need.
+   */
+	for(count = 0; count < nodeset->nodeNr; count++) {
+		/*
+		 * Set current node for XPath queries.
+		 */
+		xpathCtx->node = nodeset->nodeTab[count];
+
+		/*
+		 * Call the newtwit hook
+		 */
+		if(call->newtweet != NULL){
+			call->newtweet(call->data);
+		}
+
+		/*
+		 * Get text
+		 */
+		rc = getxpathstring(BAD_CAST totext, xpathCtx, &text);
+		if( rc < 0 ) {
+
+		} else {
+			//rsstwritelog(LOG_DEBUG, "title: %s", title);
+		 if(call->gettext != NULL){
+				rc = call->gettext(call->data, (char*) text);
+				if(rc < 0) {
+					rsstwritelog(LOG_ERROR, "gettext returned '%d'. %s:%d", rc, __FILE__, __LINE__);
+				}
+		 }
+		}
+
+		/*
+		 * Get created_at
+		 */
+		rc = getxpathstring(BAD_CAST tocreatedat, xpathCtx, &date);
+		if( rc < 0 ) {
+		} else {
+			if(call->getcreatedate != NULL) {
+				rc = call->getcreatedate(call->data, (char*) date); // Called when createdate is found
+				if(rc < 0) {
+					rsstwritelog(LOG_ERROR, "getcreatedate returned '%d'. %s:%d", rc, __FILE__, __LINE__);
+				}
+			}
+		}
+
+		/*
+		 * Call the endtweet hook
+		 */
+		if(call->endtweet != NULL){
+			call->endtweet(call->data);
+		}
+	}
+
+	/*
+	 * Call the donetweet hook parsing done.
+	 */
+	if(call->donetweet != NULL){
+		call->donetweet(call->data);
+	}
+
+	/*
+	 * When done cleanup the our mess.
+	 */
+	xmlXPathFreeObject(xpathObj);
+	xmlXPathFreeContext(xpathCtx);
+	xmlFreeDoc(doc);
+
+	return 0;
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitparse.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitparse.h
new file mode 100644
index 0000000..c189aaf
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitparse.h
@@ -0,0 +1,38 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Structure holding the callback the parser calls.
+ * When a callbackpointer is NULL, no function is called.
+ */
+typedef struct {
+	void *data; // Store use data in this struct.
+	int (*newtweet)(void *data); // Called on the start of parsing a record
+	int (*gettext)(void *data, char *string); // Called the the twittertext is found
+	int (*getcreatedate)(void *data, char *string); // Called when createdate is found
+	int (*endtweet)(void *data); // Called on the start of parsing a record
+	int (*donetweet)(void *data); // Called on the start of parsing a record
+} twitparse_callback;
+
+/*
+ * filter to handle incomming files from http://www.rsstorrents.com
+ */
+int twitparse(twitparse_callback *call, char *url, MemoryStruct *buffer);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitter.c b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitter.c
new file mode 100644
index 0000000..e5e88d1
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitter.c
@@ -0,0 +1,211 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <stdlib.h>
+
+#ifdef __MINGW32__
+#include "../../types.h"  /* looks damn ugly! */
+#else
+#include "types.h"
+#endif
+#include "curlfile.h"
+#include "logfile.h"
+#include "twitparse.h"
+#include "twitter.h"
+#include "splittext.h"
+#include "filehandler/filehandler.h"
+#include "torrentdb.h"
+#include "parsedate.h"
+
+static int newtweet(void *data)
+{
+	char *source=NULL;
+
+	twitterdata *local = (twitterdata*) data;
+
+	rsstwritelog(LOG_DEBUG, "New Tweet\n");
+
+	/*
+	 * Save statics
+	 */
+	source = local->source;
+
+	/*
+	 * Clear tweet struct
+	 */
+	memset(&(local->tweet), 0, sizeof(tweetdata));
+
+	/*
+	 * Restore statics
+	 */
+	local->source = source;
+
+	return 0;
+}
+
+/*
+ * Called on end of tweet-info
+ */
+static int endtweet(void *data)
+{
+	twitterdata   *local = (twitterdata*) data;
+	rsstor_handle *handle = local->handle;
+	metafileprops *props=NULL;
+	int					    rc=0;
+	newtorrents_struct newtor;
+
+	/*
+	 * Clean newtor
+	 */
+	memset(&newtor, 0, sizeof(newtorrents_struct));
+
+	/*
+	 * Use data to create database record.
+	 */
+	rc = splittext(local->tweet.text, &(newtor.title), &(newtor.link), &(newtor.season), &(newtor.episode));
+	if(rc < 0){
+    rsstfreemetafileprops(props);
+    rsstfreenewtor(&newtor);
+		/*
+		 * Text could not be split, no torrent record.
+		 */
+		return -1;
+	}
+
+	/*
+	 * Process data
+	 */
+	rc = rsstgetmetafileinfo(handle, torrent, newtor.link, &props);
+	if(rc < 0){
+		rsstwritelog(LOG_DEBUG, "Download failed for '%s'\n", newtor.link);
+    rsstfreemetafileprops(props);
+    rsstfreenewtor(&newtor);
+		/*
+		 * No torrent.
+		 */
+		return -1;
+	}
+	newtor.source=local->source;
+	newtor.size=(long) props->size;
+
+	/*
+	 * Print stuff.
+	 */
+	rsstwritelog(LOG_DEBUG, "link: %s, title: %s, season: %d, episode: %d, size: %ld\n",
+			newtor.link, newtor.title, newtor.season, newtor.episode,(long) props->size);
+
+	/*
+	 * Parse date to string
+	 */
+	disectdate(local->tweet.createdate, &(newtor.pubdate));
+
+	/*
+	 * Add a torrent to the newtorrents table.
+	 */
+	rsstaddnewtorrent(handle, &newtor);
+
+	/*
+	 * cleanup
+	 */
+	rsstfreemetafileprops(props);
+	rsstfreenewtor(&newtor);
+
+	rsstwritelog(LOG_DEBUG, "End Tweet\n");
+
+	return 0;
+}
+
+static int twittertext(void *data, char *string)
+{
+	twitterdata *local = (twitterdata*) data;
+	//sqlite3 *db = local->db;
+
+	/*
+	 * Debugging : print the twittertext we found.
+	 */
+	rsstwritelog(LOG_DEBUG, "Twitter text : '%s'\n", string);
+	local->tweet.text=string;
+
+	return 0;
+}
+
+static int twittecreaterdate(void *data, char *string)
+{
+	twitterdata *local = (twitterdata*) data;
+	//sqlite3 *db = local->db;
+
+	rsstwritelog(LOG_DEBUG, "Twitter createdate: '%s'\n", string);
+	local->tweet.createdate=string;
+
+	return 0;
+}
+
+/*
+ * filter to handle incomming files from a twitter timeline
+ */
+int twitter(rsstor_handle *handle, char *name, char *url, char *filter, char *metatype, MemoryStruct *rssfile)
+{
+	twitparse_callback twitcallback;
+	twitterdata				 twitdata;
+	int								 rc=0;
+	int								 retval=0;
+
+	/*
+	 * All to NULL
+	 */
+	memset(&twitcallback, 0, sizeof(twitparse_callback));
+	memset(&twitdata, 0, sizeof(twitterdata));
+
+	/*
+	 * Init data.
+	 */
+	twitdata.handle=handle;
+	twitdata.source=name;
+  twitdata.metatype=metatype;
+
+	/*
+	 * Initialize parser callbacks.
+	 */
+	twitcallback.gettext = twittertext;
+	twitcallback.getcreatedate = twittecreaterdate;
+	twitcallback.newtweet = newtweet;
+	twitcallback.endtweet = endtweet;
+	twitcallback.data = &twitdata;
+
+	/*
+	 * Call the filter to transform the timeline into database entries.
+	 * when failed return -1
+	 */
+	rc = twitparse(&twitcallback, url, rssfile);
+	if(rc != 0){
+		rsstwritelog(LOG_ERROR, "Twitter stream url '%s' name '%s' filter '%s' fialed ! %s:%d", url, name, filter, __FILE__, __LINE__);
+		retval = -1;
+	}
+
+	/*
+	 * Done.
+	 */
+	return retval;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitter.h b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitter.h
new file mode 100644
index 0000000..ad92b25
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/srcparser/twitter/twitter.h
@@ -0,0 +1,43 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Tweet data
+ */
+typedef struct {
+	char *text;
+	char *createdate;
+} tweetdata;
+
+/*
+ * Data we like to pass to the callback routines.
+ */
+typedef struct {
+	rsstor_handle *handle;
+	tweetdata tweet;
+	char 			*source; // Static, not changed during parsing
+  char      *metatype; // Type of metafiles to expect (Torrent/NZB)
+} twitterdata;
+
+/*
+ * Filter to handle incomming files from a Twitter timeline
+ */
+int twitter(rsstor_handle *handle, char *name, char *url, char *filter, char *metatype, MemoryStruct *rssfile);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/stats.c b/tags/swarmtv-0.9.2/libswarmtv/stats.c
new file mode 100644
index 0000000..d599ff0
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/stats.c
@@ -0,0 +1,374 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "types.h"
+#include "database.h"
+#include "logfile.h"
+#include "filesystem.h"
+#include "database.h"
+#include "databaseimpl.h"
+#include "torrentdownload.h"
+
+/*
+ * Get database size
+ * @Arguments
+ * size the size of the database file
+ * @return
+ * 0 when all has gone well, -1 on error
+ */
+static int rsstgetdbsize(size_t *dbsize)
+{
+  struct stat dbstat;
+  int         rc=0;
+  int         retval=0;
+  char        *dbpath=NULL;
+
+  /*
+   * Get the complete path to the DB
+   */
+  rsstcompletepath(RSST_DBFILE, &dbpath);
+
+  /*
+   * Get the information
+   */
+  rc = stat(dbpath, &dbstat);
+  if(rc == 0){
+    *dbsize=dbstat.st_size;
+  } else {
+    rsstwritelog(LOG_ERROR, "Could not retrieve size of '%s'! %s:%d", dbpath,  __FILE__, __LINE__);
+    retval=-1;
+  }
+
+  /*
+   * Clean up
+   */
+  free(dbpath);
+
+  return retval;
+}
+
+/*
+ * Get meta file count
+ * @Arguments
+ * count metafile count number of entries in newtorrents file.
+ * @Return
+ * 0 return on success, -1 on failure
+ */
+static int rsstgetmetafile(rsstor_handle *handle, int *count)
+{
+  int retval=0;
+  char *countstr=NULL;
+
+  /*
+   * Query
+   */
+  char *query = "select count(*) from newtorrents";
+
+  /*
+   * execute query
+   */
+  retval = rsstdosingletextquery(handle->db, (unsigned char const**) &countstr, query, NULL);
+  if(retval == 0){
+    /*
+     * Get results
+     */
+    *count = atoi(countstr);
+  }
+
+  /*
+   * Free stuff
+   */
+  free(countstr);
+
+  /*
+   * Done
+   */
+  return retval;
+}
+
+
+/*
+ * Get downloaded count
+ * @Arguments
+ * downloaded
+ * @Return
+ * 0 return on success, -1 on failure
+ */
+static int rsstgetdownloadedcount(rsstor_handle *handle, int *count)
+{
+  int retval=0;
+  char *countstr=NULL;
+
+  /*
+   * Query
+   */
+  char *query = "select count(*) from downloaded";
+
+  /*
+   * execute query
+   */
+  retval = rsstdosingletextquery(handle->db, (unsigned char const**) &countstr, query, NULL);
+  if(retval == 0) {
+    /*
+     * Get results
+     */
+    *count = atoi(countstr);
+  }
+
+  /*
+   * Free stuff
+   */
+  free(countstr);
+
+  /*
+   * Done
+   */
+  return retval;
+}
+
+
+/*
+ * Get sources count
+ * @Arguments
+ * sources
+ * @Return
+ * 0 return on success, -1 on failure
+ */
+static int rsstgetsources(rsstor_handle *handle, int *count)
+{
+  int retval=0;
+  char *countstr=NULL;
+
+  /*
+   * Query
+   */
+  char *query = "select count(*) from sources";
+
+  /*
+   * execute query
+   */
+  retval = rsstdosingletextquery(handle->db, (unsigned char const**) &countstr, query, NULL);
+  if(retval == 0) {
+    /*
+     * Get results
+     */
+    *count = atoi(countstr);
+  }
+
+  /*
+   * Free stuff
+   */
+  free(countstr);
+
+  /*
+   * Done
+   */
+  return retval;
+}
+
+
+/*
+ * Get sources count
+ * @Arguments
+ * version
+ * @Return
+ * 0 return on success, -1 on failure
+ */
+static void rsstgetversion(char **version)
+{
+  /*
+   * Set version from header
+   */
+  *version = RSST_VERSION;
+}
+
+
+/*
+ * Get database version
+ * @Arguments
+ * version database version
+ * @return
+ * returns 0 on success, -1 on failure
+ */
+static int rsstgetdbversion(rsstor_handle *handle, int *version)
+{
+  int retval=0;
+  char *versionstr=NULL;
+
+  /*
+   * Query
+   */
+  char *query = "select version from version";
+
+  /*
+   * execute query
+   */
+  retval = rsstdosingletextquery(handle->db, (unsigned char const**) &versionstr, query, NULL);
+  if(retval == 0) {
+    /*
+     * Get results
+     */
+    *version = atoi(versionstr);
+  }
+
+  /*
+   * Free stuff
+   */
+  free(versionstr);
+
+  /*
+   * Done
+   */
+  return retval;
+}
+
+/*
+ * Get number of simple filters
+ * @Arguments
+ * simple number of simple filters in the database
+ * @return
+ * 0 when success, -1 when failed.
+ */
+static int rsstgetsimplecount(rsstor_handle *handle, int *count)
+{
+  int retval=0;
+  char *countstr=NULL;
+
+  /*
+   * Query
+   */
+  char *query = "select count(*) from simplefilters";
+
+  /*
+   * execute query
+   */
+  retval = rsstdosingletextquery(handle->db, (unsigned char const**) &countstr, query, NULL);
+  if(retval == 0) {
+    /*
+     * Get results
+     */
+    *count = atoi(countstr);
+  }
+
+  /*
+   * Free stuff
+   */
+  free(countstr);
+
+  /*
+   * Done
+   */
+  return retval;
+}
+
+
+/*
+ * Get number of simple filters
+ * @Arguments
+ * simple number of simple filters in the database
+ * @return
+ * 0 when success, -1 when failed.
+ */
+static int rsstgetsqlcount(rsstor_handle *handle, int *count)
+{
+  int retval=0;
+  char *countstr=NULL;
+
+  /*
+   * Query
+   */
+  char *query = "select count(*) from filters";
+
+  /*
+   * execute query
+   */
+  retval = rsstdosingletextquery(handle->db, (unsigned char const**) &countstr, query, NULL);
+  if(retval == 0) {
+    /*
+     * Get results
+     */
+    *count = atoi(countstr);
+  }
+
+  /*
+   * Free stuff
+   */
+  free(countstr);
+
+  /*
+   * Done
+   */
+  return retval;
+}
+
+
+/*
+ * Get statistics from application
+ * No free for the returned struct yet
+ * @Arguments
+ * stats statistics structure
+ * @Returns
+ * 0 when okay, -1 on error
+ */
+int rsstgetstats(rsstor_handle *handle, stats_struct *stats)
+{
+  int retval=0;
+
+  /*
+   *  int metafile;   // Number of meta files in newtorrents table.
+   *  int downloaded; // Number of downloaded meta files in the downloaded table.
+   *  int sources;    // Number sources in the database.
+   *  char *version;  // Version string of software version.
+   *  int database;   // Database version number.
+   *  int simples;    // Number of simple filters.
+   *  int sqls;       // SQL filter count.
+   */
+
+  /*
+   * initialize the structure
+   */
+  memset(stats, 0, sizeof(stats));
+
+  /*
+   * Fill the variables
+   */
+  retval = rsstgetmetafile(handle, &(stats->metafile));
+  retval |= rsstgetdownloadedcount(handle,  &(stats->downloaded));
+  retval |= rsstgetsources(handle, &(stats->sources));
+  rsstgetversion(&(stats->version));
+  retval |= rsstgetdbversion(handle, &(stats->database));
+  retval |= rsstgetsimplecount(handle,&(stats->simples));
+  retval |= rsstgetsqlcount(handle, &(stats->sqls));
+  retval |= rsstgetdbsize(&(stats->dbsize));
+  retval |= rssttorusage(handle, &(stats->tormonenabled), &(stats->toruse));
+  retval |= rsstnzbusage(handle, &(stats->nzbmonenabled), &(stats->nzbuse));
+
+  /*
+   * Done return orred value.
+   */
+  return retval;
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/stats.h b/tags/swarmtv-0.9.2/libswarmtv/stats.h
new file mode 100644
index 0000000..096bfc2
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/stats.h
@@ -0,0 +1,29 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Get statistics from application
+ * @Arguments
+ * stats statistics structure
+ * @Returns
+ * 0 when okay, -1 on error
+ */
+int rsstgetstats(rsstor_handle *handle, stats_struct *stats);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/swarmtv.h b/tags/swarmtv-0.9.2/libswarmtv/swarmtv.h
new file mode 100644
index 0000000..ef04b15
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/swarmtv.h
@@ -0,0 +1,1058 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009 - 2010
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <sqlite3.h>
+#include <time.h>
+
+#ifndef RSSTOR
+#define RSSTOR
+
+/*
+ * Version of program
+ */
+#define RSST_VERSION "0.9"
+
+/*
+ * Enums used by RSS-torrent
+ */
+
+/*
+ * Loopmode
+ */
+typedef enum {loop=0, once} LOOPMODE;
+
+/*
+ * Structure holding useful torrent properties.
+ */
+typedef enum {undefined=0, torrent, nzb} METAFILETYPE;
+
+
+/*
+ * Return values for execute query inside RSS-torrent
+ * ROWS_ERROR error occurred
+ * ROWS_EMPTY no rows found or changed
+ * ROWS_FOUND select found rows
+ * ROWS_CHANGED insert or update changed rows
+ */
+#define ROWS_ERROR      -1
+#define ROWS_EMPTY      0
+#define ROWS_FOUND      1
+#define ROWS_CHANGED    2
+#define ROWS_CONSTRAINT 3
+
+/*
+ * The debug routine handle 3 debug levels
+ * LOG_DEBUG 	for debug information
+ * LOG_NORMAL for output messages
+ * LOG_ERROR  for error messages
+ */
+#define LOG_DEBUG   1
+#define LOG_NORMAL  2
+#define LOG_ERROR   3
+
+/*
+ * == Structures containing data from RSS-torrent database.
+ */
+
+/*
+ * Function pointer used in this callback implementation.
+ * @Arguments
+ * Data 		is data defined during the registration of the callback.
+ * Calldata The data passed from the calling function.
+ * @Return
+ */
+typedef int (*rsstcallbackfnct)(void *data, void *calldata);
+
+/*
+ * Structure to store callbacks in
+ */
+typedef struct{
+	int 	nr;										/* Number of functions to call. */
+	rsstcallbackfnct *callback; /* Array of function pointers. 	*/
+	void 						 **data;		/* Array of data-pointers. 			*/
+} struct_callback;
+
+/*
+ * Download RSS/torrent structure
+ */
+typedef struct {
+	int   id;			  /* ID of the RSS/torrent depends newtorrents id/downloaded id*/
+  char *name;     /* Name of the source */
+  char *url;      /* URL of the source  */
+  char *parser;   /* Parser used to parse the source */
+  char *metatype; /* The metafiles source is going to provide */
+  char *errstr;   /* Will be set when status == -1 */
+	int status;		  /* 0 when download was successful, else -1 */
+} struct_download;
+
+/*
+ * Disk full structure
+ */
+typedef struct {
+  METAFILETYPE  metatype; /* Metatype of the test */
+  int           limit;    /* Limit set */
+  int           use;      /* current usage */
+} struct_diskusage;
+
+/*
+ * Torrent structure
+ */
+typedef struct {
+  char    *name;      // Name of the download
+  char    *filtername;// Filter name delivering this metafile
+  char    *metatype;  // Torrent or NZB
+  char    *url;       // Origin URL
+  char    *metadata;  // Metafile content
+  size_t   metasize;  // the size of the metafile content
+} struct_downedmetafile;
+
+/*
+ *  Return value for Torrent handle
+ */
+typedef enum {
+  nohandler=0,
+  continue_processing,  // Continue handling the Torrent after receiving signal
+  stop_processing         // Do not save the torrent to disk
+} enum_downedmetafile;
+
+/*
+ * Enum for callbacks
+ * Make sure "lastelement" is always the last element in the list !
+ *
+ * == Using callback routines to register handle routines
+ * All callbacks to handle content starts with "handle"
+ * Handle routines at the front end can return "stop_process" to take over the handling of the signal.
+ * Handle handletorrentfile, handlenzbfile, can be used to pass Torrent data to the front end.
+ */
+typedef enum {
+  startcycle=0,       /* NULL pointer is sent with this callback */
+  rssdownload,        /* load pointer contains struct_download */
+  applysimplefilt,    /* load pointer contains simplefilter_struct */
+  applysqlfilt,       /* load pointer contains filter_struct */
+  downloadtorrent,    /* load pointer contains downloaded_struct */
+  endcycle,           /* NULL pointer is sent with this callback */
+  diskfull,           /* load pointer contains struct_diskusage */
+  handletorrentfile,  /* load pointer contains struct_downedmetafile */
+  handlenzbfile,      /* load pointer contains struct_downedmetafile */
+  lastelement         /* Here as end marker */
+} enum_callbacks;
+
+/*
+ * Callback pointers.
+ */
+typedef struct {
+	struct_callback *startcycle; 		  /* Emitted at the start of an update cycle */
+  struct_callback *rssdownload;     /* Emiited when a source is downloaded or failed */
+  struct_callback *applysimplefilt; /* Emitted at the start of the Applying of the filters */
+  struct_callback *applysqlfilt;    /* Emitted when a SQL filter is processed */
+  struct_callback *downloadtorrent; /* When a Torrent is downloaded */
+	struct_callback *endcycle; 			  /* emitted at the end of an update cycle */
+  struct_callback *diskfull;        /* emitted when the download partitions are full */
+  struct_callback *handletorrentfile;   /* emitted when a torrent is downloaded, returning enum_downedmetafile. */
+  struct_callback *handlenzbfile;       /* emitted when a nzb is downloaded, returning enum_downedmetafile */
+} struct_callbacks;
+
+/*
+ * RSS-torrent handle.
+ * This handle will change when other database types are implemented,
+ * so do not reference to components in this struct.
+ */
+typedef struct {
+	sqlite3 				 *db;				// RSS-torrent database handle.
+	int			 					lockfile; // Lock file handle.
+	struct_callbacks 	callback;	// Struct containing the callbacks
+  void             *data;     // Data pointer, to be used by the client to pass data though callbacks.
+} rsstor_handle;
+
+/*
+ * Struct holding the values to add to the database
+ */
+typedef struct {
+	int   id;				// Id of the filter
+	char *name;			// Simple filter name
+	char *title;		// Simple title regexp
+	char *exclude;	// Simple exclude regexp
+  char *category; // Simple category
+	char *source;		// Source the newtorrent originated from
+	double maxsize;	// Simple max size
+	double minsize;	// Simple minimal size
+	char *nodup;	// Simple no double filter type
+	int fromseason;		// From what season to download
+	int fromepisode;	// From episode
+} simplefilter_struct;
+
+/*
+ * Simple filters container
+ */
+typedef struct {
+	int nr;
+	simplefilter_struct *simplefilter;
+} simplefilter_container;
+
+/*
+ * Filter container
+ */
+typedef struct {
+	int 	id;				// Id of the filter
+	char *name;			// Name of the filter
+	char *filter;		// SQL of the filter
+	char *nodup;		// SQL of the avoiding duplicates filter
+} filter_struct;
+
+/*
+ * Simple filters container
+ */
+typedef struct {
+	int nr;
+	filter_struct *filter;
+} filter_container;
+
+/*
+ * Struct holding the values to enter into the newtorrents table.
+ */
+typedef struct {
+	int   id;
+	char *title;
+	char *link;
+  char  *metatype;
+	time_t pubdate;
+	char *category;
+	char *source;
+	int		season;
+	int		episode;
+	int		seeds;
+	int		peers;
+  size_t	size;
+	// 'new' is set by the routine.
+} newtorrents_struct;
+
+/*
+ * Simple filters container
+ */
+typedef struct {
+	int nr;
+	newtorrents_struct *newtorrent;
+} newtorrents_container;
+
+/*
+ * Enum holdig filter types
+ */
+typedef enum {sql=0, simple} FILTER_TYPE;
+
+/*
+ * Struct holding the values to enter into the downloaded table
+ */
+typedef struct {
+	int   id;
+	char *title;        // Title from the RSS feed
+	char *link;         // The link to the metafile
+	char *pubdate;      // The data the meta file was released
+	char *category;     // The category from the RSS feed
+  char *metatype;     // The type of content Torrent or NZB
+  char *baretitle;    // The bare title of the show/content
+	int  season;        // The season number
+	int  episode;       // The episode number
+  char *downdate;     // Date download occurred
+  char *filter;       // Filter name the match was found by
+  FILTER_TYPE type;   // Filter type the match produced
+} downloaded_struct;
+
+/*
+ * Downloaded container
+ */
+typedef struct {
+	int nr;
+	downloaded_struct *downloaded;
+} downloaded_container;
+
+/*
+ * Last downloaded
+ */
+typedef struct {
+  int   filterid;
+  char *filtername;
+  char *filtertype;
+  downloaded_struct *downloaded;
+} lastdowned_struct;
+
+/*
+ * Last downloaded container
+ */
+typedef struct {
+  int nr;
+  lastdowned_struct *lastdownloaded;
+} lastdowned_container;
+
+/*
+ * Statistics structure to be filled.
+ */
+typedef struct {
+  int     metafile;       // Number of meta files in newtorrents table.
+  int     downloaded;     // Number of downloaded meta files in the downloaded table.
+  int     sources;        // Number sources in the database.
+  char    *version;       // Version string of software version.
+  int     database;       // Database version number.
+  int     simples;        // Number of simple filters.
+  int     sqls;           // SQL filter count.
+  size_t  dbsize;         // Size of the current database file.
+  int     uselimit;       // The percentage of disk usage below a download is performed
+  int     toruse;         // The percentage use in the torrent download partition
+  int     tormonenabled;  // Torrent disk monitoring enabled 0 no, 1 yes
+  int     nzbuse;         // The percentage use in the NZB download partition
+  int     nzbmonenabled;  // NZB disk monitoring enabled 0 no, 1 yes
+} stats_struct;
+
+/*
+ * The config item names
+ */
+#define CONF_TORRENTDIR   "torrentdir"
+#define CONF_NZBDIR       "nzbdir"
+#define CONF_LOGFILE      "logfile"
+#define CONF_REFRESH      "refresh"
+#define CONF_RETAIN       "retain"
+#define CONF_DEFPARSER    "default_parser"
+#define CONF_LOCKFILE     "lockfile"
+#define CONF_SMTPTO       "smtp_to"
+#define CONF_SMTPFROM     "smtp_from"
+#define CONF_SMTPHOST     "smtp_host"
+#define CONF_MIN_SIZE     "min_size"
+#define CONF_SMTPENABLE   "smtp_enable"
+#define CONF_TORMONDIR    "tor_mon_dir"
+#define CONF_TORMONENABLE "tor_mon_enable"
+#define CONF_NZBMONDIR    "nzb_mon_dir"
+#define CONF_NZBMONENABLE "nzb_mon_enable"
+#define CONF_USAGELIMIT   "mon_limit"
+#define CONF_PROXYENABLE  "proxy_enable"
+#define CONF_PROXYURL     "proxy_url"
+#define CONF_PROXYUSEPASS "proxy_userpass"
+#define CONF_PROXYTYPE    "proxy_type"
+
+/*
+ * The proxy names
+ */
+#define RSST_PROXY_HTTP   "http"
+#define RSST_PROXY_SOCKS4 "socks4"
+#define RSST_PROXY_SOCKS5 "socks5"
+
+/*
+ * Config record container
+ */
+typedef struct {
+	int 	id;
+	char *name;
+	char *value;
+	char *description;
+} config_struct;
+
+/*
+ * Config record container
+ */
+typedef struct {
+	int            nr;
+	config_struct  *config;
+} config_container;
+
+/*
+ * source
+ */
+typedef struct {
+	int   id;
+	char *name;
+	char *url;
+	char *parser;
+  char *metatype;
+} source_struct;
+
+/*
+ * Sources container
+ */
+typedef struct {
+	int            nr;
+	source_struct *source;
+} source_container;
+
+/*
+ * == Functions to manipulate the config settings
+ */
+
+/*
+ * Initialize RSS-torrent handle
+ * @Return
+ * Pointer to handle on success, NULL on failure
+ */
+rsstor_handle *initrsstor();
+
+/*
+ * Run the Database init script.
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rsstrundbinitscript(rsstor_handle *handle);
+
+/*
+ * Free RSS-torrent handle
+ * @Arguments
+ * handle pointer to RSS-torrent structure
+ */
+void freersstor(rsstor_handle *handle);
+
+/*
+ * Get statistics from application
+ * No free for the returned struct yet
+ * @Arguments
+ * stats statistics structure
+ * @Returns
+ * 0 when okay, -1 on error
+ */
+int rsstgetstats(rsstor_handle *handle, stats_struct *stats);
+
+/*
+ * Get all config settings
+ * @Arguments
+ * handle RSS-torrent handle
+ * configitems The container to store the configitems in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallconfig(rsstor_handle *handle, config_container **configitems);
+
+/*
+ * Delete content from config_container struct
+ * @Arguments
+ * container Pointer to configcontainer to free content of
+ * @Return
+ * 0 on success, -1 on failure
+ */
+int rsstfreeconfigcontainer(config_container *container);
+
+/*
+ * Set config item
+ * @arguments
+ * handle RSS-torrent handle
+ * prop name of the property to change
+ * value new value to enter
+ * @returns
+ * When not found -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstsetconfigitem(rsstor_handle *handle, const char *prop, const char *value);
+
+/*
+ * Get value of a config object.
+ * Make sure the free the value returned in the value pointer.
+ * @arguments
+ * prop name of config property to retrieve
+ * value pointer to the pointer that is going to hold the retrieved value.
+ * @returns
+ * 0 when the value was found, otherwise -1.
+ */
+int rsstconfiggetproperty(rsstor_handle *handle, char *prop, char **value);
+
+/*
+ * Get value of a config object.
+ * @arguments
+ * prop name of the propertie to change
+ * number pointer to place to store value of prop
+ * @returns
+ * When not found -1 is returned.
+ * On succes 0 is returned.
+ */
+int rsstconfiggetint(rsstor_handle *handle, char *prop, int *number);
+
+/*
+ * == Functions to manipulate sources
+ */
+
+/*
+ * Get supported meta file types
+ * @return
+ * Returns a pointer to the names of the supported meta types.
+ */
+char **getsupportedmetatypes();
+
+/*
+ * Free source structure
+ * @Arguments
+ * source pointer to source struct to be freed
+ */
+void rsstfreesource(source_struct *source);
+
+/*
+ * Get RSS-source by id
+ * @arguments
+ * handle RSS-torrent handle
+ * id source id to get
+ * source structure containing the retrieved struct
+ * @Return
+ * 0 when okay, -1 on error
+ */
+int rsstgetsource(rsstor_handle *handle, int id, source_struct **source);
+
+/*
+ * Get all RSS-sources
+ * @arguments
+ * handle RSS-torrent handle
+ * sources The container to store the sources in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallsources(rsstor_handle *handle, source_container **sources);
+
+/*
+ * Delete content from source_container struct
+ * @Arguments
+ * container sources container content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreesourcecontainer(source_container *sources);
+
+/*
+ * Add source item
+ * @arguments
+ * handle RSS-torrent handle
+ * name filter name
+ * url source URL
+ * parsertype parser type
+ * metatype meta file type (torrent/nzb)
+ * @return
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstaddsource(rsstor_handle *handle, source_struct *source);
+
+/*
+ * Delete source item by name
+ * @arguments
+ * handle RSS-torrent handle
+ * id source id to delete
+ * @return
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelsourceid(rsstor_handle *handle, const int id);
+
+/*
+ * Delete source item by name
+ * @arguments
+ * handle RSS-torrent handle
+ * name source name to delete
+ * @return
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelsourcename(rsstor_handle *handle, const char *name);
+
+/*
+ * == Functions to manipulate downloaded database
+ */
+
+/*
+ * Get downloaded torrents
+ * @arguments
+ * handle RSS-torrent handle
+ * downloaded The container to store the downloaded in
+ * limit amount of records to retrieve
+ * offset number of records to skip at beginning
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetdownloaded(rsstor_handle *handle, downloaded_container **downloaded, int limit, int offset);
+
+/*
+ * Delete content from source_container struct
+ * @Arguments
+ * container downloaded container content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreedownloadedcontainer(downloaded_container *container);
+
+/*
+ * Delete from downloaded table
+ * @arguments
+ * handle RSS-torrent handle
+ * id id of the downloaded torrent to delete from downed table
+ * @returns
+ * 0 	On success
+ * -1 on failure
+ */
+int rsstdeldownloaded(rsstor_handle *handle, int id);
+
+/*
+ * This routine retrieves the records from the downloaded table.
+ * A selection is based on name.
+ * @Arguments
+ * db
+ * optarg
+ * @return
+ * 0 on success
+ * -1 on error
+ */
+int rsstfinddowned(rsstor_handle *handle, char *optarg);
+
+/*
+ * Function to download torrent
+ */
+
+/*
+ * Test Torrent or NZB directories, do they exist and are they writable ?
+ * @return
+ * 0 when writabe, -1 if not.
+ */
+int rssttestmetafiledir(rsstor_handle *handle);
+
+/*
+ * Get the newest season and episode
+ * @arguments
+ * filter Simple filter struct
+ * Season newest season
+ * Episode newest episode
+ * @return
+ * 0 on success otherwise 1
+ * 1 When season and episode are found
+ * -1 on error
+ * @comments
+ * This function is this file because all supporting functions are in this file.
+ */
+int rsstgetnewestepisode(simplefilter_struct *filter, int *season, int *episode);
+
+/*
+ * Do filter test
+ * show first 10 matches
+ * Takes opts_struct * as argument.
+ * return 0 on success, return -1 on failure.
+ */
+int rsstfindtorrentids(simplefilter_struct *filter);
+
+/*
+ * This routine function downloads the torrent indicated by ID.
+ * The routine looks through the newtorrents table to pick the torrent by id.
+ * @arguments
+ * id	The id that points to the torrent
+ * @returns
+ * 0 on success
+ * -1 on failure
+ */
+int rsstdownloadbyid(rsstor_handle *handle, int torid);
+
+/*
+ * This routine function downloads the torrent indicated by ID.
+ * The routine looks through the newtorrents table to pick the torrent by id.
+ * @arguments
+ * torid The id that points to the torrent
+ * @returns
+ * 0 on success
+ * -1 on failure
+ */
+int rsstdownloadbyidstr(rsstor_handle *handle, char *torid);
+
+/*
+ * == Functions to manipulate newtorrents
+ */
+
+/*
+ * Find newtorrents entries
+ * @Arguments
+ * filter simplefilterstruct to filter out the newtorrent entries we want
+ * newtorrents container handling newtorrents entries
+ * limit is the amount of rows we want to retrieve
+ * offset is the amount of rows we want to skip at the start
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfindnewtorrents(simplefilter_struct *filter, newtorrents_container **newtorrents, int limit, int offset);
+
+/*
+ * Find newtorrents entries
+ * @Arguments
+ * handle SwarmTv Handle
+ * title title to match to
+ * newtorrents container handling newtorrents entries
+ * limit is the amount of rows we want to retrieve
+ * offset is the amount of rows we want to skip at the start
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfindnewtorrentsbytitle(rsstor_handle *handle, char *title, newtorrents_container **newtorrents, int limit, int offset);
+
+/*
+ * Free strings in newtorrents_struct
+ * Be sure to free the struct yourself.
+ * @Arguments
+ * newtor structure pointer
+ * @Return
+ * void, exits on failure
+ */
+void rsstfreenewtor(newtorrents_struct *newtor);
+
+/*
+ * Delete content from newtorrents_container
+ * @Arguments
+ * container newtorrents container the content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreenewtorrentscontainer(newtorrents_container *newtorrents);
+
+/*
+ * Get newtorrent information providing its ID
+ * @Arguments
+ * handle Swarmtv Handle
+ * id id number of torrent to retrieve
+ * newtorrent structure holding information
+ * @Return
+ * Returns 0 when found, -1 on not found or error
+ */
+int rsstnewtorrentsbyid(rsstor_handle *handle, int newtorid, newtorrents_struct *newtorrent);
+
+/*
+ * Functions to manipulate the SQL filters
+ */
+
+/*
+ * Delete content from config_container struct
+ * @Arguments
+ * container Pointer to configcontainer to free content of
+ * @Return
+ * 0 on success, -1 on failure
+ */
+int rsstfreefiltercontainer(filter_container *container);
+
+/*
+ * Get all SQL filter settings
+ * @Arguments
+ * handle RSS-torrent handle
+ * container The container to store the SQL filters in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallfilter(rsstor_handle *handle, filter_container **filteritem);
+
+/*
+ * Get all SQL filter settings
+ * @Arguments
+ * handle RSS-torrent handle
+ * container The container to store the container in
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetfilterbyname(rsstor_handle *handle, char *name, filter_container **container);
+
+/*
+ * Get information of the last downloads and the filters that produced them
+ * @Arguments
+ * handle RSS-torrent handle
+ * container the pointer pointer to the container
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rsstgetlastdownloaded(rsstor_handle *handle, lastdowned_container *container);
+
+/*
+ * Free the downloaded container and its contents
+ * When the container it self is allocated, it should be freed separately
+ * @Arguments
+ * container pointer to the downed container to be freed
+ */
+void rsstfreelastdownedcontainer(lastdowned_container *container);
+
+/*
+ * Add source item
+ * @Arguments
+ * handle RSS-torrent handle
+ * name name of the filter
+ * filter SQL query to sort out the candidates
+ * nodupfilter SQL query to root out the candidates that are already downloaded.
+ * @return
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstaddfilter(rsstor_handle *handle, const char *name, const char *filter, const char *nodupfilter);
+
+/*
+ * Add simple filter
+ * @variables
+ * opts structure holding the options
+ * @returns
+ * 0 on success, else -1
+ */
+int rsstaddsimplefilter(rsstor_handle *handle, simplefilter_struct *filter);
+
+/*
+ * Edit simple filter function, pointed by Id
+ * @Arguments
+ * handle SwarmTv handle
+ * simple structure holding simple filter informaion
+ * @returns
+ * returns 0 when edited successfully ,returns -1 when editing failed
+ */
+int rssteditsimplefilter(rsstor_handle *handle, simplefilter_struct *simple);
+
+/*
+ * Get simplefilter torrents
+ * @arguments
+ * simplefilter The container to store the simplefilter in
+ * limit max number of simple filters retrieved
+ * offset the number of simple filters to skip
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetallsimplefilter(rsstor_handle *handle, simplefilter_container **simplefilter, int limit, int offset);
+
+/*
+ * Get simplefilter torrents
+ * @arguments
+ * simplefilter The container to store the simplefilter in
+ * name name of the simple filter
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetsimplefiltername(rsstor_handle *handle, simplefilter_container **simplefilter, char *name);
+
+/*
+ * Get simplefilter torrents
+ * @arguments
+ * simplefilter The container to store the simplefilter in
+ * id id of the simple filter
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstgetsimplefilterid(rsstor_handle *handle, simplefilter_struct **simplefilter, int id);
+
+/*
+ * Free simplefilter structure
+ * @Arguments
+ * simplefilter pointer to simplefilter struct to be freed
+ */
+void rsstfreesimplefilter(simplefilter_struct *simplefilter);
+
+/*
+ * Delete content from source_container struct
+ * @Arguments
+ * container simplefilter container content needs freeing
+ * @Return
+ * Returns 0 on success -1 on failure
+ */
+int rsstfreesimplefiltercontainer(simplefilter_container *container);
+
+/*
+ * Do filter test
+ * show first 10 matches
+ * @arguments
+ * filter filter SQL
+ * nodup nonup SQL
+ * @return
+ * -1 on error
+ * 0 on success
+ */
+int rsstdofiltertest(char *filter, char *nodup);
+
+/*
+ * Do filter test
+ * show first 10 matches
+ * Takes opts_struct * as argument.
+ * return 0 on success, return -1 on failure.
+ */
+int rsstdosimpletest(simplefilter_struct *filter);
+
+/*
+ * Del filter filter
+ * When already existing -1 is returned.
+ * @variables
+ * name filter name to delete
+ * @returns
+ * On success 0 is returned.
+ */
+int rsstdelsimpleid(rsstor_handle *handle, const int id);
+
+/*
+ * Del filter filter
+ * When already existing -1 is returned.
+ * @variables
+ * name filter name to delete
+ * @returns
+ * On success 0 is returned.
+ */
+int rsstdelsimplename(rsstor_handle *handle, const char *name);
+
+/*
+ * delete filter item
+ * When the name is not found -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstdelallsimple(rsstor_handle *handle);
+
+/*
+ * Delete SQL filter
+ * When already existing -1 is returned.
+ * @arguments
+ * name the name of the SQL filter to delete
+ * @return
+ * On success 0 is returned.
+ */
+int rsstdelfilter(rsstor_handle *handle, const char *name);
+
+/*
+ * Delete all filters.
+ * Deletes all filters from filtertable.
+ * @returns
+ * On success 0 is returned.
+ */
+int rsstdelallfilters(rsstor_handle *handle);
+
+/*
+ * Add source item
+ * @Arguments
+ * handle RSS-torrent handle
+ * name name of the filter
+ * filter SQL query to sort out the candidates
+ * nodupfilter SQL query to root out the candidates that are already downloaded.
+ * @return
+ * When already existing -1 is returned.
+ * On success 0 is returned.
+ */
+int rsstaddfilter(rsstor_handle *handle, const char *name, const char *filter, const char *nodupfilter);
+
+/*
+ * == Functions to run RSS-torrent
+ */
+
+/*
+ * Main loop, dispatches tasks
+ * @arguments
+ * handle RSS-torrent handle
+ * onetime Set loop for infinite loop, once for running the step just once
+ * @return
+ * 0 for now.
+ */
+int rsstrunloop(rsstor_handle *handle, LOOPMODE onetime);
+
+/*
+ * Do a cycle of workload
+ * As runloop is going to be depricated.
+ * A runloop should be implemented by the calling program.
+ * @Arguments
+ * handle
+ * @return
+ * 0 for now
+ */
+int runcycle(rsstor_handle *handle);
+
+/*
+ * == Log file writing routines
+ */
+
+/*
+ * Loglevels
+ */
+#define LOG_DEBUG   1
+#define LOG_NORMAL  2
+#define LOG_ERROR   3
+
+/*
+ * Log an entry
+ * LOG_DEBUG, LOG_NORMAL, LOG_ERROR
+ * @arguments
+ * level the log level (see log level defines)
+ * str the string to log
+ * ... the arguments to fill out in the log line
+ * @return
+ * returns 1 for now in all cases
+ */
+int rsstwritelog(int level, char *str,...);
+
+/*
+ * == Mail routines
+ */
+
+/*
+ * Uses the mail routine to send a test mail.
+ * Arguments :
+ * testxt, test message to send.
+ */
+void rssttestmail(rsstor_handle *handle, char *testtxt);
+
+/*
+ * == Callback interaction functions
+ */
+
+/*
+ * Add pointer.
+ * @arguments
+ * handle swarmtv handle
+ * enumcall the name of the callback funct
+ * callback pointer to the callback function
+ * data   pointer that will be returned as the data pointer.
+ * @return
+ * 0 on successful addition, -1 on error
+ */
+int rsstaddcallback(rsstor_handle *handle, enum_callbacks enumcall, rsstcallbackfnct callback, void *data);
+
+/*
+ * execute routines that are handling on RSS download events
+ * @Arguments
+ * handle     Handle to RSS-torrent pointer
+ * callenum   Name name of the callback to call
+ * load       payload to provide together with the callback
+ * @return
+ * return 0 when all called functions returned 0, otherwise != 0
+ */
+int rsstexecallbacks(rsstor_handle *handle, enum_callbacks callenum, void *load);
+
+/*
+ * == Functions to check Torrent download directories
+ */
+
+/*
+ * Torrent download partition usage
+ * @arguments
+ * percentage percentage in use
+ * limit percentage limit
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rssttorusage(rsstor_handle *handle, int *enabled, int *percentage);
+
+/*
+ * NZB download partition usage
+ * @arguments
+ * enabled set to 1 when enabled else 0
+ * percentage percentage in use when enabled is 0, this value is 0
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rsstnzbusage(rsstor_handle *handle, int *enabled, int *percentage);
+
+/*
+ * Get the set partition usage limit
+ * @Arguments
+ * maxuse get the max level of partition usage
+ * @return
+ * 0 when success otherwise -1
+ */
+int rsstgetmaxusage(rsstor_handle *handle, int *maxuse);
+
+#endif
+#ifdef __cplusplus
+}
+#endif
diff --git a/tags/swarmtv-0.9.2/libswarmtv/testfilter.c b/tags/swarmtv-0.9.2/libswarmtv/testfilter.c
new file mode 100644
index 0000000..db05d9d
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/testfilter.c
@@ -0,0 +1,455 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2010
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sqlite3.h>
+#include <string.h>
+
+#include "types.h"
+#include "sandboxdb.h"
+#include "logfile.h"
+#include "database.h"
+#include "databaseimpl.h"
+#include "torrentdb.h"
+#include "simplefilter.h"
+#include "torrentdownload.h"
+#include "regexp.h"
+
+/*
+ * The sandbox is created in a separate file, path is set here.
+ */
+#define  RSST_DBSANDBOX "~/.swarmtv/sandbox.db"
+
+/*
+ * The max number of results in a search result.
+ */
+#define  PAGE_LIMIT "100"
+
+/*
+ * Structure to hold season and episode
+ */
+typedef struct {
+	int season;
+	int episode;
+} season_episode;
+
+
+/*
+ * Copy content to downloaded
+ * Prevent doubles from occurring.
+ * match all records that match the filter, and copy them to the no double
+ */
+static int createdownloaded(sandboxdb *sandbox, char *filter, char *nodouble)
+{
+  int rc=0;
+  char *delfilterquery="DELETE FROM downloaded";
+	rsstor_handle handle;
+
+	/*
+	 * Initialize handle
+	 */
+	memset(&handle, 0, sizeof(rsstor_handle));
+	handle.db=sandbox->db;
+
+  /*
+   * Clean downloaded.
+   */
+  rc = rsstexecutequery(sandbox->db, delfilterquery, NULL);
+  if(rc == ROWS_ERROR){
+    rsstwritelog(LOG_ERROR, "Deleting downloaded failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * use function to add records to the downloaded table.
+   */
+  rsstapplyfilter(&handle, "Sandbox", simple, nodouble, NULL, 1, filter,  NULL);
+
+  return 0;
+}
+
+/*
+ * Set all 'newtorrents' flags to new, to imitate new arrivals
+ */
+static int setnewtorrentflags(sandboxdb *sandbox)
+{
+  int   rc=0;
+  int   retval=0;
+  char *query = "UPDATE newtorrents SET new='Y'";
+
+  /*
+   * do query
+   */
+  rc = rsstexecutequery(sandbox->db, query, NULL);
+  if(rc != ROWS_CHANGED){
+    rsstwritelog(LOG_ERROR, "Setting of new flag failed %s:%d", __FILE__, __LINE__);
+    retval=-1;
+  }
+
+  return retval;
+}
+
+/*
+ * Prepare the filter test database
+ */
+sandboxdb *rsstinitfiltertest()
+{
+  int       rc;
+  sandboxdb *sandbox;
+
+  /*
+   * create sandbox
+   */
+  sandbox = rsstcreatesandbox(RSST_DBFILE, RSST_DBSANDBOX);
+  if(sandbox == NULL) {
+    rsstwritelog(LOG_ERROR, "Sandbox creation failed %s:%d", __FILE__, __LINE__);
+    fprintf(stderr, "Sandbox creation failed %s:%d\n", __FILE__, __LINE__);
+    return NULL;
+  }
+
+  /*
+   * Prepare new torrents
+   */
+  rc = setnewtorrentflags(sandbox);
+  if(rc != 0) {
+    rsstclosesandbox(sandbox);
+    return NULL;
+  }
+
+  return sandbox;
+}
+
+
+/*
+ * Do filter test
+ * show first 10 matches
+ */
+int rsstdofiltertest(char *filter, char *nodouble)
+{
+  int rc=0;
+  sandboxdb *sandbox;
+  char *query="select newtorrents.id, downloaded.title, downloaded.season, downloaded.episode from newtorrents, downloaded "
+							"where newtorrents.link = downloaded.link order by newtorrents.id"; // get values from downloaded table
+
+  /*
+   * Initialize sandbox database
+   */
+  sandbox = rsstinitfiltertest();
+  if(sandbox == NULL){
+    rsstwritelog(LOG_ERROR, "Sandbox creation failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Execute test filter
+   */
+  rc = createdownloaded(sandbox, filter, nodouble);
+  if(rc != 0){
+    printf("Execution of test filter failed.\n");
+    rsstwritelog(LOG_ERROR, "Execution of test filter failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Print content of downloaded
+   */
+  printf(" Id                        | Title                     | Season                    | Episode\n");
+  rc = rsstprintquery(sandbox->db, query, NULL);
+  if(rc != 0){
+    printf("Listing of download queue failed.\n");
+    rsstwritelog(LOG_ERROR, "Execution of test filter failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * cleanup sandbox
+   */
+  rc = rsstclosesandbox(sandbox);
+  if(rc != 0){
+    printf("Closing sandbox failed.\n");
+    rsstwritelog(LOG_ERROR, "Closing sandbox failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  return 0;
+}
+
+
+/*
+ * Clean-up the sandbox for filter processing
+ * @Arguments
+ * sandbox the sandbox to clean-up
+ * @return
+ * 0 on success, otherwise -1
+ */
+int rsstcleanoutdb(sandboxdb *sandbox)
+{
+  int 	rc=0;
+  char 	*delquery="DELETE FROM downloaded";
+  char 	*delsimplequery="DELETE FROM simplefilters";
+
+  /*
+   * Clean downloaded.
+   */
+  rc = rsstexecutequery(sandbox->db, delquery, NULL);
+  if(rc == ROWS_ERROR){
+    rsstwritelog(LOG_ERROR, "Deleting downloaded failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+	/*
+	 * Empty simple filters in sandbox
+	 */
+  rc = rsstexecutequery(sandbox->db, delsimplequery, NULL);
+  if(rc == ROWS_ERROR){
+    rsstwritelog(LOG_ERROR, "Deleting simple filters failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+	return 0;
+}
+
+
+/*
+ * Copy content to downloaded
+ * Prevent doubles from occurring.
+ * match all records that match the filter, and copy them to the no double
+ */
+static int createsimpledownloaded(sandboxdb *sandbox, simplefilter_struct *filter)
+{
+  int 					 rc=0;
+	char 					*nodupsql=NULL;
+	rsstor_handle  handle;
+
+	/*
+	 * Get sandbox db
+	 */
+	handle.db=sandbox->db;
+
+	/*
+	 * Remove unwanted data from sandbox.
+	 */
+	rc = rsstcleanoutdb(sandbox);
+	if(rc != 0){
+    rsstwritelog(LOG_ERROR, "Cleaning out sandbox failed %s:%d", __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Add filter to sandbox
+	 */
+	rsstaddsimplefilter(&handle, filter);
+
+	/*
+	 * Execute filter
+	 * with simulate 1, to run the simple filters only in the database.
+	 */
+	rsstdownloadsimple(&handle, (SIM) sim);
+
+	/*
+	 * Clean up
+	 */
+	free(nodupsql);
+
+  return 0;
+}
+
+
+/*
+ * Get the newest season and episode
+ * @arguments
+ * filter Simple filter structure
+ * Season newest season
+ * Episode newest episode
+ * @return
+ * 0 on success otherwise 1
+ * 1 When season and episode are found
+ * -1 on error
+ */
+int rsstgetnewestepisode(simplefilter_struct *filter, int *season, int *episode)
+{
+  int rc=0;
+  sandboxdb *sandbox=NULL;
+	sqlite3_stmt *ppstmt=NULL;
+	int retval=0;
+	char *newestquery="SELECT season, episode FROM downloaded ORDER BY season DESC, episode DESC  LIMIT 1"; // Get the newest episode
+
+	/*
+	 * Initialize season and episode
+	 */
+	*season = 0;
+	*episode = 0;
+
+  /*
+   * Initialize sandbox database
+   */
+  sandbox = rsstinitfiltertest();
+  if(sandbox == NULL){
+    rsstwritelog(LOG_ERROR, "Sandbox creation failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Execute test filter
+   */
+	rc = createsimpledownloaded(sandbox, filter);
+  if(rc != 0){
+    printf("Execution of test filter failed.\n");
+    rsstwritelog(LOG_ERROR, "Execution of test filter failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Execute query to get newest season and episode numbers
+   */
+	rc = rsstexecqueryresult(sandbox->db, &ppstmt, newestquery, NULL);
+
+	/*
+	 * Extract numbers
+	 */
+	rc = sqlite3_step(ppstmt);
+
+	/*
+	 * We found an entry
+	 */
+	if(rc == SQLITE_ROW){
+		*season = sqlite3_column_int(ppstmt, 0);
+		*episode = sqlite3_column_int(ppstmt, 1);
+		retval=1;
+	}
+
+	/*
+	 * Free results
+	 */
+	sqlite3_finalize(ppstmt);
+
+  /*
+   * cleanup sandbox
+   */
+  rc = rsstclosesandbox(sandbox);
+  if(rc != 0){
+    printf("Closing sandbox failed.\n");
+    rsstwritelog(LOG_ERROR, "Closing sandbox failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+	/*
+	 * Done.
+	 */
+  return retval;
+}
+
+
+/*
+ * Do filter test
+ * show first 10 matches
+ * Takes opts_struct * as argument.
+ * return 0 on success, return -1 on failure.
+ */
+int rsstdosimpletest(simplefilter_struct *filter)
+{
+  int rc=0;
+  sandboxdb *sandbox;
+  char *query="select title, season, episode from downloaded;"; // get values from downloaded table
+	char *names[]={"Title", "Season", "Episode", "Torrent"};
+
+  /*
+   * Initializing sandbox database
+   */
+  sandbox = rsstinitfiltertest();
+  if(sandbox == NULL){
+    rsstwritelog(LOG_ERROR, "Sandbox creation failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Execute test filter
+   */
+	rc = createsimpledownloaded(sandbox, filter);
+  if(rc != 0){
+    printf("Execution of test filter failed.\n");
+    rsstwritelog(LOG_ERROR, "Execution of test filter failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Print content of downloaded
+   */
+  rc = rsstprintquerylist(sandbox->db, query, names, NULL);
+  if(rc != 0){
+    printf("Listing of download queue failed.\n");
+    rsstwritelog(LOG_ERROR, "Execution of test filter failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * cleanup sandbox
+   */
+  rc = rsstclosesandbox(sandbox);
+  if(rc != 0){
+    printf("Closing sandbox failed.\n");
+    rsstwritelog(LOG_ERROR, "Closing sandbox failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  return 0;
+}
+
+
+/*
+ * This routine retrieves the records from the downloaded table.
+ * A selection is based on name.
+ * This routine should not be here name wise, though all dependencies reside here.
+ * I'll place it here for now.
+ * @Arguments
+ * db
+ * optarg
+ * @return
+ * 0 on success
+ * -1 on error
+ */
+int rsstfinddowned(rsstor_handle *handle, char *optarg)
+{
+	int rc=0;
+	sqlite3 *db=NULL;
+
+	static char *query  = "SELECT id, season, episode, title FROM downloaded WHERE IREGEXP(?1, title);";
+	static char *names[] = {"Id", "Season", "Episode", "Title", "Downloaded torrent"};
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+	/*
+	 * print results
+	 */
+  rc = rsstprintquerylist(db, query, names, "s", optarg);
+  if(rc != 0){
+    printf("Listing of download queue failed.\n");
+    rsstwritelog(LOG_ERROR, "Execution of test filter failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+	return 0;
+}
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/testfilter.h b/tags/swarmtv-0.9.2/libswarmtv/testfilter.h
new file mode 100644
index 0000000..57edd1f
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/testfilter.h
@@ -0,0 +1,93 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2010
+ */
+
+/*
+ * Do filter test
+ * show first 10 matches
+ * @arguments
+ * filter filter SQL
+ * nodouble nodouble SQL
+ * @return
+ * -1 on error
+ * 0 on success
+ */
+int rsstdofiltertest(char *filter, char *nodouble);
+
+/*
+ * Do filter test
+ * show first 10 matches
+ * Takes opts_struct * as argument.
+ * return 0 on succes, return -1 on failure.
+ */
+int rsstfindtorrentids(simplefilter_struct *filter);
+
+/*
+ * This routine retrieves the records from the downloaded table.
+ * A selection is based on name.
+ * This routine should not be here namewise, but sinds the other function ended up here
+ * I'll place it here for now.
+ * @Arguments
+ * db
+ * optarg
+ * @return
+ * 0 on success
+ * -1 on error
+ */
+int rsstfinddowned(rsstor_handle *handle, char *optarg);
+
+/*
+ * Cleanout the sandbox for filter processing
+ * @Arguments
+ * sandbox the sandbox to cleanout
+ * @retun
+ * 0 on success, otherwise -1
+ */
+int rsstcleanoutdb(sandboxdb *sandbox);
+
+/*
+ * Prepare the filter test database
+ * @return
+ * pointer to new database struct on success, on failure NULL
+ */
+sandboxdb *rsstinitfiltertest();
+
+/*
+ * Do filter test
+ * show first 10 matches
+ * Takes opts_struct * as argument.
+ * return 0 on succes, return -1 on failure.
+ */
+int rsstdosimpletest(simplefilter_struct *filter);
+
+/*
+ * Get the newest season and episode
+ * @arguments
+ * filter Simple filter struct
+ * Season newest season
+ * Episode newest episode
+ * @return
+ * 0 on succes otherwise 1
+ * 1 When season and episode are found
+ * -1 on error
+ * @comments
+ * This function is this file because all supporting functions are in this file.
+ */
+int rsstgetnewestepisode(simplefilter_struct *filter, int *season, int *episode);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/torrentdb.c b/tags/swarmtv-0.9.2/libswarmtv/torrentdb.c
new file mode 100644
index 0000000..e0bd897
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/torrentdb.c
@@ -0,0 +1,329 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pcre.h>
+#include <sqlite3.h>
+#include <time.h>
+
+#include "types.h"
+#include "config.h"
+#include "database.h"
+#include "logfile.h"
+#include "torrentdownload.h"
+#include "lastdownloaded.h"
+
+#define 	BUFSIZE 	20
+
+/*
+ * Free strings in newtorrents_struct
+ * Be sure to free the struct yourself.
+ * @Arguments
+ * newtor structure pointer
+ * @Return
+ * void, exits on failure
+ */
+void rsstfreenewtor(newtorrents_struct *newtor)
+{
+	free(newtor->title);
+	free(newtor->link);
+	free(newtor->category);
+	free(newtor->source);
+  free(newtor->metatype);
+}
+
+
+/*
+ * Single out unlikely season/episode numbers
+ * @Arguments
+ * newtor New torrent struct to delete unusual season/episode combinations from.
+ */
+static void rsstfilterseasonepisode(newtorrents_struct *newtor)
+{
+	int magicnumbers[] = {264, 720, 1080, 0};
+	int count=0;
+	int season = newtor->season;
+	int	episode	= newtor->episode;
+
+	/*
+	 * Make sure no 264 enters in season or episode
+	 */
+	while(magicnumbers[count] != 0){
+		/*
+		 * if season or episode is one of the forbidden numbers, reset both
+		 */
+		if(season == magicnumbers[count] || episode == magicnumbers[count]){
+			newtor->season = 0;
+			newtor->episode = 0;
+		}
+
+		/*
+		 * next
+		 */
+		count++;
+	}
+}
+
+
+/*
+ * Add a torrent to the newtorrent table.
+ * @Arguments
+ * newtor structure holding the values for the record to be added
+ * @Return
+ * 0 on success, exits on -1 on failure
+ */
+int rsstaddnewtorrent(rsstor_handle *handle, newtorrents_struct *newtor)
+{
+  int           rc=0;
+	sqlite3      *db=NULL;
+  const char   *error=NULL;
+  int           errno=0;
+
+	/*
+	 * Get db pointer;
+	 */
+	db = handle->db;
+
+  char *query = "INSERT INTO newtorrents (title, link, pubdate, category, source, season, episode, seeds, peers, size, metatype, new) "
+                "VALUES (?1, ?2, date(?3, 'unixepoch'), ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, 'Y')";
+
+	/*
+	 * Remove numbers that refer to video encoding but could end up as season/episode numbers.
+	 */
+	rsstfilterseasonepisode(newtor);
+
+  // DEBUG
+  rsstwritelog(LOG_DEBUG, "############\n"
+      "title:    %s\n"
+      "link:     %s\n"
+      "pubdate:  %s\n"
+      "category: %s\n"
+			"source:   %s\n"
+      "season:   %d\n"
+      "episode:  %d\n"
+      "seeds:    %d\n"
+      "peers:    %d\n"
+      "size:     %ld\n"
+      "metatype: %s\n",
+      	newtor->title, newtor->link, ctime(&(newtor->pubdate)), newtor->category, newtor->source,
+				newtor->season, newtor->episode, newtor->seeds, newtor->peers, newtor->size, newtor->metatype);
+
+  /*
+   * execute query
+   */
+  rc = rsstexecutequery(db, query, "ssdssddddfs",
+			newtor->title, newtor->link, newtor->pubdate, newtor->category, newtor->source, newtor->season,
+			newtor->episode, newtor->seeds, newtor->peers, (double)(newtor->size), newtor->metatype);
+
+  switch(rc) {
+    case ROWS_EMPTY:
+    case ROWS_CHANGED:
+      // print nothing all is okay
+      break;
+    case ROWS_CONSTRAINT:
+      rsstwritelog(LOG_DEBUG, "Torrent already in DB");
+      break;
+    default:
+      errno = sqlite3_errcode(db);
+      error = sqlite3_errmsg(db);
+/*
+ * Workaround for older sqlite3 libraries.
+ */
+#if SQLITE_VERSION_NUMBER >= 3003009
+      rsstwritelog(LOG_ERROR, "SQL statement failed '%d'! %s %s:%d", errno, error, __FILE__, __LINE__);
+      exit(1);
+#else
+      if(errno == SQLITE_CONSTRAINT) {
+        rsstwritelog(LOG_DEBUG, "Torrent already in DB");
+      } else {
+        rsstwritelog(LOG_ERROR, "SQL statement failed '%d'! %s %s:%d", errno, error, __FILE__, __LINE__);
+        exit(1);
+      }
+#endif
+  }
+
+  /*
+   * no errors
+   */
+  return 0;
+}
+
+
+/*
+ * Add a torrent to the downloaded table.
+ * Arguments
+ * downed			pointer to struct holding values to add to the db.
+ * simulate		0 to log addition, 1 adds anyway, but does not log at all.
+ */
+void rsstadddownloaded(rsstor_handle *handle, downloaded_struct *downed, SIM  simulate)
+{
+  int        rc=0;
+  time_t     now=0;
+  sqlite3 	*db=NULL;
+
+  db = handle->db;
+
+  char *query = "INSERT INTO downloaded (title, link, pubdate, category, season, episode, metatype, date) "
+                "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7,  datetime(?8, 'unixepoch', 'localtime'))";
+
+  /*
+   * The time is now, now is the time
+   */
+  now = time(NULL);
+
+  /*
+   * Do not log downloading when we are testing filters.
+   */
+  if(simulate == (SIM) real){
+    rsstwritelog(LOG_NORMAL, "##### Download #######\n"
+        "title:    %s\n"
+        "link:     %s\n"
+        "pubdate:  %s\n"
+        "category: %s\n"
+        "metatype: %s\n"
+        "season:   %d\n"
+        "episode:  %d",
+        downed->title, downed->link, downed->pubdate, downed->category, downed->metatype, downed->season, downed->episode);
+  }
+
+  /*
+   * execute query, when failed return -1
+   */
+  rc = rsstexecutequery(db, query, "ssssddsd", downed->title, downed->link, downed->pubdate, downed->category,
+			downed->season, downed->episode, downed->metatype, now);
+  switch(rc) {
+    case ROWS_EMPTY:
+    case ROWS_CHANGED:
+      // print nothing all is okay
+      break;
+    case ROWS_CONSTRAINT:
+      rsstwritelog(LOG_ERROR, "Torrent '%s' already downloaded, please check no double filters for '%s'. %s:%d",
+					downed->link, downed->title, __FILE__, __LINE__);
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "SQL statement failed %d! %s:%d", rc, __FILE__, __LINE__);
+      exit(1);
+  }
+}
+
+/*
+ * When Torrents are processed, they are no longer new
+ * this method removes the new flag
+ */
+void rsstnonewtorrents(rsstor_handle *handle)
+{
+  int        rc=0;
+	sqlite3 	*db=NULL;
+
+	db=handle->db;
+
+  const char *query = "UPDATE newtorrents SET new='N' WHERE new='Y'";
+
+  rsstwritelog(LOG_DEBUG,"New torrents are marked old now !");
+
+  rc = rsstexecutequery(db, query, NULL);
+  if(rc == SQLITE_ERROR){
+      rsstwritelog(LOG_ERROR, "SQL statement failed %d! %s:%d", rc, __FILE__, __LINE__);
+      exit(1);
+  }
+
+  /*
+   * no errors
+   */
+  return;
+}
+
+/*
+ * Delete all newtorrents entries older the x days
+ * This function returns 0 on success, -1 SQL on failure.
+ * Arguments
+ * days 	The number of days records get retained in the newtorrents table.
+ * returns
+ * -1 on error, 0 on success
+ */
+int rsstdeloldnewtorents(rsstor_handle *handle, unsigned int days)
+{
+	char daystr[BUFSIZE+1];
+	int  rc=0;
+	sqlite3 *db=NULL;
+
+	db = handle->db;
+
+	/*
+	 * Query to delete old entries.
+	 */
+	char *query="DELETE from newtorrents where pubdate <  date('now', ?1)";
+
+	/*
+	 * Build string
+	 */
+	memset(daystr, 0, BUFSIZE+1);
+	snprintf(daystr, BUFSIZE, "-%d days", days);
+
+	/*
+	 * Execute query
+	 */
+	rc = rsstexecutequery(db, query, "s", daystr);
+	if(rc == -1) {
+		return -1;
+	}
+
+	/*
+	 * Log if we deleted old newtorrents records.
+	 */
+	if(rc == 1) {
+		rsstwritelog(LOG_DEBUG, "Deleted old torrents.");
+	} else {
+		rsstwritelog(LOG_DEBUG, "No newtorrent records have aged enough.");
+	}
+
+	return 0;
+}
+
+
+/*
+ * Delete from downloaded table
+ * @arguments
+ * id 	id of the downloaded torrent to delete from downed table
+ * @returns
+ * 0 	On success
+ * -1 on failure
+ */
+int rsstdeldownloaded(rsstor_handle *handle, int id)
+{
+	int      rc=0;
+	sqlite3 *db=NULL;
+
+	/*
+	 * Get db pointer
+	 */
+	db = handle->db;
+
+	static char *query="delete from downloaded where id=?1;";
+
+	/*
+	 * Execute query to delete
+	 */
+	rc = rsstexecutequery(db, query, "d", id);
+
+	return rc;
+}
diff --git a/tags/swarmtv-0.9.2/libswarmtv/torrentdb.h b/tags/swarmtv-0.9.2/libswarmtv/torrentdb.h
new file mode 100644
index 0000000..c10d547
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/torrentdb.h
@@ -0,0 +1,73 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+/*
+ * Free strings in newtorrents_struct
+ * Be sure to free the struct yourself.
+ * Arguments
+ * @arguments
+ * newtor newtor structure pointer
+ */
+void rsstfreenewtor(newtorrents_struct *newtor);
+
+/*
+ * Add a torrent to the newtorrent table.
+ * @arguments
+ * newtor structure holding the values for the record to be added
+ * @returns
+ * 0 on succes, exits on -1 on failure
+ */
+int rsstaddnewtorrent(rsstor_handle *handle, newtorrents_struct *newtor);
+
+/*
+ * Add a torrent to the downloaded table.
+ * @arguments
+ * downed			pointer to struct holding values to add to the db.
+ * simulate		0 to log addition, 1 adds anyway, but does not log at all. (used for filtertest)
+ */
+void rsstadddownloaded(rsstor_handle *handle, downloaded_struct *downed, SIM  simulate);
+
+/*
+ * Delete from downloaded table
+ * @arguments
+ * handle rsstor handle
+ * id 	id of the downloaded torrent to delete from downed table
+ * @returns
+ * 0 	On success
+ * -1 on failure
+ */
+int rsstdeldownloaded(rsstor_handle *handle, int id);
+
+/*
+ * When Torrents are prosessed, they are no longer new
+ * this method removes the new flag
+ */
+void rsstnonewtorrents(rsstor_handle *handle);
+
+/*
+ * Delete all newtorrents entris older the x days
+ * This function returns 0 on succes, -1 SQL on failure.
+ * @arguments
+ * days max age a newtorrent may become before deletion
+ * @return
+ * returns 0 on succes, -1 on error.
+ */
+int rsstdeloldnewtorents(rsstor_handle *handle, unsigned int days);
+
diff --git a/tags/swarmtv-0.9.2/libswarmtv/torrentdownload.c b/tags/swarmtv-0.9.2/libswarmtv/torrentdownload.c
new file mode 100644
index 0000000..c44642a
--- /dev/null
+++ b/tags/swarmtv-0.9.2/libswarmtv/torrentdownload.c
@@ -0,0 +1,1030 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Please refer to the LICENSE.txt file that comes along with this source file
+ *  or to http://www.gnu.org/licenses/gpl.txt for a full version of the license.
+ *
+ *  Program written by Paul Honig 2009
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pcre.h>
+#include <sqlite3.h>
+#include <time.h>
+
+#include "types.h"
+#include "config.h"
+#include "curlfile.h"
+#include "torrentdb.h"
+#include "logfile.h"
+#include "filehandler/filehandler.h"
+#include "filesystem.h"
+#include "database.h"
+#include "callback.h"
+#include "lastdownloaded.h"
+#include "baretitle.h"
+
+/*
+ * When libesmtp is included add header here.
+ */
+//#ifdef RSST_ESMTP_ENABLE
+//  #include "mailmsg.h"
+//#endif
+/*
+ * Max message and subject lenght for notification email
+ */
+#define MAXMSGLEN 2024
+
+
+/*
+ * Apply the filters from the query.
+ * when simulate is set to 'sim' no actual downloads are performed
+ */
+void rsstapplyfilter(rsstor_handle *handle, char *name, FILTER_TYPE type, char* nodouble, char *filtertitle, SIM simulate, char *filter, char *fmt, ...);
+
+/*
+ * Test for double downloads.
+ * Queries need to be provided by the user.
+ * return 1 if double, 0 if new
+ */
+static int testdouble(sqlite3 *db, char *nodouble, char *titleregexp, downloaded_struct *downed);
+
+/*
+ * Do download.
+ * take url, create name and call curl routine
+ */
+static int dodownload(rsstor_handle *handle, downloaded_struct *downed);
+
+/*
+ * Get the filters from the database.
+ * apply the filters.
+ * then download the results.
+ * return
+ * return 0 on succes, -1 on failure
+ */
+int rsstdownloadtorrents(rsstor_handle *handle)
+{
+  sqlite3_stmt  *ppStmt;
+  const char    *pzTail;
+  int           rc;
+  int           step_rc;
+  char          *zErrMsg = 0;
+  filter_struct sql_data;
+
+  const char *query = "select id, name, filter, nodouble from filters";
+
+  /*
+   * Prepare the sqlite statement
+   */
+  rc = rsst_sqlite3_prepare(
+      handle->db,        /* Database handle */
+      query,            /* SQL statement, UTF-8 encoded */
+      strlen(query),    /* Maximum length of zSql in bytes. */
+      &ppStmt,          /* OUT: Statement handle */
+      &pzTail           /* OUT: Pointer to unused portion of zSql */
+      );
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "sqlite3_prepare_v2 %s:%d", __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return -1;
+  }
+
+  /*
+   * loop until the end of the dataset is found
+   */
+  while( SQLITE_DONE != (step_rc = sqlite3_step(ppStmt))) {
+    /*
+     * Get name and query of the filters
+     */
+    sql_data.id = sqlite3_column_int(ppStmt, 0);
+    sql_data.name = (char*) sqlite3_column_text(ppStmt, 1);
+    sql_data.filter = (char*) sqlite3_column_text(ppStmt, 2);
+    sql_data.nodup = (char*) sqlite3_column_text(ppStmt, 3);
+
+    /*
+     * Send callbacks we are about to apply filter
+     */
+    rsstexecallbacks(handle, applysqlfilt, &sql_data);
+
+    /*
+     * call apply filter
+     */
+    rsstapplyfilter(handle, sql_data.name, sql, sql_data.nodup, NULL, (SIM) real, sql_data.filter, NULL);
+  }
+
+  /*
+   * Done with query, finalizing.
+   */
+  rc = sqlite3_finalize(ppStmt);
+
+  /*
+   * All gone well
+   */
+  return rc;
+}
+
+
+/*
+ * Test for double downloads.
+ * Queries need to be provided by the user.
+ * return 1 if double, 0 if new
+ */
+static int testdouble(sqlite3 *db, char *nodouble, char *titleregexp, downloaded_struct *downed)
+{
+  sqlite3_stmt  *ppStmt;
+  const char    *pzTail;
+  int           rc;
+  int           step_rc;
+  char          *bareregexp=NULL;
+  char          *zErrMsg = 0;
+
+  /*
+   * Generate bare title regexp
+   */
+  rsstmakebareregexp(downed->baretitle, &bareregexp);
+
+  /*
+   * prepare query
+   */
+  rc = rsst_sqlite3_prepare(
+      db,                 /* Database handle */
+      nodouble,            /* SQL statement, UTF-8 encoded */
+      strlen(nodouble),    /* Maximum length of zSql in bytes. */
+      &ppStmt,             /* OUT: Statement handle */
+      &pzTail              /* OUT: Pointer to unused portion of zSql */
+      );
+  if( rc!=SQLITE_OK ){
+    rsstwritelog(LOG_ERROR, "Testdouble query failed: %s %s:%d", nodouble, __FILE__, __LINE__);
+    rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+    sqlite3_free(zErrMsg);
+    return -1;
+  }
+
+  /*
+   * Bind values
+   * torrentdb.c:116:  rc = sqlite3_bind_text(ppStmt, 4, category, -1, SQLITE_TRANSIENT);
+   * torrentdb.c:117:  rc = sqlite3_bind_int(ppStmt, 5, season);
+   */
+  rc = sqlite3_bind_text(ppStmt, 1, downed->link, -1, SQLITE_TRANSIENT);
+  rc = sqlite3_bind_int(ppStmt, 2, downed->season);
+  rc = sqlite3_bind_int(ppStmt, 3, downed->episode);
+	if(titleregexp != NULL) {
+		rc = sqlite3_bind_text(ppStmt, 4, titleregexp, -1, SQLITE_TRANSIENT);
+	}
+  rc = sqlite3_bind_text(ppStmt, 5, bareregexp, -1, SQLITE_TRANSIENT);
+
+  /*
+   * Execute query
+   */
+  step_rc = sqlite3_step(ppStmt);
+
+  /*
+   * Cleanup
+   */
+  sqlite3_finalize(ppStmt);
+  free(bareregexp);
+
+  /*
+   * return result
+   */
+  if(step_rc == SQLITE_ROW) {
+    return 1; // ROW was found so It's a duplicate
+  } else {
+    return 0; // None found we has fresh meat :)
+  }
+}
+
+
+
+/*
+ * Use the filtername and type to get the filterid, use the link to get the downloaded id.
+ * @Arguments
+ * handle RSS-torrent handle
+ * downed Downloaded structure holding the downloaded data.
+ * filtername the name of the simple or sql filter
+ * type the filter type sql or simple
+ * @Return
+ * 0 on success -1 on failure
+ */
+int rsstupdatelastdowned(rsstor_handle *handle, downloaded_struct *downed, FILTER_TYPE type)
+{
+  int rc=0;
+  int downloadedid=0;
+  int filterid=0;
+  char *value=NULL;
+  char *downedquery = "select id from downloaded where link = ?1 LIMIT 1";
+  char *simpleidquery = "SELECT id FROM simplefilters WHERE name = ?1 LIMIT 1";
+  char *sqlidquery = "SELECT id FROM filters WHERE name = ?1 LIMIT 1";
+
+  /*
+   * Get downloaded id
+   */
+  rc = rsstdosingletextquery(handle->db, (unsigned char const**)&value, downedquery, "s", downed->link);
+  if(rc == 0){
+    downloadedid = (int) atoi(value);
+    free(value);
+    value=NULL;
+  } else {
+    rsstwritelog(LOG_ERROR, "Could not get downloaded ID for link '%s'  %s:%d", downed->link, __FILE__, __LINE__);
+    free(value);
+    return -1;
+  }
+
+  /*
+   * Get filter id and add the entry to the database.
+   */
+  switch(type){
+    case sql:
+      rc = rsstdosingletextquery(handle->db, (unsigned char const**)&value, sqlidquery, "s", downed->filter);
+      if(rc != 0){
+        rsstwritelog(LOG_ERROR, "Quering for sql filter id failed  %s:%d", __FILE__, __LINE__);
+        free(value);
+        return -1;
+      }
+
+      break;
+    case simple:
+      rc = rsstdosingletextquery(handle->db, (unsigned char const**)&value, simpleidquery, "s", downed->filter);
+      if(rc != 0){
+        rsstwritelog(LOG_ERROR, "Quering for simple filter id failed %s:%d", __FILE__, __LINE__);
+        free(value);
+        return -1;
+      }
+
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "Unknown filter type %s:%d", __FILE__, __LINE__);
+      free(value);
+      return -1;
+  }
+  filterid = (int) atoi(value);
+  free(value);
+  value=NULL;
+
+  /*
+   * Call the registration.
+   */
+  rc = rsstaddlastdownload(handle, filterid, downloadedid, type);
+  if(rc != 0){
+		rsstwritelog(LOG_ERROR, "Adding download to lastdownload table failed %s:%d", __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * Done
+   */
+  return 0;
+}
+
+
+/*
+ * Handle new results
+ */
+static void rssthandlenewresults(rsstor_handle *handle, FILTER_TYPE type, downloaded_struct *downed, SIM simulate)
+{
+	int downsuccess=0;
+	char errorstr[MAXMSGLEN+1];
+
+	/*
+	 * Make sure the string is terminated
+	 */
+	errorstr[MAXMSGLEN] = '\0';
+
+	/*
+	 * call apply filter
+	 * When the routine is called in simulated mode, no downloads are done
+	 */
+	if(simulate == (SIM) real) {
+
+		/*
+		 * Download torrent when download is successful send email.
+		 */
+		downsuccess = dodownload(handle, downed);
+		if(downsuccess == 0) {
+			/*
+			 * Send email and call callbacks
+			 */
+			//rsstsendemail(handle->db, filter, downed);
+      rsstexecallbacks(handle, downloadtorrent, downed);
+		} else {
+			/*
+			 * Call the torrent download callback and report error
+       * @@ FIX make sure this gets handled in the future.
+			 */
+			//snprintf(errorstr, MAXMSGLEN, "Torrent download failed '%s', '%s'", downed->title, downed->link);
+			//rsstexetorcallback(handle, downed->id, -1, errorstr);
+
+		}
+	}
+
+	/*
+	 * Only when download is success or simulation is enabled add found torrents to downloaded table.
+	 */
+	if(downsuccess == 0){
+		/*
+		 * When download has succeeded add entry to downloaded table
+		 * Double download attempt will not occur as a newtorrent entry is only new once.
+		 */
+		rsstadddownloaded(handle, downed, simulate);
+
+    /*
+     * Update the lastdownloaded table
+     */
+    rsstupdatelastdowned(handle, downed, type);
+	}
+}
+
+
+/*
+ * Handle filter results
+ */
+static void rssthandlefiltresults(rsstor_handle *handle, sqlite3_stmt *ppStmt, char *filtername, FILTER_TYPE type, char* nodouble, char *titleregexp, SIM simulate)
+{
+	int 							rc=0;
+	int							  step_rc=0;
+	downloaded_struct downed;
+
+	/*
+	 * loop until the end of the dataset is found
+	 */
+	while( SQLITE_DONE != (step_rc = sqlite3_step(ppStmt))) {
+		/*
+		 * Get name and query of the filters
+		 */
+		memset(&downed, 0, sizeof(downloaded_struct));
+    downed.id        =  sqlite3_column_int(ppStmt, 0);
+		downed.link      = (char*) sqlite3_column_text(ppStmt, 1);
+		downed.title     = (char*) sqlite3_column_text(ppStmt, 2);
+		downed.pubdate   = (char*) sqlite3_column_text(ppStmt, 3);
+		downed.category  = (char*) sqlite3_column_text(ppStmt, 4);
+    downed.metatype  = (char*) sqlite3_column_text(ppStmt, 5);
+		downed.season    =  sqlite3_column_int(ppStmt, 6);
+		downed.episode   =  sqlite3_column_int(ppStmt, 7);
+    downed.filter    =  filtername;
+    downed.type      =  type;
+
+    /*
+     * Use the downed.title to isolate to name in the title.
+     * Form this into a regexp, and provide that to the double test.
+     * downed.baretitle
+     */
+    rc = rsstfillbaretitle(&downed);
+    if(rc == -1) {
+      rsstwritelog(LOG_ERROR, "Extracting bare title failed! '%s' %s:%d", downed.title, __FILE__, __LINE__);
+    }
+
+		/*
+		 * Test if episode is already there
+		 */
+		rc = testdouble(handle->db, nodouble, titleregexp, &downed);
+		if(rc == 0) {
+			/*
+			 * Handle results that are no duplicate.
+			 */
+			rssthandlenewresults(handle, type, &downed, simulate);
+		} else {
+			rsstwritelog(LOG_DEBUG, "%s Season %d Episode %d is a duplicate %s:%d",
+					downed.title, downed.episode, downed.season, __FILE__, __LINE__);
+		}
+
+    /*
+     * Free bare title
+     */
+    free(downed.baretitle);
+	}
+}
+
+
+/*
+ * Apply the filters from the query.
+ * when simulate is set !=0 no actual downloads are performed
+ * arguments :
+ * db					: Sqlite3 pointer
+ * *name			: Filter name
+ * *nodouble	: SQL for the nodouble filter
+ * simulate		: When 1 simulation mode 0, no simualtion
+ * *filter		: Filter SQL
+ * *fmt				:	Format of the arguments to insert into the filter sql
+ * ...				:	Arguments for the filter SQL.
+ */
+void rsstapplyfilter(rsstor_handle *handle, char *name, FILTER_TYPE type, char* nodouble, char *titleregexp, SIM simulate, char *filter, char *fmt, ...)
+{
+	sqlite3_stmt  *ppStmt=NULL;
+	const char    *pzTail=NULL;
+	int           rc=0;
+	char          *zErrMsg=NULL;
+	va_list     	ap;
+	int						retval=0;
+	int						count=0;
+	char     	   *s=NULL;
+	int       	  d=0;
+	double        f=0.0;
+
+	/*
+	 * NULL = no arguments.
+	 */
+	if(fmt == NULL) {
+		fmt = "";
+	}
+
+	/*
+	 * Prepare the sqlite statement
+	 */
+	rc = rsst_sqlite3_prepare(
+			handle->db,           /* Database handle */
+			filter,            		/* SQL statement, UTF-8 encoded */
+			strlen(filter),    		/* Maximum length of zSql in bytes. */
+			&ppStmt,             	/* OUT: Statement handle */
+			&pzTail              	/* OUT: Pointer to unused portion of zSql */
+			);
+	if( rc!=SQLITE_OK ){
+		rsstwritelog(LOG_ERROR, "Filter '%s' failed %s:%d", name, __FILE__, __LINE__);
+		rsstwritelog(LOG_ERROR, "'%s'", filter);
+		rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+		sqlite3_free(zErrMsg);
+		retval=-1;
+	}
+
+	/*
+	 * Handle the arguments
+	 */
+	if(retval == 0) {
+		va_start(ap, fmt);
+		while (*fmt != '\0' && retval == 0){
+			count++; // next item
+			switch(*fmt++) {
+				case 's':            /* string */
+					s = va_arg(ap, char *);
+					rc = sqlite3_bind_text(ppStmt, count, s, -1, SQLITE_TRANSIENT);
+					if( rc!=SQLITE_OK ){
+						rsstwritelog(LOG_ERROR, "sqlite3_bind_text failed on argument '%d'\n'%s'\n'%s' %s:%d",
+								count, filter, fmt, __FILE__, __LINE__);
+						rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+						sqlite3_free(zErrMsg);
+						retval=-1;
+					}
+					break;
+				case 'd':            /* int */
+					d = va_arg(ap, int);
+					rc = sqlite3_bind_int(ppStmt, count, d);
+					if( rc!=SQLITE_OK ){
+						rsstwritelog(LOG_ERROR, "sqlite3_bind_int failed on argument '%d'\n'%s'\n'%s' %s:%d",
+								count, filter, fmt, __FILE__, __LINE__);
+						rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+						sqlite3_free(zErrMsg);
+						retval=-1;
+					}
+					break;
+				case 'f':            /* int */
+					f = va_arg(ap, double);
+					rc = sqlite3_bind_double(ppStmt, count, f);
+					if( rc!=SQLITE_OK ){
+						rsstwritelog(LOG_ERROR, "sqlite3_bind_double failed on argument '%d'\n'%s'\n'%s' %s:%d",
+								count, filter, fmt, __FILE__, __LINE__);
+						rsstwritelog(LOG_ERROR, "SQL error: %s", zErrMsg);
+						sqlite3_free(zErrMsg);
+						retval=-1;
+					}
+					break;
+				default:
+					rsstwritelog(LOG_ERROR, "Unknown format '%c' on position '%d'\nQuery: '%s'\nFmt: '%s'",
+							*fmt, count, filter, fmt);
+					retval=-1;
+			}
+		}
+		va_end(ap);
+	}
+
+	if(retval == 0) {
+		/*
+		 * Handle query results, filter out doubles, and take according action.
+		 */
+		rssthandlefiltresults(handle, ppStmt, name, type, nodouble, titleregexp, simulate);
+	}
+
+	/*
+	 * Done with query, finalizing.
+	 */
+	rc = sqlite3_finalize(ppStmt);
+}
+
+
+/*
+ * Create from settings and filename a complete path
+ * @Arguments
+ * handle
+ * downed
+ * path
+ * metatype
+ * fullpath
+ * @Return
+ * 0 when all was succesfull, -1 when things gone wrong
+ */
+static int rsstgetdownloadpath(rsstor_handle *handle, downloaded_struct *downed, METAFILETYPE type, char *filename)
+{
+	char *path = NULL;
+	char *fullpath = NULL;
+  char *extension = NULL;
+
+	/*
+	 * get path to put torrent in
+	 */
+  if(type == torrent) {
+    rsstconfiggetproperty(handle, CONF_TORRENTDIR, &path);
+    extension = "torrent";
+  }
+  else if(type == nzb) {
+    rsstconfiggetproperty(handle, CONF_NZBDIR, &path);
+    extension = "nzb";
+  } else {
+    rsstwritelog(LOG_ERROR, "Meta file type unknown for '%s'. %s:%d", downed->title, __FILE__, __LINE__);
+    return -1;
+  }
+
+  /*
+   * If the meta file path is not set error
+   */
+  if(strlen(path) == 0) {
+    if(type == torrent) {
+      rsstwritelog(LOG_NORMAL, "Trying to download Torrent while no download path is set!");
+    }
+    if(type == nzb) {
+      rsstwritelog(LOG_NORMAL, "Trying to download NZB while no download path is set!");
+    }
+    return -1;
+  }
+
+  /*
+   * Create full path from abbreviations
+   */
+	rsstcompletepath(path, &fullpath);
+
+	/*
+	 * Create filename.
+	 */
+	snprintf(filename, 255, "%s/%sS%dE%dR%s.%s",
+			fullpath, downed->title, downed->season, downed->episode, downed->pubdate, extension);
+
+	/*
+	 * Cleanup
+	 */
+	free(path);
+	free(fullpath);
+
+  return 0;
+}
+
+
+int rsstcheckdiskspace(rsstor_handle *handle, METAFILETYPE type, int *spaceondisk)
+{
+  int rc=0;
+  int percentage=0;
+  int maxuse=0;
+  int enabled=0;
+  struct_diskusage usage;
+
+  /*
+   * Initialize spacedisk when no blocking
+   */
+  *spaceondisk=1;
+  memset(&usage, 0, sizeof(struct_diskusage));
+
+  /*
+   * Get the maximal partition usage
+   */
+  rc = rsstgetmaxusage(handle, &maxuse);
+  if(rc != 0){
+    return -1;
+  }
+
+  /*
+   * Use the type to get the NZB or torrent usage
+   */
+  switch(type) {
+    case torrent:
+      rc = rssttorusage(handle, &enabled, &percentage);
+
+      break;
+    case nzb:
+      rc = rsstnzbusage(handle, &enabled, &percentage);
+
+      break;
+    default:
+      rsstwritelog(LOG_ERROR, "Meta file type unknown. %s:%d", __FILE__, __LINE__);
+      return -1;
+  }
+  if(rc != 0){
+    return -1;
+  }
+
+  /*
+   * When the usage is over the limit set spaceondisk to 0 and log a message
+   */
+  if(enabled == 1) {
+    if(percentage > maxuse) {
+      *spaceondisk=0;
+      if(type == torrent) {
+        rsstwritelog(LOG_ERROR, "Torrent download directory full. %s:%d", __FILE__, __LINE__);
+      }
+      if(type == nzb) {
+        rsstwritelog(LOG_ERROR, "NZB download directory full. %s:%d", __FILE__, __LINE__);
+      }
+
+      /*
+       * Send callback
+       */
+      usage.limit=maxuse;
+      usage.use=percentage;
+      usage.metatype=type;
+      rsstexecallbacks(handle, diskfull, &usage);
+    }
+  }
+
+  return 0;
+}
+
+/*
+ * Do download.
+ * take url, create name and call curl routine
+ * @Arguments
+ *
+ */
+static int dodownload(rsstor_handle *handle, downloaded_struct *downed)
+{
+	char filename[256];
+  int   rc=0;
+  int   spaceondisk=0;
+	int   retval=0;
+  METAFILETYPE type=undefined;
+
+  /*
+   * Define METAFILE type
+   */
+  rc = metafilestrtotype(downed->metatype, &type);
+  if(rc != 0) {
+    rsstwritelog(LOG_ERROR, "Meta file type unknown for '%s'. %s:%d", downed->title, __FILE__, __LINE__);
+    retval = -1;
+  }
+
+  /*
+   * Check if there is enough space on the download partitions
+   */
+  rc = rsstcheckdiskspace(handle, type, &spaceondisk);
+  if(rc != 0) {
+    rsstwritelog(LOG_ERROR, "Check disk space failed! %s:%d", __FILE__, __LINE__);
+    retval=-1;
+  }
+
+  /*
+   * Determine full Path, and commence download when success
+   */
+  rc = rsstgetdownloadpath(handle, downed, type, filename);
+  if(rc == 0 && retval == 0 && spaceondisk == 1) {
+    /*
+     * download
+     */
+    retval = rsstfindmetafilewrite(handle, type, downed->link, filename, downed->filter);
+  } else {
+    /*
+     * Meta type unknown, this is problematic
+     */
+    rsstwritelog(LOG_ERROR, "Download failed! %s:%d", __FILE__, __LINE__);
+    retval=-1;
+  }
+
+  //free(fullpath);
+
+	return retval;
+}
+
+
+/*
+ * This routine function downloads the torrent indicated by ID.
+ * The routine looks throught the newtorrents table to pick the torrent by id.
+ * @arguments
+ * torid	The id that points to the torrent
+ * @returns
+ * 0 on success
+ * -1 on failure
+ */
+int rsstdownloadbyid(rsstor_handle *handle, int torid)
+{
+	int 							rc=0;
+	sqlite3_stmt 			*ppstmt=NULL;
+	downloaded_struct downed;
+	int								retval=0;
+	int								step_rc=0;
+	sqlite3          *db=NULL;
+
+	/*
+	 * Get db pointer.
+	 */
+	db = handle->db;
+
+	static char *manualquery = "select id, link, title, pubdate, category, season, episode, metatype from newtorrents where id = ?1";
+
+	/*
+	 * Retrieve record from newtor table
+	 */
+	rc = rsstexecqueryresult(db, &ppstmt, manualquery, "d", torid);
+
+	/*
+	 * Get the first record
+	 */
+	step_rc = sqlite3_step(ppstmt);
+	if(step_rc != SQLITE_ROW) {
+		/*
+		 * No Records found
+		 */
+		retval = -1;
+	}
+
+	if(retval == 0) {
+		/*
+		 * initiate download
+		 */
+		memset(&downed, 0, sizeof(downloaded_struct));
+    downed.id        = sqlite3_column_int(ppstmt, 0);
+		downed.link      = (char*) sqlite3_column_text(ppstmt, 1);
+		downed.title     = (char*) sqlite3_column_text(ppstmt, 2);
+		downed.pubdate   = (char*) sqlite3_column_text(ppstmt, 3);
+		downed.category  = (char*) sqlite3_column_text(ppstmt, 4);
+		downed.season    =  sqlite3_column_int(ppstmt, 5);
+		downed.episode   =  sqlite3_column_int(ppstmt, 6);
+    downed.metatype  = (char*) sqlite3_column_text(ppstmt, 7);
+
+		/*
+		 * Execute download
+		 */
+		rc = dodownload(handle, &downed);
+		if(rc == 0) {
+			/*
+			 * Download successfull
+			 * Add download to downloaded database
+			 */
+			rsstadddownloaded(handle, &downed, 0);
+		} else {
+			/*
+			 * Download failed torrent not found
+			 */
+			retval = -1;
+		}
+	}
+
+	/*
+	 * Done with query, finalizing.
+	 */
+	rc = sqlite3_finalize(ppstmt);
+
+	return retval;
+}
+
+/*
+ * This routine function downloads the torrent indicated by ID.
+ * The routine looks throught the newtorrents table to pick the torrent by id.
+ * @arguments
+ * torid The id that points to the torrent
+ * @returns
+ * 0 on success
+ * -1 on failure
+ */
+int rsstdownloadbyidstr(rsstor_handle *handle, char *torid)
+{
+	int rc=0;
+	int i_torid=0;
+
+	/*
+	 * convert torid to int
+	 */
+	i_torid=atoi(torid);
+
+	/*
+	 * call real routine
+	 */
+	rc = rsstdownloadbyid(handle, i_torid);
+	if(rc == 0){
+		/*
+		 * Download successfull
+		 */
+		printf("Torrentdownload successful.\n");
+	} else {
+		/*
+		 * Download failed
+		 */
+		printf("Torrentdownload failed.\n");
+	}
+
+	return rc;
+}
+
+
+/*
+ * Test torrentdir
+ * returns
+ * 0 on succes otherwise -1
+ */
+int rssttestmetafiledir(rsstor_handle *handle)
+{
+  int retval=0;
+	int torexist=0;
+	int nzbexist=0;
+  int torwritable=0;
+  int nzbwritable=0;
+  int torpathlen=0;
+  int nzbpathlen=0;
+	char *torpath = NULL;
+	char *nzbpath = NULL;
+	char *fullpath = NULL;
+	sqlite3 *db=NULL;
+
+	/*
+	 * Get database pointer
+	 */
+	db = handle->db;
+
+	/*
+	 *  Get all the information into the variables
+	 */
+	rsstconfiggetproperty(handle, CONF_TORRENTDIR, &torpath);
+	rsstconfiggetproperty(handle, CONF_NZBDIR, &nzbpath);
+	torexist = rsstfsexists(torpath);
+	nzbexist = rsstfsexists(nzbpath);
+  torpathlen = strlen(torpath);
+  nzbpathlen = strlen(nzbpath);
+
+  /*
+   * Print the errors
+   */
+	if(torexist != 0 && torpathlen != 0) {
+		rsstwritelog(LOG_ERROR, "Torrent directory '%s' does not exist!", torpath);
+		rsstwritelog(LOG_ERROR,
+				"Please create the directory, or alter torrent directory by setting 'torrentdir' in the config. (--set-config \"torrentdir:<path>\"), "
+        "clear the setting to disable NZB download.");
+	}
+  if(nzbexist !=0 && nzbpathlen != 0) {
+		rsstwritelog(LOG_ERROR, "NZB directory '%s' does not exist!", nzbpath);
+		rsstwritelog(LOG_ERROR,
+				"Please create the directory, or alter NZB directory by setting 'nzbdir' in the config. (--set-config \"nzbdir:<path>\"), "
+        "clear the setting to disable NZB download.");
+  }
+
+	/*
+	 * Test if the directory is writable to us
+	 */
+	if(torexist == 0 && torpathlen != 0) {
+		torwritable |= rssttestwrite(torpath);
+		if(torwritable != 0) {
+			rsstwritelog(LOG_ERROR, "Torrent directory '%s' is not writable!", torpath);
+		}
+	}
+	if(nzbexist == 0 && nzbpathlen != 0) {
+		nzbwritable |= rssttestwrite(nzbpath);
+		if(nzbwritable != 0) {
+			rsstwritelog(LOG_ERROR, "NZB directory '%s' is not writable!", nzbpath);
+		}
+	}
+
+  /*
+   * Return != 0 when both torrent and NZB are invalid
+   */
+  if(((torexist != 0 || torwritable != 0) && torpathlen != 0) ||
+      ((nzbexist != 0 || nzbwritable != 0) && nzbpathlen != 0)) {
+    retval = -1;
+  }
+  if(torpathlen == 0 && nzbpathlen == 0) {
+    rsstwritelog(LOG_ERROR, "No torrent or NZB directory was set, please specify at least one.");
+    retval = -1;
+  }
+
+
+  /*
+   * Cleanup
+   */
+  free(torpath);
+  free(nzbpath);
+  free(fullpath);
+
+  return retval;
+}
+
+
+/*
+ * Get download partition usage
+ * @arguments
+ * confmondir config name to the monitor directory
+ * confenabled config name to the monitor enabled
+ * percentage percentage in use
+ * limit percentage limit
+ * @return
+ * 0 on success, -1 on failure
+ */
+static int rsstgetusage(rsstor_handle *handle, char *confmondir, char *confenabled, int *enabled, int *percentage)
+{
+  int rc=0;
+  int retval=0;
+  char *downpath=NULL;
+  char *enabledstr=NULL;
+
+  /*
+   * Init variables
+   */
+  *enabled=0;
+  *percentage=0;
+
+  /*
+   * Get settings
+   */
+  rc = rsstconfiggetproperty(handle, confmondir, &downpath);
+  rc |= rsstconfiggetproperty(handle, confenabled, &enabledstr);
+  if(rc != 0) {
+    rsstwritelog(LOG_ERROR, "Config value was not set, could not get disk usage %s:%d", __FILE__, __LINE__);
+    retval = -1;
+  }
+
+  if(retval == 0) {
+    if(strcasecmp(enabledstr, "y") == 0){
+      *enabled=1;
+    }
+  }
+
+  if(retval == 0 && *enabled == 1) {
+    /*
+     * Get usage
+     */
+    rc = rsstdiskusage(downpath, percentage);
+    if(rc != 0) {
+      rsstwritelog(LOG_ERROR, "Path incorrect, could not get disk usage %s:%d", __FILE__, __LINE__);
+      retval = -1;
+    }
+  }
+
+  free(downpath);
+  free(enabledstr);
+  return retval;
+}
+
+
+/*
+ * Torrent download partition usage
+ * @arguments
+ * percentage percentage in use
+ * limit percentage limit
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rssttorusage(rsstor_handle *handle, int *enabled, int *percentage)
+{
+  int rc=0;
+
+  rc = rsstgetusage(handle, CONF_TORMONDIR, CONF_TORMONENABLE, enabled, percentage);
+
+  return rc;
+}
+
+/*
+ * NZB download partition usage
+ * @arguments
+ * enabled set to 1 when enabled else 0
+ * percentage percentage in use when enabled is 0, this value is 0
+ * @return
+ * 0 on success, -1 on failure
+ */
+int rsstnzbusage(rsstor_handle *handle, int *enabled, int *percentage)