src/bitmapvalidator.cpp\r
src/board.cpp\r
src/boardlist.cpp\r
-src/commandthread.cpp\r
-src/datetime.cpp\r
+src/db\r
+src/dbconversions.cpp\r
+src/dbmaintenancethread.cpp\r
+src/dbsetup.cpp\r
+src/fmsapp.cpp\r
+src/freenet\r
src/global.cpp\r
src/hex.cpp\r
+src/http\r
+src/ipaddressacl.cpp\r
src/localidentity.cpp\r
-src/logfile.cpp\r
src/main.cpp\r
src/message.cpp\r
src/messagelist.cpp\r
+src/nntp\r
src/option.cpp\r
+src/optionssetup.cpp\r
src/socketdefines.cpp\r
src/stringfunctions.cpp\r
-src/threadcontroller.cpp\r
-src/uuidgenerator.cpp\r
+src/threadwrapper\r
src/db/sqlite3db.cpp\r
src/db/sqlite3recordset.cpp\r
src/db/sqlite3statement.cpp\r
src/freenet/boardlistinserter.cpp\r
src/freenet/boardlistrequester.cpp\r
src/freenet/boardlistxml.cpp\r
+src/freenet/captcha\r
src/freenet/fcpv2.cpp\r
src/freenet/fileinserter.cpp\r
src/freenet/freenetmasterthread.cpp\r
src/freenet/messagelistxml.cpp\r
src/freenet/messagerequester.cpp\r
src/freenet/messagexml.cpp\r
-src/freenet/periodicdbmaintenance.cpp\r
src/freenet/siteinserter.cpp\r
src/freenet/trustlistinserter.cpp\r
src/freenet/trustlistrequester.cpp\r
src/freenet/trustlistxml.cpp\r
src/freenet/unkeyedidcreator.cpp\r
+src/freenet/captcha/easybmp\r
src/freenet/captcha/simplecaptcha.cpp\r
src/freenet/captcha/easybmp/EasyBMP.cpp\r
src/freenet/captcha/easybmp/EasyBMP_Font.cpp\r
src/freenet/captcha/easybmp/EasyBMP_Geometry.cpp\r
+src/http/fmshttprequesthandlerfactory.cpp\r
src/http/httpthread.cpp\r
src/http/identityexportxml.cpp\r
src/http/ipagehandler.cpp\r
+src/http/multipartparser.cpp\r
+src/http/pages\r
src/http/pages/addpeerpage.cpp\r
src/http/pages/announceidentitypage.cpp\r
src/http/pages/boardspage.cpp\r
src/http/pages/peertrustpage.cpp\r
src/http/pages/showcaptchapage.cpp\r
src/nntp/extensiontrust.cpp\r
+src/nntp/mime\r
src/nntp/nntpconnection.cpp\r
src/nntp/nntplistener.cpp\r
src/nntp/uwildmat.cpp\r
src/nntp/mime/MimeChar.cpp\r
src/nntp/mime/MimeCode.cpp\r
src/nntp/mime/MimeType.cpp\r
-src/pthreadwrapper/guard.cpp\r
-src/pthreadwrapper/mutex.cpp\r
-src/pthreadwrapper/runnable.cpp\r
-src/pthreadwrapper/thread.cpp\r
-src/pthreadwrapper/threadedexecutor.cpp\r
-src/xyssl/sha1.c\r
+src/threadwrapper/threadedexector.cpp\r
)\r
\r
+SET(FMS_PLATFORM_SRC )\r
+\r
IF(DO_CHARSET_CONVERSION)\r
SET(FMS_SRC ${FMS_SRC} src/charsetconverter.cpp)\r
ENDIF(DO_CHARSET_CONVERSION)\r
\r
-IF(WIN32)\r
- SET(FMS_PLATFORM_SRC src/fmsservice.cpp)\r
-ELSE(WIN32)\r
- SET(FMS_PLATFORM_SRC src/fmsdaemon.cpp)\r
-ENDIF(WIN32)\r
-\r
IF(NOT I_HAVE_READ_THE_README)\r
MESSAGE(FATAL_ERROR "You must fully read the readme.txt before continuing.")\r
ENDIF(NOT I_HAVE_READ_THE_README)\r
\r
-ADD_DEFINITIONS(-DTIXML_USE_STL)\r
-\r
-# was for ZThreads\r
-#IF(CMAKE_COMPILER_IS_GNUCXX)\r
-# #ADD_DEFINITIONS(-fpermissive)\r
-# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")\r
-#ENDIF(CMAKE_COMPILER_IS_GNUCXX)\r
-\r
ADD_EXECUTABLE(fms ${FMS_SRC} ${FMS_PLATFORM_SRC})\r
\r
# link dl - For SQLite3 and shttpd - not for FreeBSD\r
ENDIF(CMAKE_COMPILER_IS_GNUCXX)\r
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")\r
\r
-# link ws2_32 for Windows\r
+# link ws2_32 and iphlpapi for Windows\r
IF(WIN32)\r
TARGET_LINK_LIBRARIES(fms ws2_32)\r
+ TARGET_LINK_LIBRARIES(fms iphlpapi)\r
ENDIF(WIN32)\r
\r
# add -lxnet and -lsocket on solaris\r
IF(NOT USE_BUNDLED_SQLITE)\r
FIND_LIBRARY(SQLITE3_LIBRARY NAMES sqlite3 sqlite3_s)\r
ENDIF(NOT USE_BUNDLED_SQLITE)\r
-FIND_LIBRARY(TINYXML_LIBRARY NAMES tinyxml tinyxml_s)\r
+FIND_LIBRARY(POCO_FOUNDATION_LIBRARY NAMES PocoFoundation PocoFoundationmt)\r
+FIND_LIBRARY(POCO_NET_LIBRARY NAMES PocoNet PocoNetmt)\r
+FIND_LIBRARY(POCO_UTIL_LIBRARY NAMES PocoUtil PocoUtilmt)\r
+FIND_LIBRARY(POCO_XML_LIBRARY NAMES PocoXML PocoXMLmt)\r
FIND_LIBRARY(PTHREADS_LIBRARY NAMES pthread pthreads pthreadvc2)\r
-FIND_LIBRARY(SHTTPD_LIBRARY NAMES shttpd shttpd_s)\r
FIND_LIBRARY(ICONV_LIBRARY NAMES iconv iconv_s libiconv libiconv_s)\r
\r
+IF(POCO_FOUNDATION_LIBRARY)\r
+ TARGET_LINK_LIBRARIES(fms ${POCO_FOUNDATION_LIBRARY})\r
+ IF(WIN32)\r
+ ADD_DEFINITIONS(-DPOCO_STATIC)\r
+ ENDIF(WIN32)\r
+ IF(POCO_UTIL_LIBRARY)\r
+ TARGET_LINK_LIBRARIES(fms ${POCO_UTIL_LIBRARY})\r
+ ELSE(POCO_UTIL_LIBRARY)\r
+ MESSAGE(FATAL_ERROR "Could not find system Poco Util library. You must set the location manually.")\r
+ ENDIF(POCO_UTIL_LIBRARY)\r
+ IF(POCO_NET_LIBRARY)\r
+ TARGET_LINK_LIBRARIES(fms ${POCO_NET_LIBRARY})\r
+ ELSE(POCO_NET_LIBRARY)\r
+ MESSAGE(FATAL_ERROR "Could not find system Poco Net library. You must set the location manually.")\r
+ ENDIF(POCO_NET_LIBRARY)\r
+ IF(POCO_XML_LIBRARY)\r
+ TARGET_LINK_LIBRARIES(fms ${POCO_XML_LIBRARY})\r
+ ELSE(POCO_XML_LIBRARY)\r
+ MESSAGE(FATAL_ERROR "Could not find system Poco XML library. You must set the location manually.")\r
+ ENDIF(POCO_XML_LIBRARY)\r
+ELSE(POCO_FOUNDATION_LIBRARY)\r
+ MESSAGE(FATAL_ERROR "Could not find system Poco Foundation library. You must set the location manually.")\r
+ENDIF(POCO_FOUNDATION_LIBRARY)\r
+\r
+IF(NOT WIN32)\r
+ IF(PTHREADS_LIBRARY)\r
+ TARGET_LINK_LIBRARIES(fms ${PTHREADS_LIBRARY})\r
+ ELSE(PTHREADS_LIBRARY)\r
+ MESSAGE(FATAL_ERROR "Could not find system pthread library. You must set the location manually.")\r
+ ENDIF(PTHREADS_LIBRARY)\r
+ENDIF(NOT WIN32)\r
+\r
IF(SQLITE3_LIBRARY)\r
TARGET_LINK_LIBRARIES(fms ${SQLITE3_LIBRARY})\r
ELSE(SQLITE3_LIBRARY)\r
INCLUDE_DIRECTORIES(libs/sqlite3)\r
ENDIF(SQLITE3_LIBRARY)\r
\r
-IF(TINYXML_LIBRARY)\r
- TARGET_LINK_LIBRARIES(fms ${TINYXML_LIBRARY})\r
-ELSE(TINYXML_LIBRARY)\r
- MESSAGE(STATUS "Could not find system TinyXML library. Will compile from included source.")\r
- ADD_LIBRARY(tinyxml libs/tinyxml/tinystr.cpp libs/tinyxml/tinyxml.cpp libs/tinyxml/tinyxmlerror.cpp libs/tinyxml/tinyxmlparser.cpp)\r
- TARGET_LINK_LIBRARIES(fms tinyxml)\r
- INCLUDE_DIRECTORIES(libs/tinyxml)\r
-ENDIF(TINYXML_LIBRARY)\r
-\r
-IF(PTHREADS_LIBRARY)\r
- TARGET_LINK_LIBRARIES(fms ${PTHREADS_LIBRARY})\r
-ELSE(PTHREADS_LIBRARY)\r
- MESSAGE(FATAL_ERROR "Could not find pthreads library. You must set the location manually.")\r
-ENDIF(PTHREADS_LIBRARY)\r
-\r
-IF(SHTTPD_LIBRARY)\r
- TARGET_LINK_LIBRARIES(fms ${SHTTPD_LIBRARY})\r
-ELSE(SHTTPD_LIBRARY)\r
- MESSAGE(STATUS "Could not find shttpd library. Will compile from included source.")\r
- ADD_DEFINITIONS(-DEMBEDDED)\r
- INCLUDE_DIRECTORIES(libs/shttpd/include)\r
- IF(WIN32)\r
- ADD_DEFINITIONS(-DNO_GUI)\r
- SET(SHTTPD_PLATFORM_SRC libs/shttpd/compat_win32.c)\r
- ELSE(WIN32)\r
- SET(SHTTPD_PLATFORM_SRC libs/shttpd/compat_unix.c)\r
- ENDIF(WIN32)\r
- ADD_LIBRARY(shttpd ${SHTTPD_PLATFORM_SRC} libs/shttpd/auth.c libs/shttpd/cgi.c libs/shttpd/config.c libs/shttpd/io_cgi.c libs/shttpd/io_dir.c libs/shttpd/io_emb.c libs/shttpd/io_file.c libs/shttpd/io_socket.c libs/shttpd/io_ssi.c libs/shttpd/io_ssl.c libs/shttpd/log.c libs/shttpd/md5.c libs/shttpd/shttpd.c libs/shttpd/string.c)\r
- TARGET_LINK_LIBRARIES(fms shttpd)\r
-ENDIF(SHTTPD_LIBRARY)\r
-\r
IF(DO_CHARSET_CONVERSION)\r
ADD_DEFINITIONS(-DDO_CHARSET_CONVERSION)\r
IF(ICONV_LIBRARY)\r
#ifndef _board_\r
#define _board_\r
\r
-#include "datetime.h"\r
#include "ilogger.h"\r
#include "idatabase.h"\r
\r
#include <string>\r
+#include <Poco/DateTime.h>\r
\r
class Board:public ILogger,public IDatabase\r
{\r
const long GetBoardID() const { return m_boardid; }\r
std::string GetBoardName() const { return m_boardname; }\r
std::string GetBoardDescription() const { return m_boarddescription; }\r
- DateTime GetDateCreated() const { return m_datecreated; }\r
+ Poco::DateTime GetDateCreated() const { return m_datecreated; }\r
const long GetLowMessageID() const { return m_lowmessageid; }\r
const long GetHighMessageID() const { return m_highmessageid; }\r
const long GetMessageCount() const { return m_messagecount; }\r
long m_boardid;\r
std::string m_boardname;\r
std::string m_boarddescription;\r
- DateTime m_datecreated;\r
+ Poco::DateTime m_datecreated;\r
long m_lowmessageid; // lowest id of all message currently in this board\r
long m_highmessageid; // highest id of all message currently in this board\r
long m_messagecount; // number of messages in this board\r
+++ /dev/null
-#ifndef _commandthread_\r
-#define _commandthread_\r
-\r
-#include "ilogger.h"\r
-#include "idatabase.h"\r
-\r
-//#include <zthread/Thread.h>\r
-#include "pthreadwrapper/runnable.h"\r
-\r
-class CommandThread:public PThread::Runnable,public ILogger, public IDatabase\r
-{\r
-public:\r
-\r
- void Run();\r
-\r
-private:\r
-\r
- void HandleInput(const std::string &input);\r
- \r
- // methods to handle commands\r
- void HandleHelpCommand();\r
- void HandleQuit();\r
- \r
- bool m_running;\r
-\r
-};\r
-\r
-#endif // _commandthread_\r
+++ /dev/null
-#ifndef _date_time_\r
-#define _date_time_\r
-\r
-#include <ctime>\r
-#include <string>\r
-\r
-/*\r
- Year actual year\r
- Month 1=Jan,2=Feb,etc\r
- Day 1 to last day of month\r
- Hour 0 to 23\r
- Minute 0 to 59\r
- Second 0 to 59\r
-\r
- WeekDay 0=Sunday,1=Monday,etc\r
- YearDay 1=Jan 1st, 2=Jan 2nd, etc\r
-\r
-*/\r
-\r
-class DateTime\r
-{\r
-public:\r
- DateTime();\r
- DateTime(const time_t &timet);\r
- DateTime(const struct tm *stm);\r
- ~DateTime() {}\r
-\r
- void Add(const int seconds=0, const int minutes=0, const int hours=0, const int days=0, const int months=0, const int years=0);\r
- \r
- void Set(const int year=1970, const int month=1, const int day=1, const int hour=0, const int minute=0, const int second=0);\r
- void SetT(const time_t &timet);\r
- void Set(const struct tm *stm);\r
- void Set(const std::string &datestring); // method only will work with a select few basic input formats\r
- \r
- void SetToLocalTime();\r
- void SetToGMTime();\r
- \r
- const int GetYear() const { return m_tm.tm_year+1900; }\r
- void SetYear(const int year) { m_tm.tm_year=year-1900; }\r
- const int GetMonth() const { return m_tm.tm_mon+1; }\r
- void SetMonth(const int month) { m_tm.tm_mon=month-1; }\r
- const int GetDay() const { return m_tm.tm_mday; }\r
- void SetDay(const int day) { m_tm.tm_mday=day; }\r
- const int GetWeekDay() const { return m_tm.tm_wday; }\r
- void SetWeekDay(const int weekday) { m_tm.tm_wday=weekday; }\r
- const int GetYearDay() const { return m_tm.tm_yday+1; }\r
- void SetYearDay(const int yearday) { m_tm.tm_yday=yearday-1; }\r
- const int GetHour() const { return m_tm.tm_hour; }\r
- void SetHour(const int hour) { m_tm.tm_hour=hour; }\r
- const int GetMinute() const { return m_tm.tm_min; }\r
- void SetMinute(const int minute) { m_tm.tm_min=minute; }\r
- const int GetSecond() const { return m_tm.tm_sec; }\r
- void SetSecond(const int second) { m_tm.tm_sec=second; }\r
- const int GetIsDaylightTime() const { return m_tm.tm_isdst; }\r
- void SetIsDaylightTime(const int daylighttime) { m_tm.tm_isdst=daylighttime; }\r
-\r
- void Normalize(); // normalizes any date changes that were made\r
- \r
- std::string Format(const std::string &formatstring) const;\r
-\r
- DateTime operator+(const double &rhs);\r
- DateTime operator+(const DateTime &rhs);\r
- DateTime &operator+=(const double &rhs);\r
- DateTime &operator+=(const DateTime &rhs);\r
- DateTime operator-(const double &rhs);\r
- DateTime operator-(const DateTime &rhs);\r
- DateTime &operator-=(const double &rhs);\r
- DateTime &operator-=(const DateTime &rhs);\r
- \r
- const bool operator==(const DateTime &rhs) const { return *this==rhs.m_tm; }\r
- const bool operator==(const time_t &rhs) const { return m_timet==rhs; }\r
- const bool operator==(const struct tm &rhs) const;\r
- \r
- const bool operator<(const DateTime &rhs) const { return (*this<rhs.m_tm); }\r
- const bool operator<(const time_t &rhs) const { return (m_timet<rhs); }\r
- const bool operator<(const struct tm &rhs) const;\r
- \r
- const bool operator<=(const DateTime &rhs) const { return (*this<rhs.m_tm || *this==rhs.m_tm); }\r
- const bool operator<=(const time_t &rhs) const { return (m_timet<=rhs); }\r
- const bool operator<=(const struct tm &rhs) const { return (*this<rhs || *this==rhs); }\r
- \r
- const bool operator>(const DateTime &rhs) const { return !(*this<=rhs.m_tm); }\r
- const bool operator>(const time_t &rhs) const { return (m_timet>rhs); }\r
- \r
- const bool operator>=(const DateTime &rhs) const { return !(*this<rhs.m_tm); }\r
- const bool operator>=(const time_t &rhs) const { return (m_timet>=rhs); }\r
- \r
-private:\r
- const time_t TimeGM(struct tm *gmtimein);\r
-\r
- time_t m_timet; // don't use timet for any comparisons\r
- struct tm m_tm;\r
-};\r
-\r
-#endif // _date_time_\r
#ifndef _sqlite3db_\r
#define _sqlite3db_\r
\r
-//#include <zthread/Singleton.h>\r
-//#include <zthread/Mutex.h>\r
+#include <Poco/Mutex.h>\r
#include <sqlite3.h>\r
#include <string>\r
-#include "../../pthreadwrapper/mutex.h"\r
#include "../sqlite3db.h"\r
-\r
-#include "../../pthreadwrapper/singleton.h"\r
+#include "../../threadwrapper/singleton.h"\r
\r
#if SQLITE_VERSION_NUMBER<3005000\r
#error "Your version of SQLite is too old! 3.5.0 or later is required."\r
namespace SQLite3DB\r
{\r
\r
-class DB:public PThread::Singleton<DB>\r
+class DB:public Singleton<DB>\r
{\r
public:\r
DB();\r
\r
sqlite3 *GetDB() { return m_db; }\r
\r
- PThread::Mutex m_mutex; // public so that recordset and statment can lock this mutex themselves\r
+ Poco::FastMutex m_mutex; // public so that recordset and statment can lock this mutex themselves\r
\r
private:\r
void Initialize();\r
--- /dev/null
+#ifndef _dbconversions_\r
+#define _dbconversions_\r
+\r
+void ConvertDB0100To0101();\r
+void ConvertDB0101To0103();\r
+void ConvertDB0103To0104();\r
+void ConvertDB0104To0105();\r
+void ConvertDB0105To0106();\r
+void ConvertDB0106To0107();\r
+void ConvertDB0107To0108();\r
+void ConvertDB0108To0109();\r
+void ConvertDB0109To0110();\r
+void ConvertDB0110To0111();\r
+void ConvertDB0111To0112();\r
+\r
+// TODO remove sometime after 0.1.17\r
+void FixCapitalBoardNames();\r
+\r
+#endif // _dbconversions_\r
--- /dev/null
+#ifndef _dbmaintenancethread_\r
+#define _dbmaintenancethread_\r
+\r
+#include "threadwrapper/cancelablerunnable.h"\r
+#include "ilogger.h"\r
+#include "idatabase.h"\r
+\r
+#include <Poco/DateTime.h>\r
+\r
+class DBMaintenanceThread:public CancelableRunnable,public ILogger,public IDatabase\r
+{\r
+public:\r
+ DBMaintenanceThread();\r
+\r
+ void run();\r
+\r
+private:\r
+\r
+ void Do10MinuteMaintenance();\r
+ void Do30MinuteMaintenance();\r
+ void Do1HourMaintenance();\r
+ void Do6HourMaintenance();\r
+ void Do1DayMaintenance();\r
+\r
+ Poco::DateTime m_last10minute;\r
+ Poco::DateTime m_last30minute;\r
+ Poco::DateTime m_last1hour;\r
+ Poco::DateTime m_last6hour;\r
+ Poco::DateTime m_last1day;\r
+\r
+ long m_deletemessagesolderthan;\r
+\r
+};\r
+\r
+#endif // _dbmaintenancethread_\r
--- /dev/null
+#ifndef _dbsetup_\r
+#define _dbsetup_\r
+\r
+// opens database and creates tables and initial inserts if necessary\r
+void SetupDB();\r
+\r
+#endif // _dbsetup_\r
--- /dev/null
+#ifndef _fmsapp_\r
+#define _fmsapp_\r
+\r
+#include "threadwrapper/threadedexecutor.h"\r
+\r
+#include <Poco/Util/ServerApplication.h>\r
+\r
+// main FMS application class\r
+class FMSApp:public Poco::Util::ServerApplication\r
+{\r
+public:\r
+ FMSApp();\r
+\r
+ static void Terminate() { ((FMSApp *)&FMSApp::instance())->terminate(); }\r
+\r
+private:\r
+ void initialize(Poco::Util::Application &self);\r
+ void initializeLogger();\r
+ void defineOptions(Poco::Util::OptionSet &options);\r
+ int main(const std::vector<std::string> &args);\r
+\r
+ void StartThreads();\r
+\r
+ void handleHelp(const std::string &name, const std::string &value);\r
+ void displayHelp();\r
+\r
+ bool m_displayhelp;\r
+\r
+ ThreadedExecutor m_threads;\r
+\r
+};\r
+\r
+#endif // _fmsapp_\r
+++ /dev/null
-#ifndef _fmsdaemon_\r
-#define _fmsdaemon_\r
-\r
-#define EXIT_SUCCESS 0\r
-#define EXIT_FAILURE 1\r
-\r
-void Daemonize();\r
-\r
-#endif // _fmsdaemon_\r
+++ /dev/null
-#ifndef _fmsservice_\r
-#define _fmsservice_\r
-\r
-#ifdef _WIN32\r
-\r
-#include <windows.h>\r
-\r
-#define FMS_SERVICE_NAME "FMS - Freenet Message System"\r
-\r
-extern SERVICE_STATUS ServiceStatus; \r
-extern SERVICE_STATUS_HANDLE hStatus; \r
-\r
-BOOL ServiceIsInstalled();\r
-BOOL ServiceInstall();\r
-BOOL ServiceUninstall();\r
-BOOL ServiceStart(); \r
-void ServiceMain(int argc, char** argv); \r
-void ControlHandler(DWORD request); \r
-\r
-#endif\r
-\r
-#endif // _fmsservice_\r
#include "ifcpconnected.h"\r
#include "iperiodicprocessor.h"\r
\r
-//#include <zthread/Runnable.h>\r
-#include "../pthreadwrapper/runnable.h"\r
+#include "../threadwrapper/cancelablerunnable.h"\r
\r
// forward declaration\r
class IFreenetRegistrable;\r
\r
-class FreenetMasterThread:public PThread::Runnable,public ILogger, public IFCPMessageHandler\r
+class FreenetMasterThread:public CancelableRunnable,public ILogger, public IFCPMessageHandler\r
{\r
public:\r
FreenetMasterThread();\r
\r
const bool HandleMessage(FCPMessage &message);\r
\r
- void Run();\r
+ void run();\r
\r
// registration methods for children objects\r
void RegisterPeriodicProcessor(IPeriodicProcessor *obj);\r
\r
#include "../idatabase.h"\r
#include "../ilogger.h"\r
-#include "../datetime.h"\r
#include "ifreenetregistrable.h"\r
#include "ifcpconnected.h"\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#include <Poco/DateTime.h>\r
+\r
class IdentityInserter:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
{\r
public:\r
void CheckForNeededInsert();\r
void StartInsert(const long localidentityid);\r
\r
- DateTime m_lastchecked;\r
+ Poco::DateTime m_lastchecked;\r
\r
};\r
\r
#define _identityintroductioninserter_\r
\r
#include "../idatabase.h"\r
-#include "../datetime.h"\r
#include "../ilogger.h"\r
#include "ifreenetregistrable.h"\r
#include "ifcpconnected.h"\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#include <Poco/DateTime.h>\r
+\r
class IdentityIntroductionInserter:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
{\r
public:\r
void StartInsert(const long localidentityid, const std::string &day, const std::string &UUID, const std::string &solution);\r
\r
std::string m_messagebase;\r
- DateTime m_lastchecked;\r
+ Poco::DateTime m_lastchecked;\r
bool m_inserting;\r
\r
};\r
\r
#include "../idatabase.h"\r
#include "../ilogger.h"\r
-#include "../datetime.h"\r
#include "ifreenetregistrable.h"\r
#include "ifcpconnected.h"\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#include <Poco/DateTime.h>\r
+\r
class IdentityIntroductionRequester:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
{\r
public:\r
const bool HandleGetFailed(FCPMessage &message);\r
const bool HandleAllData(FCPMessage &message);\r
\r
- DateTime m_tempdate;\r
+ Poco::DateTime m_tempdate;\r
std::map<long,bool> m_ids;\r
std::vector<std::string> m_requesting;\r
std::string m_messagebase;\r
#include "../idatabase.h"\r
#include "../ilogger.h"\r
#include "../option.h"\r
-#include "../datetime.h"\r
#include "../stringfunctions.h"\r
#include "ifreenetregistrable.h"\r
#include "ifcpconnected.h"\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timestamp.h>\r
+#include <Poco/Timespan.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
\r
std::vector<IDTYPE> m_inserting; // list of ids we are inserting\r
std::string m_messagebase;\r
- DateTime m_lastchecked;\r
+ Poco::DateTime m_lastchecked;\r
\r
// these MUST be populated by child class\r
std::string m_fcpuniquename;\r
// make sure variables have been initialized by the derived class\r
if(m_fcpuniquename=="")\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexInserter<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
+ m_log->fatal("IIndexInserter<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
}\r
if(m_fcpuniquename.find("|")!=std::string::npos)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexInserter<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
+ m_log->fatal("IIndexInserter<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
}\r
\r
m_inserting.clear();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(idparts[1],id);\r
RemoveFromInsertList(id);\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IIndexInserter<IDTYPE>::HandleMessage IdentifierCollision for "+m_fcpuniquename+" "+message["Identifier"]);\r
+ m_log->debug("IIndexInserter<IDTYPE>::HandleMessage IdentifierCollision for "+m_fcpuniquename+" "+message["Identifier"]);\r
return true;\r
}\r
}\r
{\r
m_fcpuniquename="";\r
Option::Instance()->Get("MessageBase",m_messagebase);\r
- m_lastchecked.SetToGMTime();\r
+ m_lastchecked=Poco::Timestamp();\r
}\r
\r
template <class IDTYPE>\r
void IIndexInserter<IDTYPE>::Process()\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
\r
- if(m_lastchecked<(now-(1.0/1440.0)))\r
+ if(m_lastchecked<(now-Poco::Timespan(0,0,1,0,0)))\r
{\r
CheckForNeededInsert();\r
m_lastchecked=now;\r
\r
#include "../idatabase.h"\r
#include "../ilogger.h"\r
-#include "../datetime.h"\r
#include "../option.h"\r
#include "../stringfunctions.h"\r
#include "ifreenetregistrable.h"\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timestamp.h>\r
+#include <Poco/Timespan.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
virtual const bool HandleGetFailed(FCPMessage &message)=0;\r
virtual void RemoveFromRequestList(const IDTYPE id);\r
\r
- DateTime m_tempdate;\r
- DateTime m_lastreceived;\r
- DateTime m_lastpopulated;\r
+ Poco::DateTime m_tempdate;\r
+ Poco::DateTime m_lastreceived;\r
+ Poco::DateTime m_lastpopulated;\r
std::string m_messagebase;\r
std::map<IDTYPE,bool> m_ids; // map of all ids we know and whether we have requested file from them yet\r
std::vector<IDTYPE> m_requesting; // list of ids we are currently requesting from\r
// make sure variables have been initialized by the derived class\r
if(m_maxrequests==-1)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexRequester<IDTYPE>::FCPConnected maxrequests not initialized correctly!");\r
+ m_log->fatal("IIndexRequester<IDTYPE>::FCPConnected maxrequests not initialized correctly!");\r
}\r
if(m_fcpuniquename=="")\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
+ m_log->fatal("IIndexRequester<IDTYPE>::FCPConnected fcpuniquename not initialized correctly!");\r
}\r
if(m_fcpuniquename.find("|")!=std::string::npos)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_FATAL,"IIndexRequester<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
+ m_log->fatal("IIndexRequester<IDTYPE>::FCPConnected fcpuniquename contains | character! This is not a valid character!");\r
}\r
\r
- m_lastreceived.SetToGMTime();\r
+ m_lastreceived=Poco::Timestamp();\r
m_requesting.clear();\r
PopulateIDList();\r
- m_lastpopulated.SetToGMTime();\r
+ m_lastpopulated=Poco::Timestamp();\r
}\r
\r
template <class IDTYPE>\r
if(message["Identifier"].find(m_fcpuniquename)==0)\r
{\r
\r
- m_lastreceived.SetToGMTime();\r
+ m_lastreceived=Poco::Timestamp();\r
\r
if(message.GetName()=="DataFound")\r
{\r
m_fcpuniquename="";\r
\r
Option::Instance()->Get("MessageBase",m_messagebase);\r
- m_tempdate.SetToGMTime();\r
- m_lastreceived.SetToGMTime();\r
- m_lastpopulated.SetToGMTime();\r
- m_lastpopulated.Add(0,-10);\r
+ m_tempdate=Poco::Timestamp();\r
+ m_lastreceived=Poco::Timestamp();\r
+ m_lastpopulated=Poco::Timestamp();\r
+ m_lastpopulated-=Poco::Timespan(0,0,10,0,0);\r
}\r
\r
template <class IDTYPE>\r
void IIndexRequester<IDTYPE>::Process()\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
\r
// max is the smaller of the config value or the total number of ids we will request from\r
typename std::map<IDTYPE,bool>::size_type max=m_maxrequests>m_ids.size() ? m_ids.size() : m_maxrequests;\r
else\r
{\r
// we requested from all ids in the list, repopulate the list (only every 10 minutes)\r
- if(m_lastpopulated<(now-1.0/144.0))\r
+ if(m_lastpopulated<(now-Poco::Timespan(0,0,10,0,0)))\r
{\r
PopulateIDList();\r
- m_lastpopulated.SetToGMTime();\r
+ m_lastpopulated=Poco::Timestamp();\r
}\r
}\r
}\r
// special case - if there were 0 ids on the list when we started then we will never get a chance to repopulate the list\r
// this will recheck for ids every minute\r
- if(m_ids.size()==0 && m_tempdate<(now-(1.0/1440.0)))\r
+ if(m_ids.size()==0 && m_tempdate<(now-Poco::Timespan(0,0,1,0,0)))\r
{\r
PopulateIDList();\r
m_tempdate=now;\r
}\r
// if we haven't received any messages to this object in 10 minutes, clear the requests and repopulate id list\r
- if(m_ids.size()>0 && m_lastreceived<(now-(1.0/144.0)))\r
+ if(m_ids.size()>0 && m_lastreceived<(now-Poco::Timespan(0,0,10,0,0)))\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IIndexRequester<IDTYPE>::Process "+m_fcpuniquename+" Object has not received any messages in 10 minutes. Restarting requests.");\r
+ m_log->error("IIndexRequester<IDTYPE>::Process "+m_fcpuniquename+" Object has not received any messages in 10 minutes. Restarting requests.");\r
FCPConnected();\r
}\r
\r
\r
#include "iindexinserter.h"\r
\r
-//class IntroductionPuzzleInserter:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
+#include <Poco/DateTime.h>\r
+\r
class IntroductionPuzzleInserter:public IIndexInserter<long>\r
{\r
public:\r
const bool HandlePutSuccessful(FCPMessage &message);\r
const bool HandlePutFailed(FCPMessage &message);\r
\r
- DateTime m_lastchecked;\r
+ Poco::DateTime m_lastchecked;\r
\r
};\r
\r
\r
#include "../idatabase.h"\r
#include "../ilogger.h"\r
-#include "../datetime.h"\r
#include "ifreenetregistrable.h"\r
#include "ifcpconnected.h"\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#include <Poco/DateTime.h>\r
+\r
class IntroductionPuzzleRequester:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
{\r
public:\r
const bool HandleAllData(FCPMessage &message);\r
const bool HandleGetFailed(FCPMessage &message);\r
\r
- DateTime m_tempdate;\r
+ Poco::DateTime m_tempdate;\r
std::string m_messagebase;\r
long m_maxrequests;\r
std::vector<long> m_requesting; // list of ids we are currently requesting from\r
+++ /dev/null
-#ifndef _periodicdbmaintenance_\r
-#define _periodicdbmaintenance_\r
-\r
-#include "../idatabase.h"\r
-#include "../ilogger.h"\r
-#include "../datetime.h"\r
-#include "ifreenetregistrable.h"\r
-#include "iperiodicprocessor.h"\r
-\r
-class PeriodicDBMaintenance:public IFreenetRegistrable,public IPeriodicProcessor,public IDatabase,public ILogger\r
-{\r
-public:\r
- PeriodicDBMaintenance();\r
-\r
- void Process();\r
-\r
- void RegisterWithThread(FreenetMasterThread *thread);\r
-\r
-private:\r
- void Do10MinuteMaintenance();\r
- void Do30MinuteMaintenance();\r
- void Do1HourMaintenance();\r
- void Do6HourMaintenance();\r
- void Do1DayMaintenance();\r
-\r
- DateTime m_check10mins;\r
- DateTime m_check30mins;\r
- DateTime m_check1hour;\r
- DateTime m_check6hours;\r
- DateTime m_check1day;\r
-\r
- long m_deletemessagesolderthan;\r
- \r
-};\r
-\r
-#endif // _periodicdbmaintenance_\r
\r
#include "../idatabase.h"\r
#include "../ilogger.h"\r
-#include "../datetime.h"\r
#include "ifreenetregistrable.h"\r
#include "ifcpconnected.h"\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#include <Poco/DateTime.h>\r
+\r
class TrustListInserter:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger\r
{\r
public:\r
void StartInsert(const long localidentityid, const std::string &privatekey);\r
\r
std::string m_messagebase;\r
- DateTime m_lastchecked;\r
+ Poco::DateTime m_lastchecked;\r
\r
};\r
\r
#define _unkeyedidcreatorr_\r
\r
#include "../ilogger.h"\r
-#include "../datetime.h"\r
#include "../idatabase.h"\r
#include "ifreenetregistrable.h"\r
#include "ifcpconnected.h"\r
#include "ifcpmessagehandler.h"\r
#include "iperiodicprocessor.h"\r
\r
+#include <Poco/DateTime.h>\r
+\r
\r
/**\r
\brief Looks for any unkeyed Local Identities and requests SSK keys for them\r
void CheckForUnkeyedID();\r
void SaveKeys(const long localidentityid, const std::string &publickey, const std::string &privatekey);\r
\r
- DateTime m_lastchecked;\r
+ Poco::DateTime m_lastchecked;\r
bool m_waiting;\r
};\r
\r
#define _global_\r
\r
#include <string>\r
-#include <vector>\r
-#include "pthreadwrapper/thread.h"\r
+#include <Poco/ScopedLock.h>\r
+#include <Poco/Mutex.h>\r
\r
-#define FMS_VERSION "0.2.23"\r
+#define FMS_VERSION "0.3.0"\r
\r
-// opens database and creates tables and initial inserts if necessary\r
-void SetupDB();\r
-void ConvertDB0100To0101();\r
-void ConvertDB0101To0103();\r
-void ConvertDB0103To0104();\r
-void ConvertDB0104To0105();\r
-void ConvertDB0105To0106();\r
-void ConvertDB0106To0107();\r
-void ConvertDB0107To0108();\r
-void ConvertDB0108To0109();\r
-void ConvertDB0109To0110();\r
-void ConvertDB0110To0111();\r
-void ConvertDB0111To0112();\r
-// inserts default options into the database\r
-void SetupDefaultOptions();\r
-// opens logfile and sets it up\r
-void SetupLogFile();\r
+typedef Poco::ScopedLock<Poco::FastMutex> Guard;\r
\r
std::string CreateShortIdentityName(const std::string &name, const std::string &publickey);\r
\r
-// TODO remove sometime after 0.1.17\r
-void FixCapitalBoardNames();\r
-\r
-void SigHandler(int signum);\r
-\r
-void MainFunction();\r
-void Shutdown();\r
-\r
-// needed for Windows to setup network\r
-void SetupNetwork();\r
-// cleanup network on Windows\r
-void ShutdownNetwork();\r
-\r
-extern volatile bool wantshutdown;\r
-\r
#endif // _global_\r
--- /dev/null
+#ifndef _fmshttprequesthandlerfactory_\r
+#define _fmshttprequesthandlerfactory_\r
+\r
+#include "ipagehandler.h"\r
+#include "../ipaddressacl.h"\r
+#include "../ilogger.h"\r
+\r
+#include <Poco/Net/HTTPRequestHandlerFactory.h>\r
+#include <Poco/Net/HTTPServerRequest.h>\r
+\r
+class FMSHTTPRequestHandlerFactory:public Poco::Net::HTTPRequestHandlerFactory,public ILogger\r
+{\r
+public:\r
+ FMSHTTPRequestHandlerFactory();\r
+ ~FMSHTTPRequestHandlerFactory();\r
+\r
+ Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request);\r
+\r
+private:\r
+ std::vector<IPageHandler *> m_pagehandlers;\r
+ IPAddressACL m_acl;\r
+\r
+};\r
+\r
+#endif // _fmshttprequesthandlerfactory_\r
+++ /dev/null
-#ifndef _httpdefs_\r
-#define _httpdefs_\r
-\r
-struct httpstate\r
-{\r
- char *m_indata;\r
- long m_indatalen;\r
- long m_indatapos;\r
- char *m_outdata;\r
- long m_outdatalen;\r
- long m_outdatapos;\r
-};\r
-\r
-#endif // _httpdefs_\r
#ifndef _httpthread_\r
#define _httpthread_\r
\r
-#include "../pthreadwrapper/runnable.h"\r
+#include "../threadwrapper/cancelablerunnable.h"\r
#include "../ilogger.h"\r
#include "../idatabase.h"\r
-#include "ipagehandler.h"\r
-#include "httpdefs.h"\r
\r
#include <cstdlib>\r
-#include <shttpd.h>\r
\r
-class HTTPThread:public PThread::Runnable,public ILogger, public IDatabase\r
+class HTTPThread:public CancelableRunnable,public ILogger, public IDatabase\r
{\r
public:\r
HTTPThread();\r
- ~HTTPThread();\r
\r
- void Run();\r
+ void run();\r
\r
private:\r
- static void PageCallback(shttpd_arg *arg);\r
+ //static void PageCallback(shttpd_arg *arg);\r
\r
- struct shttpd_ctx *m_ctx;\r
-\r
- std::vector<IPageHandler *> m_pagehandlers;\r
+ int m_listenport;\r
\r
};\r
\r
#ifndef _ipagehandler_\r
#define _ipagehandler_\r
\r
+#include "../ilogger.h"\r
+\r
+#include <Poco/Net/HTTPRequestHandler.h>\r
+#include <Poco/Net/HTTPServerRequest.h>\r
+#include <Poco/Net/HTTPServerResponse.h>\r
+\r
#include <cstdlib>\r
#include <string>\r
#include <map>\r
#include <vector>\r
-#include <shttpd.h>\r
\r
-class IPageHandler\r
+class IPageHandler:public Poco::Net::HTTPRequestHandler,public ILogger\r
{\r
public:\r
IPageHandler() {}\r
IPageHandler(const std::string &templatestr) { m_template=templatestr; }\r
virtual ~IPageHandler() {}\r
+ virtual const bool WillHandleURI(const std::string &uri)=0;\r
+\r
+ virtual IPageHandler *New()=0; // returns a new instance of the object\r
\r
- /**\r
- \brief Handles request for a page\r
- \r
- \return true if request was handled, false if it was ignored\r
- */\r
- const bool Handle(shttpd_arg *arg);\r
+ virtual void handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response);\r
\r
private:\r
- virtual const bool WillHandleURI(const std::string &uri)=0;\r
virtual const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)=0;\r
- \r
+\r
protected:\r
- // splits apart data into name,data pairs in args map\r
- void HandleMultiPartData(const std::string &contenttypeheader, char *data, const long datalen, std::map<std::string,std::string> &args);\r
// converts from basename[#] query args into a vector where the vector pos is the index pos #\r
void CreateArgArray(const std::map<std::string,std::string> &vars, const std::string &basename, std::vector<std::string> &args);\r
const std::string CreateTrueFalseDropDown(const std::string &name, const std::string &selected);\r
\r
- // replaces html control characters with elements (i.e. < becomes <)\r
+ void CreateQueryVarMap(Poco::Net::HTTPServerRequest &request, std::map<std::string,std::string> &vars);\r
+\r
+ // replaces html elements with encoded characters (i.e. < becomes <)\r
const std::string SanitizeOutput(const std::string &input);\r
\r
std::string m_template;\r
--- /dev/null
+#ifndef _multipartparser_\r
+#define _multipartparser_\r
+\r
+#include <Poco/Net/PartHandler.h>\r
+#include <map>\r
+#include <string>\r
+\r
+class MultiPartParser:public Poco::Net::PartHandler\r
+{\r
+public:\r
+ void handlePart(const Poco::Net::MessageHeader &header, std::istream &stream);\r
+\r
+ std::map<std::string,std::string> GetVars() { return vars; }\r
+\r
+private:\r
+ std::map<std::string,std::string> vars;\r
+};\r
+\r
+#endif // _multipartparser_\r
public:\r
AddPeerPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new AddPeerPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
AnnounceIdentityPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new AnnounceIdentityPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
BoardsPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new BoardsPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
ConfirmPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new ConfirmPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
ControlBoardPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new ControlBoardPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
CreateIdentityPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new CreateIdentityPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
ExecQueryPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new ExecQueryPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
HomePage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new HomePage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
InsertedFilesPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new InsertedFilesPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
{\r
public:\r
LocalIdentitiesPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
+\r
+ IPageHandler *New() { return new LocalIdentitiesPage(m_template); }\r
+\r
+ void handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response);\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
\r
+ void HandleUpdate(const std::map<std::string,std::string> &queryvars);\r
+ void HandleDelete(const std::map<std::string,std::string> &queryvars);\r
+ void HandleImport(const std::map<std::string,std::string> &queryvars);\r
+ const std::string HandleExport();\r
+\r
};\r
\r
#endif // _localidentitiespage_\r
public:\r
OptionsPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new OptionsPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
PeerDetailsPage(const std::string templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new PeerDetailsPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
PeerMaintenancePage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new PeerMaintenancePage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
public:\r
PeerTrustPage(const std::string &templatestr):IPageHandler(templatestr) {}\r
\r
+ IPageHandler *New() { return new PeerTrustPage(m_template); }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
{\r
public:\r
\r
+ void handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response);\r
+\r
+ IPageHandler *New() { return new ShowCaptchaPage; }\r
+\r
private:\r
const bool WillHandleURI(const std::string &uri);\r
- const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars);\r
+ const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars) {return "";}\r
\r
};\r
\r
#ifndef _ifmsxmldocument_\r
#define _ifmsxmldocument_\r
\r
+#include <Poco/DOM/Document.h>\r
+#include <Poco/DOM/Element.h>\r
+#include <Poco/DOM/Text.h>\r
+#include <Poco/DOM/CDATASection.h>\r
+#include <Poco/DOM/DOMParser.h>\r
+#include <Poco/DOM/DOMWriter.h>\r
+#include <Poco/XML/XMLWriter.h>\r
+#include <Poco/AutoPtr.h>\r
+\r
#include "stringfunctions.h"\r
\r
#include <string>\r
-#include <tinyxml.h>\r
\r
#ifdef XMEM\r
#include <xmem.h>\r
\r
protected:\r
/**\r
+ Poco doesn't like CDATA with whitespace outside the tags\r
+ This will remove the whitespace from around CDATA tags\r
+ */\r
+ virtual const std::string FixCDATA(const std::string &xmlstr)\r
+ {\r
+ std::string rstring=xmlstr;\r
+ std::string::size_type beg1=std::string::npos;\r
+ std::string::size_type end1=rstring.find("<![CDATA[");\r
+ std::string::size_type beg2=std::string::npos;\r
+ std::string::size_type end2=std::string::npos;\r
+\r
+ while(end1!=std::string::npos)\r
+ {\r
+ beg1=rstring.rfind(">",end1);\r
+ if(beg1!=end1-1)\r
+ {\r
+ rstring.erase(beg1+1,end1-(beg1+1));\r
+ }\r
+\r
+ beg2=rstring.find("]]>",end1);\r
+ if(beg2!=std::string::npos)\r
+ {\r
+ end2=rstring.find("<",beg2);\r
+ if(end2!=std::string::npos)\r
+ {\r
+ rstring.erase(beg2+3,end2-(beg2+3));\r
+ }\r
+ }\r
+\r
+ end1=rstring.find("<![CDATA[",end1+1);\r
+ }\r
+ return rstring;\r
+ }\r
+ /**\r
\brief Creates and returns an element with a boolean value\r
*/\r
- virtual TiXmlElement *XMLCreateBooleanElement(const std::string &name, const bool value)\r
+ virtual Poco::XML::Element *XMLCreateBooleanElement(Poco::XML::Document *doc, const std::string &name, const bool value)\r
{\r
- TiXmlText *txt=new TiXmlText(value ? "true" : "false");\r
- TiXmlElement *el=new TiXmlElement(name);\r
- el->LinkEndChild(txt);\r
- return el;\r
+ if(doc)\r
+ {\r
+ Poco::XML::Text *txt=doc->createTextNode(value ? "true" : "false");\r
+ Poco::XML::Element *el=doc->createElement(name);\r
+ el->appendChild(txt);\r
+ return el;\r
+ }\r
+ else\r
+ {\r
+ return NULL;\r
+ }\r
}\r
\r
/**\r
\brief Creates and returns an element with a CDATA value\r
*/\r
- virtual TiXmlElement *XMLCreateCDATAElement(const std::string &name, const std::string &data)\r
+ virtual Poco::XML::Element *XMLCreateCDATAElement(Poco::XML::Document *doc, const std::string &name, const std::string &data)\r
{\r
- TiXmlText *txt=new TiXmlText(data);\r
- txt->SetCDATA(true);\r
- TiXmlElement *el=new TiXmlElement(name);\r
- el->LinkEndChild(txt);\r
- return el;\r
+ if(doc)\r
+ {\r
+ // Poco XML won't break up CDATA sections correctly when assigned a string with the \r
+ // end tag is present. However, it will parse it correctly, so we will manually break the\r
+ // CDATA into separate parts\r
+ Poco::XML::CDATASection *sec=doc->createCDATASection(StringFunctions::Replace(data,"]]>","]]]><![CDATA[]>"));\r
+ Poco::XML::Element *el=doc->createElement(name);\r
+ el->appendChild(sec);\r
+ return el;\r
+ }\r
+ else\r
+ {\r
+ return NULL;\r
+ }\r
}\r
\r
/**\r
\brief Creates and returns a text element\r
*/\r
- virtual TiXmlElement *XMLCreateTextElement(const std::string &name, const std::string &data)\r
+ virtual Poco::XML::Element *XMLCreateTextElement(Poco::XML::Document *doc, const std::string &name, const std::string &data)\r
{\r
- TiXmlText *txt=new TiXmlText(data);\r
- TiXmlElement *el=new TiXmlElement(name);\r
- el->LinkEndChild(txt);\r
- return el;\r
+ if(doc)\r
+ {\r
+ Poco::XML::Text *txt=doc->createTextNode(data);\r
+ Poco::XML::Element *el=doc->createElement(name);\r
+ el->appendChild(txt);\r
+ return el;\r
+ }\r
+ else\r
+ {\r
+ return NULL;\r
+ }\r
}\r
\r
- virtual TiXmlElement *XMLCreateTextElement(const std::string &name, const long data)\r
+ virtual Poco::XML::Element *XMLCreateTextElement(Poco::XML::Document *doc, const std::string &name, const long data)\r
{\r
- std::string datastr;\r
- StringFunctions::Convert(data,datastr);\r
- return XMLCreateTextElement(name,datastr);\r
+ if(doc)\r
+ {\r
+ std::string datastr;\r
+ StringFunctions::Convert(data,datastr);\r
+ return XMLCreateTextElement(doc,name,datastr);\r
+ }\r
+ else\r
+ {\r
+ return NULL;\r
+ }\r
}\r
\r
- virtual const bool XMLGetBooleanElement(TiXmlElement *parent, const std::string &name)\r
+ virtual const bool XMLGetBooleanElement(Poco::XML::Element *parent, const std::string &name)\r
{\r
- TiXmlHandle hnd(parent);\r
- TiXmlText *txt=hnd.FirstChild(name).FirstChild().ToText();\r
- if(txt)\r
+ Poco::XML::Element *el=XMLGetFirstChild(parent,name);\r
+ if(el && el->firstChild())\r
{\r
- if(txt->ValueStr()=="true")\r
+ if(el->firstChild()->getNodeValue()=="true")\r
{\r
return true;\r
}\r
return false;\r
}\r
\r
+ virtual Poco::XML::Element *XMLGetFirstChild(Poco::XML::Node *parent, const std::string &name)\r
+ {\r
+ if(parent)\r
+ {\r
+ Poco::XML::Node *child=parent->firstChild();\r
+ while(child && child->nodeName()!=name)\r
+ {\r
+ child=child->nextSibling();\r
+ }\r
+ return static_cast<Poco::XML::Element *>(child);\r
+ }\r
+ else\r
+ {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ virtual Poco::XML::Element *XMLGetNextSibling(Poco::XML::Node *node, const std::string &name)\r
+ {\r
+ if(node)\r
+ {\r
+ Poco::XML::Node *next=node->nextSibling();\r
+ while(next && next->nodeName()!=name)\r
+ {\r
+ next=next->nextSibling();\r
+ }\r
+ return static_cast<Poco::XML::Element *>(next);\r
+ }\r
+ else\r
+ {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
const std::string SanitizeSingleString(const std::string &text)\r
{\r
std::string returntext=text;\r
}\r
return returntext;\r
}\r
+\r
+ const std::string GenerateXML(Poco::XML::Document *doc)\r
+ {\r
+ std::ostringstream str;\r
+ if(doc)\r
+ {\r
+ Poco::XML::DOMWriter dr;\r
+ dr.setOptions(Poco::XML::XMLWriter::WRITE_XML_DECLARATION | Poco::XML::XMLWriter::PRETTY_PRINT);\r
+ dr.setNewLine(Poco::XML::XMLWriter::NEWLINE_CRLF);\r
+ dr.writeNode(str,doc);\r
+ }\r
+ return str.str();\r
+ }\r
\r
};\r
\r
#ifndef _ilogger_\r
#define _ilogger_\r
\r
-#include "logfile.h"\r
+#include <Poco/Util/ServerApplication.h>\r
+#include <Poco/LogFile.h>\r
\r
/**\r
\brief Base class for classes that want to use the singleton LogFile object\r
class ILogger\r
{\r
public:\r
- ILogger():m_log(LogFile::Instance()) {}\r
+ ILogger():m_log(&Poco::Util::ServerApplication::instance().logger()) {}\r
\r
protected:\r
- LogFile *m_log;\r
+ Poco::Logger *m_log;\r
};\r
\r
#endif // _ilogger_\r
--- /dev/null
+#ifndef _ipaddressacl_\r
+#define _ipaddressacl_\r
+\r
+#include <Poco/Net/IPAddress.h>\r
+#include <vector>\r
+#include <string>\r
+\r
+class IPAddressACL\r
+{\r
+public:\r
+ IPAddressACL();\r
+\r
+ const bool IsAllowed(const Poco::Net::IPAddress &addr);\r
+ const bool IsAllowed(const std::string &addrstr);\r
+\r
+ const bool Add(const std::string &aclentry);\r
+\r
+ void SetAllowByDefault(const bool allowbydefault) { m_allowbydefault=allowbydefault; }\r
+ const bool GetAllowByDefault() const { return m_allowbydefault; }\r
+\r
+private:\r
+ const std::string CreateMask(const int maskbits);\r
+\r
+ // Poco 1.3.0 + has Poco::Net::IPAddress::mask - but 1.2.9 does not\r
+ Poco::Net::IPAddress MaskAddress(const Poco::Net::IPAddress &addr, const Poco::Net::IPAddress &mask);\r
+\r
+ struct entry\r
+ {\r
+ entry(const bool allow, const Poco::Net::IPAddress &mask, const Poco::Net::IPAddress &addr):m_allow(allow),m_mask(mask),m_addr(addr) {}\r
+ bool m_allow;\r
+ Poco::Net::IPAddress m_mask;\r
+ Poco::Net::IPAddress m_addr;\r
+ };\r
+\r
+ bool m_allowbydefault; // allow or deny hosts if not explicitly defined\r
+\r
+ std::vector<entry> m_entries;\r
+\r
+};\r
+\r
+#endif // _acl_\r
+++ /dev/null
-#ifndef _logfile_\r
-#define _logfile_\r
-\r
-//#include <zthread/Singleton.h>\r
-//#include <zthread/Mutex.h>\r
-#include "pthreadwrapper/mutex.h"\r
-#include <string>\r
-#include "pthreadwrapper/singleton.h"\r
-\r
-class LogFile:public PThread::Singleton<LogFile>\r
-{\r
-public:\r
- LogFile();\r
- LogFile(const std::string &filename);\r
- ~LogFile();\r
-\r
- enum LogLevel\r
- {\r
- LOGLEVEL_FATAL=0,\r
- LOGLEVEL_ERROR=1,\r
- LOGLEVEL_WARNING=2,\r
- LOGLEVEL_INFO=3,\r
- LOGLEVEL_DEBUG=4\r
- };\r
- \r
- bool OpenFile();\r
- bool CloseFile();\r
- \r
- std::string GetFileName() { return m_filename; }\r
- void SetFileName(std::string filename) { m_filename=filename; }\r
- \r
- const bool GetWriteDate() { return m_writedate; }\r
- void SetWriteDate(const bool writedate) { m_writedate=writedate; }\r
- \r
- const bool GetWriteLogLevel() { return m_writeloglevel; }\r
- void SetWriteLogLevel(const bool writeloglevel) { m_writeloglevel=writeloglevel; }\r
- \r
- const LogLevel GetLogLevel() { return m_loglevel; }\r
- void SetLogLevel(const LogLevel loglevel) { m_loglevel=loglevel; }\r
-\r
- const bool GetWriteNewLine() { return m_writenewline; }\r
- void SetWriteNewLine(const bool writenewline) { m_writenewline=writenewline; }\r
- \r
- void WriteLog(const char *format, ...);\r
- void WriteLog(const std::string &text);\r
- void WriteLog(const LogLevel level, const char *format, ...);\r
- void WriteLog(const LogLevel level, const std::string &text);\r
-\r
- void WriteNewLine();\r
- \r
-private:\r
- void WriteDate();\r
- void WriteLogLevel(LogLevel level);\r
-\r
- FILE *m_fileptr;\r
- std::string m_filename;\r
- LogLevel m_loglevel;\r
- bool m_writedate;\r
- bool m_writeloglevel;\r
- bool m_writenewline;\r
- char *m_datebuffer;\r
-\r
- PThread::Mutex m_logmutex;\r
- \r
-};\r
-\r
-#endif // _logfile_\r
\r
#include "idatabase.h"\r
#include "ilogger.h"\r
-#include "datetime.h"\r
+\r
+#include <Poco/DateTime.h>\r
\r
class Message:public IDatabase,public ILogger\r
{\r
const std::string GetSubject() const { return m_subject; }\r
const std::string GetBody() const { return m_body; }\r
const std::string GetReplyBoardName() { return m_replyboardname; }\r
- const DateTime GetDateTime() const { return m_datetime; }\r
+ const Poco::DateTime GetDateTime() const { return m_datetime; }\r
const std::string GetFromName() const { return m_fromname; }\r
std::vector<std::string> GetBoards() const { return m_boards; }\r
std::map<long,std::string> GetInReplyTo() const { return m_inreplyto; }\r
std::string m_subject;\r
std::string m_body;\r
std::string m_replyboardname;\r
- DateTime m_datetime;\r
+ Poco::DateTime m_datetime;\r
std::string m_fromname;\r
std::vector<std::string> m_boards;\r
std::map<long,std::string> m_inreplyto;\r
#ifndef _nntpconnection_\r
#define _nntpconnection_\r
\r
+#include "../threadwrapper/cancelablerunnable.h"\r
#include "../socketdefines.h"\r
#include "../ilogger.h"\r
#include "../message.h"\r
\r
#include <string>\r
#include <vector>\r
-//#include <zthread/Runnable.h>\r
-#include "../pthreadwrapper/runnable.h"\r
\r
#ifdef _WIN32\r
\r
#include <arpa/inet.h>\r
#endif\r
\r
-class NNTPConnection:public PThread::Runnable,public ILogger\r
+class NNTPConnection:public CancelableRunnable,public ILogger\r
{\r
public:\r
NNTPConnection(SOCKET sock);\r
void Disconnect();\r
const bool Disconnected() { return m_socket==INVALID_SOCKET; }\r
\r
- void Run();\r
+ void run();\r
\r
private:\r
\r
\r
#include <list>\r
#include <vector>\r
-//#include <zthread/Thread.h>\r
-//#include <zthread/Task.h>\r
-//#include <zthread/ZThread.h>\r
-//#include <zthread/ThreadedExecutor.h>\r
-#include "../pthreadwrapper/runnable.h"\r
-#include "../pthreadwrapper/threadedexecutor.h"\r
-\r
+#include "../threadwrapper/threadedexecutor.h"\r
#include "../socketdefines.h"\r
+#include "../ilogger.h"\r
\r
/**\r
\brief Listens for NNTP connections\r
*/\r
-class NNTPListener:public PThread::Runnable\r
+class NNTPListener:public CancelableRunnable,public ILogger\r
{\r
public:\r
NNTPListener();\r
~NNTPListener();\r
\r
- void Run();\r
+ void run();\r
void StartListen();\r
\r
private:\r
\r
unsigned short m_listenport;\r
std::vector<SOCKET> m_listensockets;\r
- //ZThread::ThreadedExecutor m_connections;\r
- //std::vector<PThread::Thread *> m_connectionthreads;\r
- PThread::ThreadedExecutor m_connections;\r
+\r
+ ThreadedExecutor m_connections;\r
\r
};\r
\r
#include "db/sqlite3db.h"\r
\r
#include <sstream>\r
-//#include <zthread/Singleton.h>\r
-#include "pthreadwrapper/singleton.h"\r
+#include "threadwrapper/singleton.h"\r
\r
//just a wrapper around the database for the options table\r
-class Option:public PThread::Singleton<Option>\r
+class Option:public Singleton<Option>\r
{\r
public:\r
const bool Get(const std::string &option, std::string &value);\r
--- /dev/null
+#ifndef _optionssetup_\r
+#define _optionssetup_\r
+\r
+// inserts default options into the database\r
+void SetupDefaultOptions();\r
+\r
+#endif // _optionssetup_\r
+++ /dev/null
-/**\r
- Light C++ wrapper around PThreads\r
-*/\r
-\r
-#ifndef _pthread_wrapper_\r
-\r
-#include <pthread.h>\r
-\r
-namespace PThread\r
-{\r
-\r
- // forward declarations\r
- class NonCopyable;\r
- class Mutex;\r
- class Guard;\r
- class Runnable;\r
- class Thread;\r
- class ThreadedExecutor;\r
-\r
-} // namespace\r
-\r
-#include "pthreadwrapper/noncopyable.h"\r
-#include "pthreadwrapper/mutex.h"\r
-#include "pthreadwrapper/guard.h"\r
-#include "pthreadwrapper/runnable.h"\r
-#include "pthreadwrapper/thread.h"\r
-#include "pthreadwrapper/threadedexecutor.h"\r
-#include "pthreadwrapper/singleton.h"\r
-\r
-#endif // _pthread_wrapper_\r
+++ /dev/null
-#ifndef _pthread_wrapper_\r
-#define _pthread_wrapper_\r
-\r
-#include <exception>\r
-\r
-namespace PThread\r
-{\r
- \r
-class DeadlockException:public std::exception\r
-{\r
-public:\r
- const char *what() const throw() { return "Deadlock Exception"; }\r
-};\r
- \r
-} // namespace\r
-\r
-#endif // _pthread_wrapper_\r
+++ /dev/null
-#ifndef _pthread_guard_\r
-#define _pthread_guard_\r
-\r
-namespace PThread\r
-{\r
-\r
-class Mutex;\r
-\r
-class Guard\r
-{\r
-public:\r
- Guard();\r
- Guard(Mutex &mutex);\r
- ~Guard();\r
-private:\r
- Mutex *m_mutex;\r
-};\r
-\r
-} // namespace\r
-\r
-#endif // _pthread_guard_\r
+++ /dev/null
-#ifndef _pthread_mutex_\r
-#define _pthread_mutex_\r
-\r
-#include <pthread.h>\r
-#include "deadlockexception.h"\r
-\r
-namespace PThread\r
-{\r
-\r
-class Mutex\r
-{\r
-public:\r
- Mutex();\r
- ~Mutex();\r
-\r
- void Acquire() throw(std::exception);\r
- void Release();\r
-\r
-private:\r
- pthread_mutex_t m_mutex;\r
- pthread_mutexattr_t m_attr;\r
-};\r
-\r
-} // namespace\r
-\r
-#endif // _pthread_mutex_\r
+++ /dev/null
-#ifndef _pthread_noncopyable_\r
-#define _pthread_noncopyable_\r
-\r
-namespace PThread\r
-{\r
-\r
-class NonCopyable\r
-{\r
-protected:\r
- NonCopyable() {}\r
- virtual ~NonCopyable() {}\r
-\r
-private:\r
- // restrict copy and assignment\r
- NonCopyable(const NonCopyable &rhs);\r
- const NonCopyable &operator=(const NonCopyable &rhs);\r
-};\r
- \r
-} // namespace\r
-\r
-#endif // _pthread_noncopyable_\r
+++ /dev/null
-#ifndef _pthread_runnable_\r
-#define _pthread_runnable_\r
-\r
-#include "thread.h"\r
-\r
-namespace PThread\r
-{\r
-\r
-class Thread;\r
-\r
-class Runnable\r
-{\r
-public:\r
- Runnable():m_thread(0) {}\r
- virtual ~Runnable() {}\r
-\r
- virtual void Run()=0;\r
-\r
-protected:\r
- void Sleep(const long ms);\r
- const bool IsCancelled();\r
-\r
-private:\r
-\r
- friend class Thread;\r
- Thread *m_thread;\r
-\r
-};\r
-\r
-} // namespace\r
-\r
-#endif // _pthread_runnable_\r
+++ /dev/null
-#ifndef _pthread_singleton_\r
-#define _pthread_singleton_\r
-\r
-#include "noncopyable.h"\r
-#include "guard.h"\r
-\r
-#include <cassert>\r
-\r
-namespace PThread\r
-{\r
-\r
-//! SingletonDestroyer\r
-template <class T>\r
-class Destroyer {\r
- \r
- T* doomed;\r
- \r
- public:\r
- \r
- Destroyer(T* q) : doomed(q) {\r
- assert(doomed);\r
- }\r
- \r
- ~Destroyer();\r
-\r
-};\r
-\r
-template <class T>\r
-Destroyer<T>::~Destroyer() {\r
- \r
- try {\r
- \r
- if(doomed)\r
- delete doomed;\r
- \r
- } catch(...) { }\r
- \r
- doomed = 0;\r
- \r
-} \r
-\r
-template <class T>\r
-class Singleton:public NonCopyable\r
-{\r
-public:\r
-\r
- static T *Instance();\r
-\r
-private:\r
- \r
-};\r
-\r
-template <class T>\r
-T *Singleton<T>::Instance()\r
-{\r
- static T *obj=0;\r
- static Mutex mutex;\r
- Guard g(mutex);\r
- if(obj==0)\r
- {\r
- obj=new T();\r
- static Destroyer<T> des(obj);\r
- }\r
- return const_cast<T*>(obj);\r
-}\r
-\r
-} // namespace\r
-\r
-#endif // _pthread_singleton_\r
+++ /dev/null
-#ifndef _pthread_thread_\r
-#define _pthread_thread_\r
-\r
-#include "noncopyable.h"\r
-#include "runnable.h"\r
-#include <pthread.h>\r
-\r
-namespace PThread\r
-{\r
-\r
-void Sleep(const long ms);\r
-\r
-class Runnable;\r
-\r
-class Thread:public NonCopyable\r
-{\r
-public:\r
- Thread();\r
- Thread(Runnable *runnable);\r
- ~Thread();\r
-\r
- void Join();\r
- void Cancel();\r
-\r
- void Sleep(const long ms);\r
- const bool IsCancelled() { return m_cancelled; }\r
- const bool IsRunning() { return m_running; }\r
-\r
-private:\r
- void Start();\r
- static void *EntryPoint(void *pthis);\r
-\r
- pthread_t m_thread;\r
- int m_threadnum;\r
- bool m_running; // thread (object) is currently running\r
- bool m_cancelled;\r
- Runnable *m_runnable; // actual object that is being run\r
- bool m_threadcleaned;\r
-\r
-};\r
-\r
-} // namespace\r
-\r
-#endif // _pthread_thread_\r
+++ /dev/null
-#ifndef _pthread_threadedexecutor_\r
-#define _pthread_threadedexecutor_\r
-\r
-#include "noncopyable.h"\r
-#include "runnable.h"\r
-#include <vector>\r
-\r
-namespace PThread\r
-{\r
-\r
-class ThreadedExecutor:public NonCopyable\r
-{\r
-public:\r
- ThreadedExecutor() {}\r
- ~ThreadedExecutor();\r
-\r
- void Execute(Runnable *runnable);\r
- \r
- void Join();\r
- void Cancel();\r
-\r
-private:\r
- void CleanupFinished();\r
- \r
- std::vector<Thread *> m_threads;\r
-};\r
-\r
-}\r
-\r
-#endif // _pthread_threadedexecutor_\r
+++ /dev/null
-#ifndef _threadcontroller_\r
-#define _threadcontroller_\r
-\r
-#include "ilogger.h"\r
-#include "pthreadwrapper/thread.h"\r
-#include "pthreadwrapper/singleton.h"\r
-\r
-class ThreadController:public PThread::Singleton<ThreadController>,public ILogger\r
-{\r
-public:\r
- ThreadController():m_freenetthread(NULL),m_httpthread(NULL),m_nntpthread(NULL) {}\r
- ~ThreadController();\r
-\r
- void StartThreads();\r
- void ShutdownThreads();\r
- void RestartThreads();\r
-\r
- void StartFreenetThread();\r
- void StartHTTPThread();\r
- void StartNNTPThread();\r
-\r
- void ShutdownFreenetThread();\r
- void ShutdownHTTPThread();\r
- void ShutdownNNTPThread();\r
-\r
-private:\r
- void ReadConfig();\r
-\r
- bool m_startfreenet;\r
- bool m_starthttp;\r
- bool m_startnntp;\r
-\r
- PThread::Thread *m_freenetthread;\r
- PThread::Thread *m_httpthread;\r
- PThread::Thread *m_nntpthread;\r
-\r
-};\r
-\r
-#endif // _threadcontroller_\r
--- /dev/null
+#ifndef _cancelablerunnable_\r
+#define _cancelablerunnable_\r
+\r
+#include <Poco/Runnable.h>\r
+#include <Poco/Mutex.h>\r
+\r
+class CancelableRunnable:public Poco::Runnable\r
+{\r
+public:\r
+ CancelableRunnable():m_cancelled(false) {}\r
+\r
+ void Cancel() { Poco::ScopedLock<Poco::FastMutex> g(m_cancelledmutex); m_cancelled=true; }\r
+ const bool IsCancelled() { Poco::ScopedLock<Poco::FastMutex> g(m_cancelledmutex); return m_cancelled; }\r
+\r
+private:\r
+\r
+ Poco::FastMutex m_cancelledmutex;\r
+ bool m_cancelled;\r
+\r
+};\r
+\r
+#endif // _cancelablerunnable_\r
--- /dev/null
+#ifndef _cancelablethread_\r
+#define _cancelablethread_\r
+\r
+#include "cancelablerunnable.h"\r
+\r
+#include <Poco/Thread.h>\r
+\r
+class CancelableThread:public Poco::Thread\r
+{\r
+public:\r
+ CancelableThread():m_runnable(0) {}\r
+ CancelableThread(CancelableRunnable *runnable):m_runnable(runnable) { start(*runnable); }\r
+ ~CancelableThread()\r
+ {\r
+ if(m_runnable)\r
+ {\r
+ delete m_runnable;\r
+ }\r
+ }\r
+\r
+ // CancelableThread takes ownership of runnable and will destroy it in the destructor\r
+ void Start(CancelableRunnable *runnable) { m_runnable=runnable; start(*runnable); }\r
+\r
+ void Cancel() { if(m_runnable) { m_runnable->Cancel(); } }\r
+ const bool IsCancelled() { return m_runnable ? m_runnable->IsCancelled() : false; }\r
+\r
+private:\r
+\r
+ CancelableRunnable *m_runnable;\r
+\r
+};\r
+\r
+#endif // _cancelablethread_\r
--- /dev/null
+#ifndef _noncopyable_\r
+#define _noncopyable_\r
+\r
+class NonCopyable\r
+{\r
+protected:\r
+ NonCopyable() {}\r
+ virtual ~NonCopyable() {}\r
+\r
+private:\r
+ // restrict copy and assignment\r
+ NonCopyable(const NonCopyable &rhs);\r
+ const NonCopyable &operator=(const NonCopyable &rhs);\r
+};\r
+\r
+#endif // _noncopyable_\r
--- /dev/null
+#ifndef _singleton_\r
+#define _singleton_\r
+\r
+#include <cassert>\r
+\r
+#include "noncopyable.h"\r
+\r
+//! SingletonDestroyer\r
+template <class T>\r
+class Destroyer\r
+{\r
+ T* doomed;\r
+ public:\r
+ \r
+ Destroyer(T* q) : doomed(q) { assert(doomed); }\r
+ ~Destroyer();\r
+};\r
+\r
+template <class T>\r
+Destroyer<T>::~Destroyer()\r
+{\r
+ try\r
+ {\r
+ if(doomed)\r
+ {\r
+ delete doomed;\r
+ }\r
+ }\r
+ catch(...)\r
+ {\r
+ }\r
+ \r
+ doomed = 0;\r
+}\r
+\r
+template <class T>\r
+class Singleton:public NonCopyable\r
+{\r
+public:\r
+\r
+ static T *Instance();\r
+\r
+private:\r
+ \r
+};\r
+\r
+template <class T>\r
+T *Singleton<T>::Instance()\r
+{\r
+ static T *obj=0;\r
+ static Poco::FastMutex mutex;\r
+ Poco::ScopedLock<Poco::FastMutex> g(mutex);\r
+ if(obj==0)\r
+ {\r
+ obj=new T();\r
+ static Destroyer<T> des(obj);\r
+ }\r
+ return const_cast<T*>(obj);\r
+}\r
+\r
+#endif // _singleton_\r
--- /dev/null
+#ifndef _threadedexecutor_\r
+#define _threadedexecutor_\r
+\r
+#include "cancelablerunnable.h"\r
+#include "cancelablethread.h"\r
+\r
+#include <vector>\r
+\r
+class ThreadedExecutor\r
+{\r
+public:\r
+ ~ThreadedExecutor();\r
+\r
+ void Start(CancelableRunnable *runnable);\r
+\r
+ void Join();\r
+ void Cancel();\r
+\r
+private:\r
+ void CleanupCompleted();\r
+\r
+ std::vector<CancelableThread *> m_threads;\r
+};\r
+\r
+#endif // _threadedexecutor_\r
+++ /dev/null
-#ifndef _uuidgenerator_\r
-#define _uuidgenerator_\r
-\r
-#include <string>\r
-\r
-/**\r
- \brief UUID v4 (based on random numbers)\r
-\r
- reference : http://lists.evolt.org/pipermail/javascript/2006-July/010716.html\r
-*/\r
-class UUIDGenerator\r
-{\r
-public:\r
-\r
- const std::string Generate();\r
-\r
-private:\r
-\r
- const std::string RandHex(const int len);\r
-\r
-};\r
-\r
-#endif // _uuidgenerator_\r
+++ /dev/null
-/**\r
- * \file config.h\r
- *\r
- * This set of compile-time options may be used to enable\r
- * or disable features selectively, and reduce the global\r
- * memory footprint.\r
- */\r
-#ifndef XYSSL_CONFIG_H\r
-#define XYSSL_CONFIG_H\r
-\r
-#ifndef _CRT_SECURE_NO_DEPRECATE\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-#endif\r
-\r
-/*\r
- * Uncomment if native integers are 8-bit wide.\r
- *\r
-#define XYSSL_HAVE_INT8\r
- */\r
-\r
-/*\r
- * Uncomment if native integers are 16-bit wide.\r
- *\r
-#define XYSSL_HAVE_INT16\r
- */\r
-\r
-/*\r
- * Uncomment if the compiler supports long long.\r
- *\r
-#define XYSSL_HAVE_LONGLONG\r
- */\r
-\r
-/*\r
- * Uncomment if the CPU supports SSE2 (IA-32 specific).\r
- *\r
-#define XYSSL_HAVE_SSE2\r
- */\r
-\r
-/*\r
- * Enable all SSL/TLS debugging messages.\r
- */\r
-#define XYSSL_DEBUG_MSG\r
-\r
-/*\r
- * Enable the checkup functions (*_self_test).\r
- *\r
-#define XYSSL_SELF_TEST\r
- */\r
-\r
-/*\r
- * Enable the prime-number generation code.\r
- */\r
-#define XYSSL_GENPRIME\r
-\r
-/*\r
- * Uncomment this macro to store the AES tables in ROM.\r
- *\r
-#define XYSSL_AES_ROM_TABLES\r
- */\r
-\r
-/*\r
- * Module: library/aes.c\r
- * Caller: library/ssl_tls.c\r
- *\r
- * This module enables the following ciphersuites:\r
- * SSL_RSA_AES_256_SHA\r
- * SSL_EDH_RSA_AES_256_SHA\r
- */\r
-#define XYSSL_AES_C\r
-\r
-/*\r
- * Module: library/arc4.c\r
- * Caller: library/ssl_tls.c\r
- *\r
- * This module enables the following ciphersuites:\r
- * SSL_RSA_RC4_128_MD5\r
- * SSL_RSA_RC4_128_SHA\r
- */\r
-#define XYSSL_ARC4_C\r
-\r
-/*\r
- * Module: library/base64.c\r
- * Caller: library/x509parse.c\r
- *\r
- * This module is required for X.509 support.\r
- */\r
-#define XYSSL_BASE64_C\r
-\r
-/*\r
- * Module: library/bignum.c\r
- * Caller: library/dhm.c\r
- * library/rsa.c\r
- * library/ssl_tls.c\r
- * library/x509parse.c\r
- *\r
- * This module is required for RSA and DHM support.\r
- */\r
-#define XYSSL_BIGNUM_C\r
-\r
-/*\r
- * Module: library/certs.c\r
- * Caller:\r
- *\r
- * This module is used for testing (ssl_client/server).\r
- */\r
-#define XYSSL_CERTS_C\r
-\r
-/*\r
- * Module: library/debug.c\r
- * Caller: library/ssl_cli.c\r
- * library/ssl_srv.c\r
- * library/ssl_tls.c\r
- *\r
- * This module provides debugging functions.\r
- *\r
-#define XYSSL_DEBUG_C\r
- */\r
-\r
-/*\r
- * Module: library/des.c\r
- * Caller: library/ssl_tls.c\r
- *\r
- * This module enables the following ciphersuites:\r
- * SSL_RSA_DES_168_SHA\r
- * SSL_EDH_RSA_DES_168_SHA\r
- */\r
-#define XYSSL_DES_C\r
-\r
-/*\r
- * Module: library/dhm.c\r
- * Caller: library/ssl_cli.c\r
- * library/ssl_srv.c\r
- *\r
- * This module enables the following ciphersuites:\r
- * SSL_EDH_RSA_DES_168_SHA\r
- * SSL_EDH_RSA_AES_256_SHA\r
- */\r
-#define XYSSL_DHM_C\r
-\r
-/*\r
- * Module: library/havege.c\r
- * Caller:\r
- *\r
- * This module enables the HAVEGE random number generator.\r
- */\r
-#define XYSSL_HAVEGE_C\r
-\r
-/*\r
- * Module: library/md2.c\r
- * Caller: library/x509parse.c\r
- *\r
- * This module enables support for MD2-signed X.509 certificates.\r
- */\r
-#define XYSSL_MD2_C\r
-\r
-/*\r
- * Module: library/md4.c\r
- * Caller: library/x509parse.c\r
- *\r
- * This module enables support for MD4-signed X.509 certificates.\r
- */\r
-#define XYSSL_MD4_C\r
-\r
-/*\r
- * Module: library/md5.c\r
- * Caller: library/ssl_tls.c\r
- * library/x509parse.c\r
- *\r
- * This module is required for SSL/TLS and X.509.\r
- */\r
-#define XYSSL_MD5_C\r
-\r
-/*\r
- * Module: library/net.c\r
- * Caller:\r
- *\r
- * This module provides TCP/IP networking routines.\r
- */\r
-#define XYSSL_NET_C\r
-\r
-/*\r
- * Module: library/padlock.c\r
- * Caller: library/aes.c\r
- *\r
- * This modules adds support for the VIA PadLock on x86.\r
- */\r
-#define XYSSL_PADLOCK_C\r
-\r
-/*\r
- * Module: library/rsa.c\r
- * Caller: library/ssl_cli.c\r
- * library/ssl_srv.c\r
- * library/ssl_tls.c\r
- * library/x509.c\r
- *\r
- * This module is required for SSL/TLS and X.509.\r
- */\r
-#define XYSSL_RSA_C\r
-\r
-/*\r
- * Module: library/sha1.c\r
- * Caller: library/ssl_cli.c\r
- * library/ssl_srv.c\r
- * library/ssl_tls.c\r
- * library/x509parse.c\r
- *\r
- * This module is required for SSL/TLS and X.509.\r
- */\r
-#define XYSSL_SHA1_C\r
-\r
-/*\r
- * Module: library/sha2.c\r
- * Caller:\r
- *\r
- * This module adds support for SHA-224 and SHA-256.\r
- */\r
-#define XYSSL_SHA2_C\r
-\r
-/*\r
- * Module: library/sha4.c\r
- * Caller:\r
- *\r
- * This module adds support for SHA-384 and SHA-512.\r
- */\r
-#define XYSSL_SHA4_C\r
-\r
-/*\r
- * Module: library/ssl_cli.c\r
- * Caller:\r
- *\r
- * This module is required for SSL/TLS client support.\r
- */\r
-#define XYSSL_SSL_CLI_C\r
-\r
-/*\r
- * Module: library/ssl_srv.c\r
- * Caller:\r
- *\r
- * This module is required for SSL/TLS server support.\r
- */\r
-#define XYSSL_SSL_SRV_C\r
-\r
-/*\r
- * Module: library/ssl_tls.c\r
- * Caller: library/ssl_cli.c\r
- * library/ssl_srv.c\r
- *\r
- * This module is required for SSL/TLS.\r
- */\r
-#define XYSSL_SSL_TLS_C\r
-\r
-/*\r
- * Module: library/timing.c\r
- * Caller: library/havege.c\r
- *\r
- * This module is used by the HAVEGE random number generator.\r
- */\r
-#define XYSSL_TIMING_C\r
-\r
-/*\r
- * Module: library/x509parse.c\r
- * Caller: library/ssl_cli.c\r
- * library/ssl_srv.c\r
- * library/ssl_tls.c\r
- *\r
- * This module is required for X.509 certificate parsing.\r
- */\r
-#define XYSSL_X509_PARSE_C\r
-\r
-/*\r
- * Module: library/x509_write.c\r
- * Caller:\r
- *\r
- * This module is required for X.509 certificate writing.\r
- */\r
-#define XYSSL_X509_WRITE_C\r
-\r
-#endif /* config.h */\r
+++ /dev/null
-/**\r
- * \file sha1.h\r
- */\r
-#ifndef XYSSL_SHA1_H\r
-#define XYSSL_SHA1_H\r
-\r
-/**\r
- * \brief SHA-1 context structure\r
- */\r
-typedef struct\r
-{\r
- unsigned long total[2]; /*!< number of bytes processed */\r
- unsigned long state[5]; /*!< intermediate digest state */\r
- unsigned char buffer[64]; /*!< data block being processed */\r
-\r
- unsigned char ipad[64]; /*!< HMAC: inner padding */\r
- unsigned char opad[64]; /*!< HMAC: outer padding */\r
-}\r
-sha1_context;\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-/**\r
- * \brief SHA-1 context setup\r
- *\r
- * \param ctx context to be initialized\r
- */\r
-void sha1_starts( sha1_context *ctx );\r
-\r
-/**\r
- * \brief SHA-1 process buffer\r
- *\r
- * \param ctx SHA-1 context\r
- * \param input buffer holding the data\r
- * \param ilen length of the input data\r
- */\r
-void sha1_update( sha1_context *ctx, unsigned char *input, int ilen );\r
-\r
-/**\r
- * \brief SHA-1 final digest\r
- *\r
- * \param ctx SHA-1 context\r
- * \param output SHA-1 checksum result\r
- */\r
-void sha1_finish( sha1_context *ctx, unsigned char output[20] );\r
-\r
-/**\r
- * \brief Output = SHA-1( input buffer )\r
- *\r
- * \param input buffer holding the data\r
- * \param ilen length of the input data\r
- * \param output SHA-1 checksum result\r
- */\r
-void sha1( unsigned char *input, int ilen, unsigned char output[20] );\r
-\r
-/**\r
- * \brief Output = SHA-1( file contents )\r
- *\r
- * \param path input file name\r
- * \param output SHA-1 checksum result\r
- *\r
- * \return 0 if successful, 1 if fopen failed,\r
- * or 2 if fread failed\r
- */\r
-int sha1_file( char *path, unsigned char output[20] );\r
-\r
-/**\r
- * \brief SHA-1 HMAC context setup\r
- *\r
- * \param ctx HMAC context to be initialized\r
- * \param key HMAC secret key\r
- * \param keylen length of the HMAC key\r
- */\r
-void sha1_hmac_starts( sha1_context *ctx, unsigned char *key, int keylen );\r
-\r
-/**\r
- * \brief SHA-1 HMAC process buffer\r
- *\r
- * \param ctx HMAC context\r
- * \param input buffer holding the data\r
- * \param ilen length of the input data\r
- */\r
-void sha1_hmac_update( sha1_context *ctx, unsigned char *input, int ilen );\r
-\r
-/**\r
- * \brief SHA-1 HMAC final digest\r
- *\r
- * \param ctx HMAC context\r
- * \param output SHA-1 HMAC checksum result\r
- */\r
-void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );\r
-\r
-/**\r
- * \brief Output = HMAC-SHA-1( hmac key, input buffer )\r
- *\r
- * \param key HMAC secret key\r
- * \param keylen length of the HMAC key\r
- * \param input buffer holding the data\r
- * \param ilen length of the input data\r
- * \param output HMAC-SHA-1 result\r
- */\r
-void sha1_hmac( unsigned char *key, int keylen,\r
- unsigned char *input, int ilen,\r
- unsigned char output[20] );\r
-\r
-/**\r
- * \brief Checkup routine\r
- *\r
- * \return 0 if successful, or 1 if the test failed\r
- */\r
-int sha1_self_test( int verbose );\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-#endif /* sha1.h */\r
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-#if !defined(NO_AUTH)
-/*
- * Stringify binary data. Output buffer must be twice as big as input,
- * because each byte takes 2 bytes in string representation
- */
-static void
-bin2str(char *to, const unsigned char *p, size_t len)
-{
- const char *hex = "0123456789abcdef";
-
- for (;len--; p++) {
- *to++ = hex[p[0] >> 4];
- *to++ = hex[p[0] & 0x0f];
- }
-}
-
-/*
- * Return stringified MD5 hash for list of vectors.
- * buf must point to at least 32-bytes long buffer
- */
-static void
-md5(char *buf, ...)
-{
- unsigned char hash[16];
- const struct vec *v;
- va_list ap;
- MD5_CTX ctx;
- int i;
-
- MD5Init(&ctx);
-
- va_start(ap, buf);
- for (i = 0; (v = va_arg(ap, const struct vec *)) != NULL; i++) {
- assert(v->len >= 0);
- if (v->len == 0)
- continue;
- if (i > 0)
- MD5Update(&ctx, (unsigned char *) ":", 1);
- MD5Update(&ctx,(unsigned char *)v->ptr,(unsigned int)v->len);
- }
- va_end(ap);
-
- MD5Final(hash, &ctx);
- bin2str(buf, hash, sizeof(hash));
-}
-
-/*
- * Compare to vectors. Return 1 if they are equal
- */
-static int
-vcmp(const struct vec *v1, const struct vec *v2)
-{
- return (v1->len == v2->len && !memcmp(v1->ptr, v2->ptr, v1->len));
-}
-
-struct digest {
- struct vec user;
- struct vec uri;
- struct vec nonce;
- struct vec cnonce;
- struct vec resp;
- struct vec qop;
- struct vec nc;
-};
-
-static const struct auth_keyword {
- size_t offset;
- struct vec vec;
-} known_auth_keywords[] = {
- {offsetof(struct digest, user), {"username=", 9}},
- {offsetof(struct digest, cnonce), {"cnonce=", 7}},
- {offsetof(struct digest, resp), {"response=", 9}},
- {offsetof(struct digest, uri), {"uri=", 4}},
- {offsetof(struct digest, qop), {"qop=", 4}},
- {offsetof(struct digest, nc), {"nc=", 3}},
- {offsetof(struct digest, nonce), {"nonce=", 6}},
- {0, {NULL, 0}}
-};
-
-static void
-parse_authorization_header(const struct vec *h, struct digest *dig)
-{
- const unsigned char *p, *e, *s;
- struct vec *v, vec;
- const struct auth_keyword *kw;
-
- (void) memset(dig, 0, sizeof(*dig));
- p = (unsigned char *) h->ptr + 7;
- e = (unsigned char *) h->ptr + h->len;
-
- while (p < e) {
-
- /* Skip spaces */
- while (p < e && (*p == ' ' || *p == ','))
- p++;
-
- /* Skip to "=" */
- for (s = p; s < e && *s != '='; )
- s++;
- s++;
-
- /* Is it known keyword ? */
- for (kw = known_auth_keywords; kw->vec.len > 0; kw++)
- if (kw->vec.len <= s - p &&
- !memcmp(p, kw->vec.ptr, kw->vec.len))
- break;
-
- if (kw->vec.len == 0)
- v = &vec; /* Dummy placeholder */
- else
- v = (struct vec *) ((char *) dig + kw->offset);
-
- if (*s == '"') {
- p = ++s;
- while (p < e && *p != '"')
- p++;
- } else {
- p = s;
- while (p < e && *p != ' ' && *p != ',')
- p++;
- }
-
- v->ptr = (char *) s;
- v->len = p - s;
-
- if (*p == '"')
- p++;
-
- DBG(("auth field [%.*s]", v->len, v->ptr));
- }
-}
-
-/*
- * Check the user's password, return 1 if OK
- */
-static int
-check_password(int method, const struct vec *ha1, const struct digest *digest)
-{
- char a2[32], resp[32];
- struct vec vec_a2;
-
- /* XXX Due to a bug in MSIE, we do not compare the URI */
- /* Also, we do not check for authentication timeout */
- if (/*strcmp(dig->uri, c->ouri) != 0 || */
- digest->resp.len != 32 /*||
- now - strtoul(dig->nonce, NULL, 10) > 3600 */)
- return (0);
-
- md5(a2, &known_http_methods[method], &digest->uri, NULL);
- vec_a2.ptr = a2;
- vec_a2.len = sizeof(a2);
- md5(resp, ha1, &digest->nonce, &digest->nc,
- &digest->cnonce, &digest->qop, &vec_a2, NULL);
-
- return (!memcmp(resp, digest->resp.ptr, 32));
-}
-
-static FILE *
-open_auth_file(struct shttpd_ctx *ctx, const char *path)
-{
- char name[FILENAME_MAX];
- const char *p, *e;
- FILE *fp = NULL;
- int fd;
-
- if (ctx->options[OPT_AUTH_GPASSWD] != NULL) {
- /* Use global passwords file */
- my_snprintf(name, sizeof(name), "%s",
- ctx->options[OPT_AUTH_GPASSWD]);
- } else {
- /* Try to find .htpasswd in requested directory */
- for (p = path, e = p + strlen(p) - 1; e > p; e--)
- if (IS_DIRSEP_CHAR(*e))
- break;
-
- assert(IS_DIRSEP_CHAR(*e));
- (void) my_snprintf(name, sizeof(name), "%.*s/%s",
- (int) (e - p), p, HTPASSWD);
- }
-
- if ((fd = my_open(name, O_RDONLY, 0)) == -1) {
- DBG(("open_auth_file: open(%s)", name));
- } else if ((fp = fdopen(fd, "r")) == NULL) {
- DBG(("open_auth_file: fdopen(%s)", name));
- (void) close(fd);
- }
-
- return (fp);
-}
-
-/*
- * Parse the line from htpasswd file. Line should be in form of
- * "user:domain:ha1". Fill in the vector values. Return 1 if successful.
- */
-static int
-parse_htpasswd_line(const char *s, struct vec *user,
- struct vec *domain, struct vec *ha1)
-{
- user->len = domain->len = ha1->len = 0;
-
- for (user->ptr = s; *s != '\0' && *s != ':'; s++, user->len++);
- if (*s++ != ':')
- return (0);
-
- for (domain->ptr = s; *s != '\0' && *s != ':'; s++, domain->len++);
- if (*s++ != ':')
- return (0);
-
- for (ha1->ptr = s; *s != '\0' && !isspace(* (unsigned char *) s);
- s++, ha1->len++);
-
- DBG(("parse_htpasswd_line: [%.*s] [%.*s] [%.*s]", user->len, user->ptr,
- domain->len, domain->ptr, ha1->len, ha1->ptr));
-
- return (user->len > 0 && domain->len > 0 && ha1->len > 0);
-}
-
-/*
- * Authorize against the opened passwords file. Return 1 if authorized.
- */
-static int
-authorize(struct conn *c, FILE *fp)
-{
- struct vec *auth_vec = &c->ch.auth.v_vec;
- struct vec *user_vec = &c->ch.user.v_vec;
- struct vec user, domain, ha1;
- struct digest digest;
- int ok = 0;
- char line[256];
-
- if (auth_vec->len > 20 &&
- !my_strncasecmp(auth_vec->ptr, "Digest ", 7)) {
-
- parse_authorization_header(auth_vec, &digest);
- *user_vec = digest.user;
-
- while (fgets(line, sizeof(line), fp) != NULL) {
-
- if (!parse_htpasswd_line(line, &user, &domain, &ha1))
- continue;
-
- DBG(("[%.*s] [%.*s] [%.*s]", user.len, user.ptr,
- domain.len, domain.ptr, ha1.len, ha1.ptr));
-
- if (vcmp(user_vec, &user) &&
- !memcmp(c->ctx->options[OPT_AUTH_REALM],
- domain.ptr, domain.len)) {
- ok = check_password(c->method, &ha1, &digest);
- break;
- }
- }
- }
-
- return (ok);
-}
-
-int
-check_authorization(struct conn *c, const char *path)
-{
- FILE *fp = NULL;
- int len, n, authorized = 1;
- const char *p, *s = c->ctx->options[OPT_PROTECT];
- char protected_path[FILENAME_MAX];
-
- FOR_EACH_WORD_IN_LIST(s, len) {
-
- if ((p = memchr(s, '=', len)) == NULL || p >= s + len || p == s)
- continue;
-
- if (!memcmp(c->uri, s, p - s)) {
-
- n = s + len - p + 1;
- if (n > (int) sizeof(protected_path) - 1)
- n = sizeof(protected_path) - 1;
-
- my_strlcpy(protected_path, p + 1, n);
-
- if ((fp = fopen(protected_path, "r")) == NULL)
- elog(E_LOG, c, "check_auth: cannot open %s: %s",
- protected_path, strerror(errno));
- break;
- }
- }
-
- if (fp == NULL)
- fp = open_auth_file(c->ctx, path);
-
- if (fp != NULL) {
- authorized = authorize(c, fp);
- (void) fclose(fp);
- }
-
- return (authorized);
-}
-
-int
-is_authorized_for_put(struct conn *c)
-{
- FILE *fp;
- int ret = 0;
-
- if ((fp = fopen(c->ctx->options[OPT_AUTH_PUT], "r")) != NULL) {
- ret = authorize(c, fp);
- (void) fclose(fp);
- }
-
- return (ret);
-}
-
-void
-send_authorization_request(struct conn *c)
-{
- char buf[512];
-
- (void) my_snprintf(buf, sizeof(buf), "Unauthorized\r\n"
- "WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\", "
- "nonce=\"%lu\"", c->ctx->options[OPT_AUTH_REALM],
- (unsigned long) current_time);
-
- send_server_error(c, 401, buf);
-}
-
-/*
- * Edit the passwords file.
- */
-int
-edit_passwords(const char *fname, const char *domain,
- const char *user, const char *pass)
-{
- int ret = EXIT_SUCCESS, found = 0;
- struct vec u, d, p;
- char line[512], tmp[FILENAME_MAX], ha1[32];
- FILE *fp = NULL, *fp2 = NULL;
-
- (void) my_snprintf(tmp, sizeof(tmp), "%s.tmp", fname);
-
- /* Create the file if does not exist */
- if ((fp = fopen(fname, "a+")))
- (void) fclose(fp);
-
- /* Open the given file and temporary file */
- if ((fp = fopen(fname, "r")) == NULL)
- elog(E_FATAL, 0, "Cannot open %s: %s", fname, strerror(errno));
- else if ((fp2 = fopen(tmp, "w+")) == NULL)
- elog(E_FATAL, 0, "Cannot open %s: %s", tmp, strerror(errno));
-
- p.ptr = pass;
- p.len = strlen(pass);
-
- /* Copy the stuff to temporary file */
- while (fgets(line, sizeof(line), fp) != NULL) {
- u.ptr = line;
- if ((d.ptr = strchr(line, ':')) == NULL)
- continue;
- u.len = d.ptr - u.ptr;
- d.ptr++;
- if (strchr(d.ptr, ':') == NULL)
- continue;
- d.len = strchr(d.ptr, ':') - d.ptr;
-
- if ((int) strlen(user) == u.len &&
- !memcmp(user, u.ptr, u.len) &&
- (int) strlen(domain) == d.len &&
- !memcmp(domain, d.ptr, d.len)) {
- found++;
- md5(ha1, &u, &d, &p, NULL);
- (void) fprintf(fp2, "%s:%s:%.32s\n", user, domain, ha1);
- } else {
- (void) fprintf(fp2, "%s", line);
- }
- }
-
- /* If new user, just add it */
- if (found == 0) {
- u.ptr = user; u.len = strlen(user);
- d.ptr = domain; d.len = strlen(domain);
- md5(ha1, &u, &d, &p, NULL);
- (void) fprintf(fp2, "%s:%s:%.32s\n", user, domain, ha1);
- }
-
- /* Close files */
- (void) fclose(fp);
- (void) fclose(fp2);
-
- /* Put the temp file in place of real file */
- (void) my_remove(fname);
- (void) my_rename(tmp, fname);
-
- return (ret);
-}
-#endif /* NO_AUTH */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-#if !defined(NO_CGI)
-struct env_block {
- char buf[ENV_MAX]; /* Environment buffer */
- int len; /* Space taken */
- char *vars[CGI_ENV_VARS]; /* Point into the buffer */
- int nvars; /* Number of variables */
-};
-
-/*
- * UNIX socketpair() implementation. Why? Because Windows does not have it.
- * Return 0 on success, -1 on error.
- */
-static int
-my_socketpair(struct conn *c, int sp[2])
-{
- struct sockaddr_in sa;
- int sock, ret = -1;
- socklen_t len = sizeof(sa);
-
- (void) memset(&sa, 0, sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_port = htons(0);
- sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
- elog(E_LOG, c, "mysocketpair: socket(): %d", ERRNO);
- } else if (bind(sock, (struct sockaddr *) &sa, len) != 0) {
- elog(E_LOG, c, "mysocketpair: bind(): %d", ERRNO);
- (void) closesocket(sock);
- } else if (listen(sock, 1) != 0) {
- elog(E_LOG, c, "mysocketpair: listen(): %d", ERRNO);
- (void) closesocket(sock);
- } else if (getsockname(sock, (struct sockaddr *) &sa, &len) != 0) {
- elog(E_LOG, c, "mysocketpair: getsockname(): %d", ERRNO);
- (void) closesocket(sock);
- } else if ((sp[0] = socket(AF_INET, SOCK_STREAM, 6)) == -1) {
- elog(E_LOG, c, "mysocketpair: socket(): %d", ERRNO);
- (void) closesocket(sock);
- } else if (connect(sp[0], (struct sockaddr *) &sa, len) != 0) {
- elog(E_LOG, c, "mysocketpair: connect(): %d", ERRNO);
- (void) closesocket(sock);
- (void) closesocket(sp[0]);
- } else if ((sp[1] = accept(sock,(struct sockaddr *) &sa, &len)) == -1) {
- elog(E_LOG, c, "mysocketpair: accept(): %d", ERRNO);
- (void) closesocket(sock);
- (void) closesocket(sp[0]);
- } else {
- /* Success */
- ret = 0;
- (void) closesocket(sock);
- }
-
-#ifndef _WIN32
- (void) fcntl(sp[0], F_SETFD, FD_CLOEXEC);
- (void) fcntl(sp[1], F_SETFD, FD_CLOEXEC);
-#endif /* _WIN32*/
-
- return (ret);
-}
-
-static void
-addenv(struct env_block *block, const char *fmt, ...)
-{
- int n, space;
- va_list ap;
-
- space = sizeof(block->buf) - block->len - 2;
- assert(space >= 0);
-
- va_start(ap, fmt);
- n = vsnprintf(block->buf + block->len, space, fmt, ap);
- va_end(ap);
-
- if (n > 0 && n < space && block->nvars < CGI_ENV_VARS - 2) {
- block->vars[block->nvars++] = block->buf + block->len;
- block->len += n + 1; /* Include \0 terminator */
- }
-}
-
-static void
-add_http_headers_to_env(struct env_block *b, const char *s, int len)
-{
- const char *p, *v, *e = s + len;
- int space, n, i, ch;
-
- /* Loop through all headers in the request */
- while (s < e) {
-
- /* Find where this header ends. Remember where value starts */
- for (p = s, v = NULL; p < e && *p != '\n'; p++)
- if (v == NULL && *p == ':')
- v = p;
-
- /* 2 null terminators and "HTTP_" */
- space = (sizeof(b->buf) - b->len) - (2 + 5);
- assert(space >= 0);
-
- /* Copy header if enough space in the environment block */
- if (v > s && p > v + 2 && space > p - s) {
-
- /* Store var */
- if (b->nvars < (int) NELEMS(b->vars) - 1)
- b->vars[b->nvars++] = b->buf + b->len;
-
- (void) memcpy(b->buf + b->len, "HTTP_", 5);
- b->len += 5;
-
- /* Copy header name. Substitute '-' to '_' */
- n = v - s;
- for (i = 0; i < n; i++) {
- ch = s[i] == '-' ? '_' : s[i];
- b->buf[b->len++] = toupper(ch);
- }
-
- b->buf[b->len++] = '=';
-
- /* Copy header value */
- v += 2;
- n = p[-1] == '\r' ? (p - v) - 1 : p - v;
- for (i = 0; i < n; i++)
- b->buf[b->len++] = v[i];
-
- /* Null-terminate */
- b->buf[b->len++] = '\0';
- }
-
- s = p + 1; /* Shift to the next header */
- }
-}
-
-static void
-prepare_environment(const struct conn *c, const char *prog,
- struct env_block *blk)
-{
- const struct headers *h = &c->ch;
- const char *s, *root = c->ctx->options[OPT_ROOT];
- size_t len;
-
- blk->len = blk->nvars = 0;
-
- /* Prepare the environment block */
- addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1");
- addenv(blk, "%s", "SERVER_PROTOCOL=HTTP/1.1");
- addenv(blk, "%s", "REDIRECT_STATUS=200"); /* PHP */
- addenv(blk, "SERVER_PORT=%d", c->loc_port);
- addenv(blk, "SERVER_NAME=%s", c->ctx->options[OPT_AUTH_REALM]);
- addenv(blk, "SERVER_ROOT=%s", root);
- addenv(blk, "DOCUMENT_ROOT=%s", root);
- addenv(blk, "REQUEST_METHOD=%s", known_http_methods[c->method].ptr);
- addenv(blk, "REMOTE_ADDR=%s", inet_ntoa(c->sa.u.sin.sin_addr));
- addenv(blk, "REMOTE_PORT=%hu", ntohs(c->sa.u.sin.sin_port));
- addenv(blk, "REQUEST_URI=%s", c->uri);
- addenv(blk, "SCRIPT_NAME=%s", prog + strlen(root));
- addenv(blk, "SCRIPT_FILENAME=%s", prog); /* PHP */
- addenv(blk, "PATH_TRANSLATED=%s", prog);
-
- if (h->ct.v_vec.len > 0)
- addenv(blk, "CONTENT_TYPE=%.*s",
- h->ct.v_vec.len, h->ct.v_vec.ptr);
-
- if (c->query != NULL)
- addenv(blk, "QUERY_STRING=%s", c->query);
-
- if (c->path_info != NULL)
- addenv(blk, "PATH_INFO=/%s", c->path_info);
-
- if (h->cl.v_big_int > 0)
- addenv(blk, "CONTENT_LENGTH=%lu", h->cl.v_big_int);
-
- if ((s = getenv("PATH")) != NULL)
- addenv(blk, "PATH=%s", s);
-
-#ifdef _WIN32
- if ((s = getenv("COMSPEC")) != NULL)
- addenv(blk, "COMSPEC=%s", s);
- if ((s = getenv("SYSTEMROOT")) != NULL)
- addenv(blk, "SYSTEMROOT=%s", s);
-#else
- if ((s = getenv("LD_LIBRARY_PATH")) != NULL)
- addenv(blk, "LD_LIBRARY_PATH=%s", s);
-#endif /* _WIN32 */
-
- if ((s = getenv("PERLLIB")) != NULL)
- addenv(blk, "PERLLIB=%s", s);
-
- if (h->user.v_vec.len > 0) {
- addenv(blk, "REMOTE_USER=%.*s",
- h->user.v_vec.len, h->user.v_vec.ptr);
- addenv(blk, "%s", "AUTH_TYPE=Digest");
- }
-
- /* Add user-specified variables */
- s = c->ctx->options[OPT_CGI_ENVIRONMENT];
- FOR_EACH_WORD_IN_LIST(s, len)
- addenv(blk, "%.*s", len, s);
-
- /* Add all headers as HTTP_* variables */
- add_http_headers_to_env(blk, c->headers,
- c->rem.headers_len - (c->headers - c->request));
-
- blk->vars[blk->nvars++] = NULL;
- blk->buf[blk->len++] = '\0';
-
- assert(blk->nvars < CGI_ENV_VARS);
- assert(blk->len > 0);
- assert(blk->len < (int) sizeof(blk->buf));
-
- /* Debug stuff to view passed environment */
- DBG(("%s: %d vars, %d env size", prog, blk->nvars, blk->len));
- {
- int i;
- for (i = 0 ; i < blk->nvars; i++)
- DBG(("[%s]", blk->vars[i] ? blk->vars[i] : "null"));
- }
-}
-
-int
-run_cgi(struct conn *c, const char *prog)
-{
- struct env_block blk;
- char dir[FILENAME_MAX], *p;
- int ret, pair[2];
-
- prepare_environment(c, prog, &blk);
- pair[0] = pair[1] = -1;
-
- /* CGI must be executed in its own directory */
- (void) my_snprintf(dir, sizeof(dir), "%s", prog);
- for (p = dir + strlen(dir) - 1; p > dir; p--)
- if (*p == '/') {
- *p++ = '\0';
- break;
- }
-
- if (my_socketpair(c, pair) != 0) {
- ret = -1;
- } else if (spawn_process(c, prog, blk.buf, blk.vars, pair[1], dir)) {
- ret = -1;
- (void) closesocket(pair[0]);
- (void) closesocket(pair[1]);
- } else {
- ret = 0;
- c->loc.chan.sock = pair[0];
- }
-
- return (ret);
-}
-
-void
-do_cgi(struct conn *c)
-{
- DBG(("running CGI: [%s]", c->uri));
- assert(c->loc.io.size > CGI_REPLY_LEN);
- memcpy(c->loc.io.buf, CGI_REPLY, CGI_REPLY_LEN);
- c->loc.io.head = c->loc.io.tail = c->loc.io.total = CGI_REPLY_LEN;
- c->loc.io_class = &io_cgi;
- c->loc.flags = FLAG_R;
- if (c->method == METHOD_POST)
- c->loc.flags |= FLAG_W;
-}
-
-#endif /* !NO_CGI */
+++ /dev/null
-/**********************************************************************
- *
- * rtems shttpd management
- *
- * FILE NAME : rtems_shttpd.c
- *
- * AUTHOR : Steven Johnson
- *
- * DESCRIPTION : Defines the interface functions to the shttp daemon
- *
- * REVISION : $Id: compat_rtems.c,v 1.2 2006/11/12 03:29:17 infidel Exp $
- *
- * COMMENTS :
- *
- **********************************************************************/
-
- /**********************************************************************
- * INCLUDED MODULES
- **********************************************************************/
-#include <rtems.h>
-#include "defs.h"
-
-#define MAX_WEB_BASE_PATH_LENGTH 256
-#define MIN_SHTTPD_STACK (8*1024)
-
-typedef struct RTEMS_HTTPD_ARGS {
- rtems_shttpd_init init_callback;
- rtems_shttpd_addpages addpages_callback;
- char webroot[MAX_WEB_BASE_PATH_LENGTH];
-} RTEMS_HTTPD_ARGS;
-
-static int rtems_webserver_running = FALSE; //not running.
-
-static rtems_task rtems_httpd_daemon(rtems_task_argument args )
-{
- RTEMS_HTTPD_ARGS *httpd_args = (RTEMS_HTTPD_ARGS*)args;
-
- struct shttpd_ctx *ctx;
-
- if (httpd_args != NULL)
- if (httpd_args->init_callback != NULL)
- httpd_args->init_callback();
-
-/**************************************
- * Initialize the web server
- */
- /*
- * Initialize SHTTPD context.
- * Set WWW root to current WEB_ROOT_PATH.
- */
- ctx = shttpd_init(NULL, "document_root", httpd_args->webroot, NULL);
-
- if (httpd_args != NULL)
- if (httpd_args->addpages_callback != NULL)
- httpd_args->addpages_callback(ctx);
-
- /* Finished with args, so free them */
- if (httpd_args != NULL)
- free(httpd_args);
-
- /* Open listening socket */
- shttpd_listen(ctx, 9000);
-
- rtems_webserver_running = TRUE;
-
- /* Serve connections infinitely until someone kills us */
- while (rtems_webserver_running)
- shttpd_poll(ctx, 1000);
-
- /* Unreached, because we will be killed by a signal */
- shttpd_fini(ctx);
-
- rtems_task_delete( RTEMS_SELF );
-}
-
-rtems_status_code rtems_initialize_webserver(rtems_task_priority initial_priority,
- rtems_unsigned32 stack_size,
- rtems_mode initial_modes,
- rtems_attribute attribute_set,
- rtems_shttpd_init init_callback,
- rtems_shttpd_addpages addpages_callback,
- char *webroot
- )
-{
- rtems_status_code sc;
- rtems_id tid;
- RTEMS_HTTPD_ARGS *args;
-
- if (stack_size < MIN_SHTTPD_STACK)
- stack_size = MIN_SHTTPD_STACK;
-
- args = malloc(sizeof(RTEMS_HTTPD_ARGS));
-
- if (args != NULL)
- {
- args->init_callback = init_callback;
- args->addpages_callback = addpages_callback;
- strncpy(args->webroot,webroot,MAX_WEB_BASE_PATH_LENGTH);
-
- sc = rtems_task_create(rtems_build_name('H', 'T', 'P', 'D'),
- initial_priority,
- stack_size,
- initial_modes,
- attribute_set,
- &tid);
-
- if (sc == RTEMS_SUCCESSFUL)
- {
- sc = rtems_task_start(tid, rtems_httpd_daemon, (rtems_task_argument)args);
- }
- }
- else
- {
- sc = RTEMS_NO_MEMORY;
- }
-
- return sc;
-}
-
-void rtems_terminate_webserver(void)
-{
- rtems_webserver_running = FALSE; //not running, so terminate
-}
-
-int rtems_webserver_ok(void)
-{
- return rtems_webserver_running;
-}
-
-void
-set_close_on_exec(int fd)
-{
- // RTEMS Does not have a functional "execve"
- // so technically this call does not do anything,
- // but it doesnt hurt either.
- (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
-}
-
-int
-my_stat(const char *path, struct stat *stp)
-{
- return (stat(path, stp));
-}
-
-int
-my_open(const char *path, int flags, int mode)
-{
- return (open(path, flags, mode));
-}
-
-int
-my_remove(const char *path)
-{
- return (remove(path));
-}
-
-int
-my_rename(const char *path1, const char *path2)
-{
- return (rename(path1, path2));
-}
-
-int
-my_mkdir(const char *path, int mode)
-{
- return (mkdir(path, mode));
-}
-
-char *
-my_getcwd(char *buffer, int maxlen)
-{
- return (getcwd(buffer, maxlen));
-}
-
-int
-set_non_blocking_mode(int fd)
-{
- int ret = -1;
- int flags;
-
- if ((flags = fcntl(fd, F_GETFL, 0)) == -1) {
- DBG(("nonblock: fcntl(F_GETFL): %d", ERRNO));
- } else if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) {
- DBG(("nonblock: fcntl(F_SETFL): %d", ERRNO));
- } else {
- ret = 0; /* Success */
- }
-
- return (ret);
-}
-
-#if !defined(NO_CGI)
-int
-spawn_process(struct conn *c, const char *prog, char *envblk, char **envp)
-{
- return (-1); // RTEMS does not have subprocess support as standard.
-}
-#endif
+++ /dev/null
-/**
- * @file rtems/rtems-shttpd.h
- */
-
-#ifndef _rtems_rtems_webserver_h
-#define _rtems_rtems_webserver_h
-
-#include "shttpd.h"
-
-#include <rtems.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <dirent.h>
-
-/* RTEMS is an Real Time Embedded operating system, for operation in hardware.
- It does not have SSL or CGI support, as it does not have dynamic library
- loading or sub-processes. */
-#define EMBEDDED
-#define NO_SSL
-#define NO_CGI
-
-#define DIRSEP '/'
-#define O_BINARY 0
-#define ERRNO errno
-
-/* RTEMS version is Thread Safe */
-#define InitializeCriticalSection(x) rtems_semaphore_create( \
- rtems_build_name('H','T','P','X'), \
- 1, /* Not Held Yet.*/ \
- RTEMS_FIFO | \
- RTEMS_BINARY_SEMAPHORE, \
- 0, \
- x);
-#define EnterCriticalSection(x) rtems_semaphore_obtain(*(x),RTEMS_WAIT,RTEMS_NO_TIMEOUT)
-#define LeaveCriticalSection(x) rtems_semaphore_release(*(x))
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (*rtems_shttpd_addpages)(struct shttpd_ctx *ctx);
-typedef void (*rtems_shttpd_init)(void);
-
-rtems_status_code rtems_initialize_webserver(rtems_task_priority initial_priority,
- rtems_unsigned32 stack_size,
- rtems_mode initial_modes,
- rtems_attribute attribute_set,
- rtems_shttpd_init init_callback,
- rtems_shttpd_addpages addpages_callback,
- char *webroot
- );
-void rtems_terminate_webserver(void);
-int rtems_webserver_ok(void);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-void
-set_close_on_exec(int fd)
-{
- (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
-}
-
-int
-my_stat(const char *path, struct stat *stp)
-{
- return (stat(path, stp));
-}
-
-int
-my_open(const char *path, int flags, int mode)
-{
- return (open(path, flags, mode));
-}
-
-int
-my_remove(const char *path)
-{
- return (remove(path));
-}
-
-int
-my_rename(const char *path1, const char *path2)
-{
- return (rename(path1, path2));
-}
-
-int
-my_mkdir(const char *path, int mode)
-{
- return (mkdir(path, mode));
-}
-
-char *
-my_getcwd(char *buffer, int maxlen)
-{
- return (getcwd(buffer, maxlen));
-}
-
-int
-set_non_blocking_mode(int fd)
-{
- int ret = -1;
- int flags;
-
- if ((flags = fcntl(fd, F_GETFL, 0)) == -1) {
- DBG(("nonblock: fcntl(F_GETFL): %d", ERRNO));
- } else if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) {
- DBG(("nonblock: fcntl(F_SETFL): %d", ERRNO));
- } else {
- ret = 0; /* Success */
- }
-
- return (ret);
-}
-
-#ifndef NO_CGI
-int
-spawn_process(struct conn *c, const char *prog, char *envblk,
- char *envp[], int sock, const char *dir)
-{
- int ret;
- pid_t pid;
- const char *p, *interp = c->ctx->options[OPT_CGI_INTERPRETER];
-
- envblk = NULL; /* unused */
-
- if ((pid = vfork()) == -1) {
-
- ret = -1;
- elog(E_LOG, c, "redirect: fork: %s", strerror(errno));
-
- } else if (pid == 0) {
-
- /* Child */
-
- (void) chdir(dir);
- (void) dup2(sock, 0);
- (void) dup2(sock, 1);
- (void) closesocket(sock);
-
- /* If error file is specified, send errors there */
- if (c->ctx->error_log)
- (void) dup2(fileno(c->ctx->error_log), 2);
-
- if ((p = strrchr(prog, '/')) != NULL)
- p++;
- else
- p = prog;
-
- /* Execute CGI program */
- if (interp == NULL) {
- (void) execle(p, p, NULL, envp);
- elog(E_FATAL, c, "redirect: exec(%s)", prog);
- } else {
- (void) execle(interp, interp, p, NULL, envp);
- elog(E_FATAL, c, "redirect: exec(%s %s)",
- interp, prog);
- }
-
- /* UNREACHED */
- exit(EXIT_FAILURE);
-
- } else {
-
- /* Parent */
- ret = 0;
- (void) closesocket(sock);
- }
-
- return (ret);
-}
-#endif /* !NO_CGI */
+++ /dev/null
-/*
- * Copyright (c) 2004-2007 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/mman.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
-
-#include <pwd.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <dlfcn.h>
-#define SSL_LIB "libssl.so"
-#define DIRSEP '/'
-#define IS_DIRSEP_CHAR(c) ((c) == '/')
-#define O_BINARY 0
-#define closesocket(a) close(a)
-#define ERRNO errno
-#define NO_GUI
-
-#define InitializeCriticalSection(x) /* FIXME UNIX version is not MT safe */
-#define EnterCriticalSection(x)
-#define LeaveCriticalSection(x)
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-static void
-fix_directory_separators(char *path)
-{
- for (; *path != '\0'; path++) {
- if (*path == '/')
- *path = '\\';
- if (*path == '\\')
- while (path[1] == '\\' || path[1] == '/')
- (void) memmove(path + 1,
- path + 2, strlen(path + 2) + 1);
- }
-}
-
-static int
-protect_against_code_disclosure(const char *path)
-{
- WIN32_FIND_DATA data;
- HANDLE handle;
- const char *p;
-
- /*
- * Protect against CGI code disclosure under Windows.
- * This is very nasty hole. Windows happily opens files with
- * some garbage in the end of file name. So fopen("a.cgi ", "r")
- * actually opens "a.cgi", and does not return an error! And since
- * "a.cgi " does not have valid CGI extension, this leads to
- * the CGI code disclosure.
- * To protect, here we delete all fishy characters from the
- * end of file name.
- */
-
- if ((handle = FindFirstFile(path, &data)) == INVALID_HANDLE_VALUE)
- return (FALSE);
-
- FindClose(handle);
-
- for (p = path + strlen(path); p > path && p[-1] != '\\';)
- p--;
-
- if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
- strcmp(data.cFileName, p) != 0)
- return (FALSE);
-
- return (TRUE);
-}
-
-int
-my_open(const char *path, int flags, int mode)
-{
- char buf[FILENAME_MAX];
- wchar_t wbuf[FILENAME_MAX];
-
- my_strlcpy(buf, path, sizeof(buf));
- fix_directory_separators(buf);
- MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf));
-
- if (protect_against_code_disclosure(buf) == FALSE)
- return (-1);
-
- return (_wopen(wbuf, flags));
-}
-
-int
-my_stat(const char *path, struct stat *stp)
-{
- char buf[FILENAME_MAX], *p;
- wchar_t wbuf[FILENAME_MAX];
-
- my_strlcpy(buf, path, sizeof(buf));
- fix_directory_separators(buf);
-
- p = buf + strlen(buf) - 1;
- while (p > buf && *p == '\\' && p[-1] != ':')
- *p-- = '\0';
-
- MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf));
-
- return (_wstat(wbuf, (struct _stat *) stp));
-}
-
-int
-my_remove(const char *path)
-{
- char buf[FILENAME_MAX];
- wchar_t wbuf[FILENAME_MAX];
-
- my_strlcpy(buf, path, sizeof(buf));
- fix_directory_separators(buf);
-
- MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf));
-
- return (_wremove(wbuf));
-}
-
-int
-my_rename(const char *path1, const char *path2)
-{
- char buf1[FILENAME_MAX];
- char buf2[FILENAME_MAX];
- wchar_t wbuf1[FILENAME_MAX];
- wchar_t wbuf2[FILENAME_MAX];
-
- my_strlcpy(buf1, path1, sizeof(buf1));
- my_strlcpy(buf2, path2, sizeof(buf2));
- fix_directory_separators(buf1);
- fix_directory_separators(buf2);
-
- MultiByteToWideChar(CP_UTF8, 0, buf1, -1, wbuf1, sizeof(wbuf1));
- MultiByteToWideChar(CP_UTF8, 0, buf2, -1, wbuf2, sizeof(wbuf2));
-
- return (_wrename(wbuf1, wbuf2));
-}
-
-int
-my_mkdir(const char *path, int mode)
-{
- char buf[FILENAME_MAX];
- wchar_t wbuf[FILENAME_MAX];
-
- my_strlcpy(buf, path, sizeof(buf));
- fix_directory_separators(buf);
-
- MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf));
-
- return (_wmkdir(wbuf));
-}
-
-static char *
-wide_to_utf8(const wchar_t *str)
-{
- char *buf = NULL;
- if (str) {
- int nchar = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
- if (nchar > 0) {
- buf = malloc(nchar);
- if (!buf)
- errno = ENOMEM;
- else if (!WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, nchar, NULL, NULL)) {
- free(buf);
- buf = NULL;
- errno = EINVAL;
- }
- } else
- errno = EINVAL;
- } else
- errno = EINVAL;
- return buf;
-}
-
-char *
-my_getcwd(char *buffer, int maxlen)
-{
- char *result = NULL;
- wchar_t *wbuffer, *wresult;
-
- if (buffer) {
- /* User-supplied buffer */
- wbuffer = malloc(maxlen * sizeof(wchar_t));
- if (wbuffer == NULL)
- return NULL;
- } else
- /* Dynamically allocated buffer */
- wbuffer = NULL;
- wresult = _wgetcwd(wbuffer, maxlen);
- if (wresult) {
- int err = errno;
- if (buffer) {
- /* User-supplied buffer */
- int n = WideCharToMultiByte(CP_UTF8, 0, wresult, -1, buffer, maxlen, NULL, NULL);
- if (n == 0)
- err = ERANGE;
- free(wbuffer);
- result = buffer;
- } else {
- /* Buffer allocated by _wgetcwd() */
- result = wide_to_utf8(wresult);
- err = errno;
- free(wresult);
- }
- errno = err;
- }
- return result;
-}
-
-DIR *
-opendir(const char *name)
-{
- DIR *dir = NULL;
- char path[FILENAME_MAX];
- wchar_t wpath[FILENAME_MAX];
-
- if (name == NULL || name[0] == '\0') {
- errno = EINVAL;
- } else if ((dir = malloc(sizeof(*dir))) == NULL) {
- errno = ENOMEM;
- } else {
- my_snprintf(path, sizeof(path), "%s/*", name);
- fix_directory_separators(path);
- MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, sizeof(wpath));
- dir->handle = FindFirstFileW(wpath, &dir->info);
-
- if (dir->handle != INVALID_HANDLE_VALUE) {
- dir->result.d_name[0] = '\0';
- } else {
- free(dir);
- dir = NULL;
- }
- }
-
- return (dir);
-}
-
-int
-closedir(DIR *dir)
-{
- int result = -1;
-
- if (dir != NULL) {
- if (dir->handle != INVALID_HANDLE_VALUE)
- result = FindClose(dir->handle) ? 0 : -1;
-
- free(dir);
- }
-
- if (result == -1)
- errno = EBADF;
-
- return (result);
-}
-
-struct dirent *
-readdir(DIR *dir)
-{
- struct dirent *result = 0;
-
- if (dir && dir->handle != INVALID_HANDLE_VALUE) {
- if(!dir->result.d_name ||
- FindNextFileW(dir->handle, &dir->info)) {
- result = &dir->result;
-
- WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName,
- -1, result->d_name,
- sizeof(result->d_name), NULL, NULL);
- }
- } else {
- errno = EBADF;
- }
-
- return (result);
-}
-
-int
-set_non_blocking_mode(int fd)
-{
- unsigned long on = 1;
-
- return (ioctlsocket(fd, FIONBIO, &on));
-}
-
-void
-set_close_on_exec(int fd)
-{
- fd = 0; /* Do nothing. There is no FD_CLOEXEC on Windows */
-}
-
-#if !defined(NO_CGI)
-
-struct threadparam {
- SOCKET s;
- HANDLE hPipe;
- big_int_t content_len;
-};
-
-/*
- * Thread function that reads POST data from the socket pair
- * and writes it to the CGI process.
- */
-static void//DWORD WINAPI
-stdoutput(void *arg)
-{
- struct threadparam *tp = arg;
- int n, sent, stop = 0;
- big_int_t total = 0;
- DWORD k;
- char buf[BUFSIZ];
- size_t max_recv;
-
- max_recv = min(sizeof(buf), tp->content_len - total);
- while (!stop && max_recv > 0 && (n = recv(tp->s, buf, max_recv, 0)) > 0) {
- for (sent = 0; !stop && sent < n; sent += k)
- if (!WriteFile(tp->hPipe, buf + sent, n - sent, &k, 0))
- stop++;
- total += n;
- max_recv = min(sizeof(buf), tp->content_len - total);
- }
-
- CloseHandle(tp->hPipe); /* Suppose we have POSTed everything */
- free(tp);
-}
-
-/*
- * Thread function that reads CGI output and pushes it to the socket pair.
- */
-static void
-stdinput(void *arg)
-{
- struct threadparam *tp = arg;
- static int ntotal;
- int k, stop = 0;
- DWORD n, sent;
- char buf[BUFSIZ];
-
- while (!stop && ReadFile(tp->hPipe, buf, sizeof(buf), &n, NULL)) {
- ntotal += n;
- for (sent = 0; !stop && sent < n; sent += k)
- if ((k = send(tp->s, buf + sent, n - sent, 0)) <= 0)
- stop++;
- }
- CloseHandle(tp->hPipe);
-
- /*
- * Windows is a piece of crap. When this thread closes its end
- * of the socket pair, the other end (get_cgi() function) may loose
- * some data. I presume, this happens if get_cgi() is not fast enough,
- * and the data written by this end does not "push-ed" to the other
- * end socket buffer. So after closesocket() the remaining data is
- * gone. If I put shutdown() before closesocket(), that seems to
- * fix the problem, but I am not sure this is the right fix.
- * XXX (submitted by James Marshall) we do not do shutdown() on UNIX.
- * If fork() is called from user callback, shutdown() messes up things.
- */
- shutdown(tp->s, 2);
-
- closesocket(tp->s);
- free(tp);
-
- _endthread();
-}
-
-static void
-spawn_stdio_thread(int sock, HANDLE hPipe, void (*func)(void *),
- big_int_t content_len)
-{
- struct threadparam *tp;
- DWORD tid;
-
- tp = malloc(sizeof(*tp));
- assert(tp != NULL);
-
- tp->s = sock;
- tp->hPipe = hPipe;
- tp->content_len = content_len;
- _beginthread(func, 0, tp);
-}
-
-int
-spawn_process(struct conn *c, const char *prog, char *envblk,
- char *envp[], int sock, const char *dir)
-{
- HANDLE a[2], b[2], h[2], me;
- DWORD flags;
- char *p, cmdline[FILENAME_MAX], line[FILENAME_MAX];
- FILE *fp;
- STARTUPINFOA si;
- PROCESS_INFORMATION pi;
-
- me = GetCurrentProcess();
- flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS;
-
- /* FIXME add error checking code here */
- CreatePipe(&a[0], &a[1], NULL, 0);
- CreatePipe(&b[0], &b[1], NULL, 0);
- DuplicateHandle(me, a[0], me, &h[0], 0, TRUE, flags);
- DuplicateHandle(me, b[1], me, &h[1], 0, TRUE, flags);
-
- (void) memset(&si, 0, sizeof(si));
- (void) memset(&pi, 0, sizeof(pi));
-
- /* XXX redirect CGI errors to the error log file */
- si.cb = sizeof(si);
- si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE;
- si.hStdOutput = si.hStdError = h[1];
- si.hStdInput = h[0];
-
- /* If CGI file is a script, try to read the interpreter line */
- if (c->ctx->options[OPT_CGI_INTERPRETER] == NULL) {
- if ((fp = fopen(prog, "r")) != NULL) {
- (void) fgets(line, sizeof(line), fp);
- if (memcmp(line, "#!", 2) != 0)
- line[2] = '\0';
- /* Trim whitespaces from interpreter name */
- for (p = &line[strlen(line) - 1]; p > line &&
- isspace(*p); p--)
- *p = '\0';
- (void) fclose(fp);
- }
- (void) my_snprintf(cmdline, sizeof(cmdline), "%s%s%s",
- line + 2, line[2] == '\0' ? "" : " ", prog);
- } else {
- (void) my_snprintf(cmdline, sizeof(cmdline), "%s %s",
- c->ctx->options[OPT_CGI_INTERPRETER], prog);
- }
-
- (void) my_snprintf(line, sizeof(line), "%s", dir);
- fix_directory_separators(line);
- fix_directory_separators(cmdline);
-
- /*
- * Spawn reader & writer threads before we create CGI process.
- * Otherwise CGI process may die too quickly, loosing the data
- */
- spawn_stdio_thread(sock, b[0], stdinput, 0);
- spawn_stdio_thread(sock, a[1], stdoutput, c->rem.content_len);
-
- if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
- CREATE_NEW_PROCESS_GROUP, envblk, line, &si, &pi) == 0) {
- elog(E_LOG, c,"redirect: CreateProcess(%s): %d",cmdline,ERRNO);
- return (-1);
- } else {
- CloseHandle(h[0]);
- CloseHandle(h[1]);
- CloseHandle(pi.hThread);
- CloseHandle(pi.hProcess);
- }
-
- return (0);
-}
-
-#endif /* !NO_CGI */
+++ /dev/null
-/*
- * Copyright (c) 2004-2007 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-/* Tip from Justin Maximilian, suppress errors from winsock2.h */
-#define _WINSOCKAPI_
-
-#include <windows.h>
-#include <winsock2.h>
-#include <commctrl.h>
-#include <winnls.h>
-#include <shlobj.h>
-#include <shellapi.h>
-
-#ifndef _WIN32_WCE
-
-#include <process.h>
-#include <direct.h>
-#include <io.h>
-
-#else /* _WIN32_WCE */
-
-/* Windows CE-specific definitions */
-#define NO_CGI /* WinCE has no pipes */
-#define NO_GUI /* temporarily until it is fixed */
-#pragma comment(lib,"ws2")
-/* WinCE has both Unicode and ANSI versions of GetProcAddress */
-#undef GetProcAddress
-#define GetProcAddress GetProcAddressA
-#include "compat_wince.h"
-
-#endif /* _WIN32_WCE */
-
-#define ERRNO GetLastError()
-#define NO_SOCKLEN_T
-#define SSL_LIB L"libssl32.dll"
-#define DIRSEP '\\'
-#define IS_DIRSEP_CHAR(c) ((c) == '/' || (c) == '\\')
-#define O_NONBLOCK 0
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define snprintf _snprintf
-#define vsnprintf _vsnprintf
-#define mkdir(x,y) _mkdir(x)
-#define popen(x,y) _popen(x, y)
-#define pclose(x) _pclose(x)
-#define dlopen(x,y) LoadLibraryW(x)
-#define dlsym(x,y) (void *) GetProcAddress(x,y)
-#define _POSIX_
-
-#ifdef __LCC__
-#include <stdint.h>
-#endif /* __LCC__ */
-
-#ifdef _MSC_VER /* MinGW already has these */
-typedef unsigned int uint32_t;
-typedef unsigned short uint16_t;
-typedef __int64 uint64_t;
-#define S_ISDIR(x) ((x) & _S_IFDIR)
-#endif /* _MSC_VER */
-
-/*
- * POSIX dirent interface
- */
-struct dirent {
- char d_name[FILENAME_MAX];
-};
-
-typedef struct DIR {
- HANDLE handle;
- WIN32_FIND_DATAW info;
- struct dirent result;
- char *name;
-} DIR;
-
-extern DIR *opendir(const char *name);
-extern int closedir(DIR *dir);
-extern struct dirent *readdir(DIR *dir);
+++ /dev/null
-/*
- vi:ts=8:sw=8:noet
- * Copyright (c) 2006 Luke Dunstan <infidel@users.sourceforge.net>
- * Partly based on code by David Kashtan, Validus Medical Systems
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * This file provides various functions that are available on desktop Windows
- * but not on Windows CE
- */
-
-#ifdef _MSC_VER
-/* Level 4 warnings caused by windows.h */
-#pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int
-#pragma warning(disable : 4115) // named type definition in parentheses
-#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
-#pragma warning(disable : 4514) // unreferenced inline function has been removed
-#pragma warning(disable : 4244) // conversion from 'int ' to 'unsigned short ', possible loss of data
-#pragma warning(disable : 4100) // unreferenced formal parameter
-#endif
-
-#include <windows.h>
-#include <stdlib.h>
-
-#include "compat_wince.h"
-
-
-static WCHAR *to_wide_string(LPCSTR pStr)
-{
- int nwide;
- WCHAR *buf;
-
- if(pStr == NULL)
- return NULL;
- nwide = MultiByteToWideChar(CP_ACP, 0, pStr, -1, NULL, 0);
- if(nwide == 0)
- return NULL;
- buf = malloc(nwide * sizeof(WCHAR));
- if(buf == NULL) {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return NULL;
- }
- if(MultiByteToWideChar(CP_ACP, 0, pStr, -1, buf, nwide) == 0) {
- free(buf);
- return NULL;
- }
- return buf;
-}
-
-FILE *fdopen(int handle, const char *mode)
-{
- WCHAR *wmode = to_wide_string(mode);
- FILE *result;
-
- if(wmode != NULL)
- result = _wfdopen((void *)handle, wmode);
- else
- result = NULL;
- free(wmode);
- return result;
-}
-
-/*
- * Time conversion constants
- */
-#define FT_EPOCH (116444736000000000i64)
-#define FT_TICKS (10000000i64)
-
- /*
- * Convert a FILETIME to a time_t
- */
-static time_t convert_FILETIME_to_time_t(FILETIME *File_Time)
-{
- __int64 Temp;
-
- /*
- * Convert the FILETIME structure to 100nSecs since 1601 (as a 64-bit value)
- */
- Temp = (((__int64)File_Time->dwHighDateTime) << 32) + (__int64)File_Time->dwLowDateTime;
- /*
- * Convert to seconds from 1970
- */
- return((time_t)((Temp - FT_EPOCH) / FT_TICKS));
-}
-
-/*
- * Convert a FILETIME to a tm structure
- */
-static struct tm *Convert_FILETIME_To_tm(FILETIME *File_Time)
-{
- SYSTEMTIME System_Time;
- static struct tm tm = {0};
- static const short Day_Of_Year_By_Month[12] = {(short)(0),
- (short)(31),
- (short)(31 + 28),
- (short)(31 + 28 + 31),
- (short)(31 + 28 + 31 + 30),
- (short)(31 + 28 + 31 + 30 + 31),
- (short)(31 + 28 + 31 + 30 + 31 + 30),
- (short)(31 + 28 + 31 + 30 + 31 + 30 + 31),
- (short)(31 + 28 + 31 + 30 + 31 + 30 + 31 + 31),
- (short)(31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30),
- (short)(31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31),
- (short)(31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30)};
-
-
- /*
- * Turn the FILETIME into a SYSTEMTIME
- */
- FileTimeToSystemTime(File_Time, &System_Time);
- /*
- * Use SYSTEMTIME to fill in the tm structure
- */
- tm.tm_sec = System_Time.wSecond;
- tm.tm_min = System_Time.wMinute;
- tm.tm_hour = System_Time.wHour;
- tm.tm_mday = System_Time.wDay;
- tm.tm_mon = System_Time.wMonth - 1;
- tm.tm_year = System_Time.wYear - 1900;
- tm.tm_wday = System_Time.wDayOfWeek;
- tm.tm_yday = Day_Of_Year_By_Month[tm.tm_mon] + tm.tm_mday - 1;
- if (tm.tm_mon >= 2) {
- /*
- * Check for leap year (every 4 years but not every 100 years but every 400 years)
- */
- if ((System_Time.wYear % 4) == 0) {
- /*
- * It Is a 4th year
- */
- if ((System_Time.wYear % 100) == 0) {
- /*
- * It is a 100th year
- */
- if ((System_Time.wYear % 400) == 0) {
- /*
- * It is a 400th year: It is a leap year
- */
- tm.tm_yday++;
- }
- } else {
- /*
- * It is not a 100th year: It is a leap year
- */
- tm.tm_yday++;
- }
- }
- }
- return(&tm);
-}
-
-/*
- * Convert a time_t to a FILETIME
- */
-static void Convert_time_t_To_FILETIME(time_t Time, FILETIME *File_Time)
-{
- __int64 Temp;
-
- /*
- * Use 64-bit calculation to convert seconds since 1970 to
- * 100nSecs since 1601
- */
- Temp = ((__int64)Time * FT_TICKS) + FT_EPOCH;
- /*
- * Put it into the FILETIME structure
- */
- File_Time->dwLowDateTime = (DWORD)Temp;
- File_Time->dwHighDateTime = (DWORD)(Temp >> 32);
-}
-
-/*
- * Convert a tm structure to a FILETIME
- */
-static FILETIME *Convert_tm_To_FILETIME(struct tm *tm)
-{
- SYSTEMTIME System_Time;
- static FILETIME File_Time = {0};
-
- /*
- * Use the tm structure to fill in a SYSTEM
- */
- System_Time.wYear = tm->tm_year + 1900;
- System_Time.wMonth = tm->tm_mon + 1;
- System_Time.wDayOfWeek = tm->tm_wday;
- System_Time.wDay = tm->tm_mday;
- System_Time.wHour = tm->tm_hour;
- System_Time.wMinute = tm->tm_min;
- System_Time.wSecond = tm->tm_sec;
- System_Time.wMilliseconds = 0;
- /*
- * Convert it to a FILETIME and return it
- */
- SystemTimeToFileTime(&System_Time, &File_Time);
- return(&File_Time);
-}
-
-
-/************************************************************************/
-/* */
-/* Errno emulation: There is no errno on Windows/CE and we need */
-/* to make it per-thread. So we have a function */
-/* that returns a pointer to the errno for the */
-/* current thread. */
-/* */
-/* If there is ONLY the main thread then we can */
-/* quickly return some static storage. */
-/* */
-/* If we have multiple threads running, we use */
-/* Thread-Local Storage to hold the pointer */
-/* */
-/************************************************************************/
-
-/*
- * Function pointer for returning errno pointer
- */
-static int *Initialize_Errno(void);
-int *(*__WinCE_Errno_Pointer_Function)(void) = Initialize_Errno;
-
-/*
- * Static errno storage for the main thread
- */
-static int Errno_Storage = 0;
-
-/*
- * Thread-Local storage slot for errno
- */
-static int TLS_Errno_Slot = 0xffffffff;
-
-/*
- * Number of threads we have running and critical section protection
- * for manipulating it
- */
-static int Number_Of_Threads = 0;
-static CRITICAL_SECTION Number_Of_Threads_Critical_Section;
-
-/*
- * For the main thread only -- return the errno pointer
- */
-static int *Get_Main_Thread_Errno(void)
-{
- return &Errno_Storage;
-}
-
-/*
- * When there is more than one thread -- return the errno pointer
- */
-static int *Get_Thread_Errno(void)
-{
- return (int *)TlsGetValue(TLS_Errno_Slot);
-}
-
-/*
- * Initialize a thread's errno
- */
-static void Initialize_Thread_Errno(int *Errno_Pointer)
-{
- /*
- * Make sure we have a slot
- */
- if (TLS_Errno_Slot == 0xffffffff) {
- /*
- * No: Get one
- */
- TLS_Errno_Slot = (int)TlsAlloc();
- if (TLS_Errno_Slot == 0xffffffff) ExitProcess(3);
- }
- /*
- * We can safely check for 0 threads, because
- * only the main thread will be initializing
- * at this point. Make sure the critical
- * section that protects the number of threads
- * is initialized
- */
- if (Number_Of_Threads == 0)
- InitializeCriticalSection(&Number_Of_Threads_Critical_Section);
- /*
- * Store the errno pointer
- */
- if (TlsSetValue(TLS_Errno_Slot, (LPVOID)Errno_Pointer) == 0) ExitProcess(3);
- /*
- * Bump the number of threads
- */
- EnterCriticalSection(&Number_Of_Threads_Critical_Section);
- Number_Of_Threads++;
- if (Number_Of_Threads > 1) {
- /*
- * We have threads other than the main thread:
- * Use thread-local storage
- */
- __WinCE_Errno_Pointer_Function = Get_Thread_Errno;
- }
- LeaveCriticalSection(&Number_Of_Threads_Critical_Section);
-}
-
-/*
- * Initialize errno emulation on Windows/CE (Main thread)
- */
-static int *Initialize_Errno(void)
-{
- /*
- * Initialize the main thread's errno in thread-local storage
- */
- Initialize_Thread_Errno(&Errno_Storage);
- /*
- * Set the errno function to be the one that returns the
- * main thread's errno
- */
- __WinCE_Errno_Pointer_Function = Get_Main_Thread_Errno;
- /*
- * Return the main thread's errno
- */
- return &Errno_Storage;
-}
-
-/*
- * Initialize errno emulation on Windows/CE (New thread)
- */
-void __WinCE_Errno_New_Thread(int *Errno_Pointer)
-{
- Initialize_Thread_Errno(Errno_Pointer);
-}
-
-/*
- * Note that a thread has exited
- */
-void __WinCE_Errno_Thread_Exit(void)
-{
- /*
- * Decrease the number of threads
- */
- EnterCriticalSection(&Number_Of_Threads_Critical_Section);
- Number_Of_Threads--;
- if (Number_Of_Threads <= 1) {
- /*
- * We only have the main thread
- */
- __WinCE_Errno_Pointer_Function = Get_Main_Thread_Errno;
- }
- LeaveCriticalSection(&Number_Of_Threads_Critical_Section);
-}
-
-
-char *
-strerror(int errnum)
-{
- return "(strerror not implemented)";
-}
-
-#define FT_EPOCH (116444736000000000i64)
-#define FT_TICKS (10000000i64)
-
-int
-_wstat(const WCHAR *path, struct _stat *buffer)
-{
- WIN32_FIND_DATA data;
- HANDLE handle;
- WCHAR *p;
-
- /* Fail if wildcard characters are specified */
- if (wcscspn(path, L"?*") != wcslen(path))
- return -1;
-
- handle = FindFirstFile(path, &data);
- if (handle == INVALID_HANDLE_VALUE) {
- errno = GetLastError();
- return -1;
- }
- FindClose(handle);
-
- /* Found: Convert the file times */
- buffer->st_mtime = convert_FILETIME_to_time_t(&data.ftLastWriteTime);
- if (data.ftLastAccessTime.dwLowDateTime || data.ftLastAccessTime.dwHighDateTime)
- buffer->st_atime = convert_FILETIME_to_time_t(&data.ftLastAccessTime);
- else
- buffer->st_atime = buffer->st_mtime;
- if (data.ftCreationTime.dwLowDateTime || data.ftCreationTime.dwHighDateTime)
- buffer->st_ctime = convert_FILETIME_to_time_t(&data.ftCreationTime);
- else
- buffer->st_ctime = buffer->st_mtime;
-
- /* Convert the file modes */
- buffer->st_mode = (unsigned short)((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? (S_IFDIR | S_IEXEC) : S_IFREG);
- buffer->st_mode |= (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : (S_IREAD | S_IWRITE);
- if((p = wcsrchr(path, L'.')) != NULL) {
- p++;
- if (_wcsicmp(p, L".exe") == 0)
- buffer->st_mode |= S_IEXEC;
- }
- buffer->st_mode |= (buffer->st_mode & 0700) >> 3;
- buffer->st_mode |= (buffer->st_mode & 0700) >> 6;
- /* Set the other information */
- buffer->st_nlink = 1;
- buffer->st_size = (unsigned long int)data.nFileSizeLow;
- buffer->st_uid = 0;
- buffer->st_gid = 0;
- buffer->st_ino = 0 /*data.dwOID ?*/;
- buffer->st_dev = 0;
-
- return 0; /* success */
-}
-
-/*
- * Helper function for cemodule -- do an fstat() operation on a Win32 File Handle
- */
-int
-_fstat(int handle, struct _stat *st)
-{
- BY_HANDLE_FILE_INFORMATION Data;
-
- /*
- * Get the file information
- */
- if (!GetFileInformationByHandle((HANDLE)handle, &Data)) {
- /*
- * Return error
- */
- errno = GetLastError();
- return(-1);
- }
- /*
- * Found: Convert the file times
- */
- st->st_mtime=(time_t)((*(__int64*)&Data.ftLastWriteTime-FT_EPOCH)/FT_TICKS);
- if(Data.ftLastAccessTime.dwLowDateTime || Data.ftLastAccessTime.dwHighDateTime)
- st->st_atime=(time_t)((*(__int64*)&Data.ftLastAccessTime-FT_EPOCH)/FT_TICKS);
- else
- st->st_atime=st->st_mtime ;
- if(Data.ftCreationTime.dwLowDateTime || Data.ftCreationTime.dwHighDateTime )
- st->st_ctime=(time_t)((*(__int64*)&Data.ftCreationTime-FT_EPOCH)/FT_TICKS);
- else
- st->st_ctime=st->st_mtime ;
- /*
- * Convert the file modes
- */
- st->st_mode = (unsigned short)((Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? (S_IFDIR | S_IEXEC) : S_IFREG);
- st->st_mode |= (Data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : (S_IREAD | S_IWRITE);
- st->st_mode |= (st->st_mode & 0700) >> 3;
- st->st_mode |= (st->st_mode & 0700) >> 6;
- /*
- * Set the other information
- */
- st->st_nlink=1;
- st->st_size=(unsigned long int)Data.nFileSizeLow;
- st->st_uid=0;
- st->st_gid=0;
- st->st_ino=0;
- st->st_dev=0;
- /*
- * Return success
- */
- return(0);
-}
-
-int _wopen(const wchar_t *filename, int oflag, ...)
-{
- DWORD Access, ShareMode, CreationDisposition;
- HANDLE Handle;
- static int Modes[4] = {0, (GENERIC_READ | GENERIC_WRITE), GENERIC_READ, GENERIC_WRITE};
-
- /*
- * Calculate the CreateFile arguments
- */
- Access = Modes[oflag & O_MODE_MASK];
- ShareMode = (oflag & O_EXCL) ? 0 : (FILE_SHARE_READ | FILE_SHARE_WRITE);
- if (oflag & O_TRUNC)
- CreationDisposition = (oflag & O_CREAT) ? CREATE_ALWAYS : TRUNCATE_EXISTING;
- else
- CreationDisposition = (oflag & O_CREAT) ? CREATE_NEW : OPEN_EXISTING;
-
- Handle = CreateFileW(filename, Access, ShareMode, NULL, CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
-
- /*
- * Deal with errors
- */
- if (Handle == INVALID_HANDLE_VALUE) {
- errno = GetLastError();
- if ((errno == ERROR_ALREADY_EXISTS) || (errno == ERROR_FILE_EXISTS))
- errno = ERROR_ALREADY_EXISTS;
- return -1;
- }
- /*
- * Return the handle
- */
- return (int)Handle;
-}
-
-int
-_close(int handle)
-{
- if(CloseHandle((HANDLE)handle))
- return 0;
- errno = GetLastError();
- return -1;
-}
-
-int
-_write(int handle, const void *buffer, unsigned int count)
-{
- DWORD numwritten = 0;
- if(!WriteFile((HANDLE)handle, buffer, count, &numwritten, NULL)) {
- errno = GetLastError();
- return -1;
- }
- return numwritten;
-}
-
-int
-_read(int handle, void *buffer, unsigned int count)
-{
- DWORD numread = 0;
- if(!ReadFile((HANDLE)handle, buffer, count, &numread, NULL)) {
- errno = GetLastError();
- return -1;
- }
- return numread;
-}
-
-long
-_lseek(int handle, long offset, int origin)
-{
- DWORD dwMoveMethod;
- DWORD result;
-
- switch(origin) {
- default:
- errno = EINVAL;
- return -1L;
- case SEEK_SET:
- dwMoveMethod = FILE_BEGIN;
- break;
- case SEEK_CUR:
- dwMoveMethod = FILE_CURRENT;
- break;
- case SEEK_END:
- dwMoveMethod = FILE_END;
- break;
- }
- result = SetFilePointer((HANDLE)handle, offset, NULL, dwMoveMethod);
- if(result == 0xFFFFFFFF) {
- errno = GetLastError();
- return -1;
- }
- return (long)result;
-}
-
-int
-_wmkdir(const wchar_t *dirname)
-{
- if(!CreateDirectoryW(dirname, NULL)) {
- errno = GetLastError();
- return -1;
- }
- return 0;
-}
-
-int
-_wremove(const wchar_t *filename)
-{
- if(!DeleteFileW(filename)) {
- errno = GetLastError();
- return -1;
- }
- return 0;
-}
-
-int
-_wrename(const wchar_t *oldname, const wchar_t *newname)
-{
- if(!MoveFileW(oldname, newname)) {
- errno = GetLastError();
- return -1;
- }
- return 0;
-}
-
-wchar_t *
-_wgetcwd(wchar_t *buffer, int maxlen)
-{
- wchar_t *result;
- WCHAR wszPath[MAX_PATH + 1];
- WCHAR *p;
-
- if(!GetModuleFileNameW(NULL, wszPath, MAX_PATH + 1)) {
- errno = GetLastError();
- return NULL;
- }
- /* Remove the filename part of the path to leave the directory */
- p = wcsrchr(wszPath, L'\\');
- if(p)
- *p = L'\0';
-
- if(buffer == NULL)
- result = _wcsdup(wszPath);
- else if(wcslen(wszPath) + 1 > (size_t)maxlen) {
- result = NULL;
- errno = ERROR_INSUFFICIENT_BUFFER;
- } else {
- wcsncpy(buffer, wszPath, maxlen);
- buffer[maxlen - 1] = L'\0';
- result = buffer;
- }
- return result;
-}
-
-/*
- * The missing "C" runtime gmtime() function
- */
-struct tm *gmtime(const time_t *TimeP)
-{
- FILETIME File_Time;
-
- /*
- * Deal with null time pointer
- */
- if (!TimeP) return(NULL);
- /*
- * time_t -> FILETIME -> tm
- */
- Convert_time_t_To_FILETIME(*TimeP, &File_Time);
- return(Convert_FILETIME_To_tm(&File_Time));
-}
-
-/*
- * The missing "C" runtime localtime() function
- */
-struct tm *localtime(const time_t *TimeP)
-{
- FILETIME File_Time, Local_File_Time;
-
- /*
- * Deal with null time pointer
- */
- if (!TimeP) return(NULL);
- /*
- * time_t -> FILETIME -> Local FILETIME -> tm
- */
- Convert_time_t_To_FILETIME(*TimeP, &File_Time);
- FileTimeToLocalFileTime(&File_Time, &Local_File_Time);
- return(Convert_FILETIME_To_tm(&Local_File_Time));
-}
-
-/*
- * The missing "C" runtime mktime() function
- */
-time_t mktime(struct tm *tm)
-{
- FILETIME *Local_File_Time;
- FILETIME File_Time;
-
- /*
- * tm -> Local FILETIME -> FILETIME -> time_t
- */
- Local_File_Time = Convert_tm_To_FILETIME(tm);
- LocalFileTimeToFileTime(Local_File_Time, &File_Time);
- return(convert_FILETIME_to_time_t(&File_Time));
-}
-
-/*
- * Missing "C" runtime time() function
- */
-time_t time(time_t *TimeP)
-{
- SYSTEMTIME System_Time;
- FILETIME File_Time;
- time_t Result;
-
- /*
- * Get the current system time
- */
- GetSystemTime(&System_Time);
- /*
- * SYSTEMTIME -> FILETIME -> time_t
- */
- SystemTimeToFileTime(&System_Time, &File_Time);
- Result = convert_FILETIME_to_time_t(&File_Time);
- /*
- * Return the time_t
- */
- if (TimeP) *TimeP = Result;
- return(Result);
-}
-
-static char Standard_Name[32] = "GMT";
-static char Daylight_Name[32] = "GMT";
-char *tzname[2] = {Standard_Name, Daylight_Name};
-long timezone = 0;
-int daylight = 0;
-
-void tzset(void)
-{
- TIME_ZONE_INFORMATION Info;
- int Result;
-
- /*
- * Get our current timezone information
- */
- Result = GetTimeZoneInformation(&Info);
- switch(Result) {
- /*
- * We are on standard time
- */
- case TIME_ZONE_ID_STANDARD:
- daylight = 0;
- break;
- /*
- * We are on daylight savings time
- */
- case TIME_ZONE_ID_DAYLIGHT:
- daylight = 1;
- break;
- /*
- * We don't know the timezone information (leave it GMT)
- */
- default: return;
- }
- /*
- * Extract the timezone information
- */
- timezone = Info.Bias * 60;
- if (Info.StandardName[0])
- WideCharToMultiByte(CP_ACP, 0, Info.StandardName, -1, Standard_Name, sizeof(Standard_Name) - 1, NULL, NULL);
- if (Info.DaylightName[0])
- WideCharToMultiByte(CP_ACP, 0, Info.DaylightName, -1, Daylight_Name, sizeof(Daylight_Name) - 1, NULL, NULL);
-}
-
-/*** strftime() from newlib libc/time/strftime.c ***/
-
-/*
- * Sane snprintf(). Acts like snprintf(), but never return -1 or the
- * value bigger than supplied buffer.
- */
-static int
-Snprintf(char *buf, size_t buflen, const char *fmt, ...)
-{
- va_list ap;
- int n;
-
- if (buflen == 0)
- return (0);
-
- va_start(ap, fmt);
- n = _vsnprintf(buf, buflen, fmt, ap);
- va_end(ap);
-
- if (n < 0 || n > (int) buflen - 1) {
- n = buflen - 1;
- }
- buf[n] = '\0';
-
- return (n);
-}
-
-#define snprintf Snprintf
-
-/* from libc/include/_ansi.h */
-#define _CONST const
-#define _DEFUN(name, arglist, args) name(args)
-#define _AND ,
-/* from libc/time/local.h */
-#define TZ_LOCK
-#define TZ_UNLOCK
-#define _tzname tzname
-#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
-#define YEAR_BASE 1900
-#define SECSPERMIN 60L
-#define MINSPERHOUR 60L
-#define HOURSPERDAY 24L
-#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
-
-/*
- * strftime.c
- * Original Author: G. Haley
- * Additions from: Eric Blake
- *
- * Places characters into the array pointed to by s as controlled by the string
- * pointed to by format. If the total number of resulting characters including
- * the terminating null character is not more than maxsize, returns the number
- * of characters placed into the array pointed to by s (not including the
- * terminating null character); otherwise zero is returned and the contents of
- * the array indeterminate.
- */
-
-/*
-FUNCTION
-<<strftime>>---flexible calendar time formatter
-
-INDEX
- strftime
-
-ANSI_SYNOPSIS
- #include <time.h>
- size_t strftime(char *<[s]>, size_t <[maxsize]>,
- const char *<[format]>, const struct tm *<[timp]>);
-
-TRAD_SYNOPSIS
- #include <time.h>
- size_t strftime(<[s]>, <[maxsize]>, <[format]>, <[timp]>)
- char *<[s]>;
- size_t <[maxsize]>;
- char *<[format]>;
- struct tm *<[timp]>;
-
-DESCRIPTION
-<<strftime>> converts a <<struct tm>> representation of the time (at
-<[timp]>) into a null-terminated string, starting at <[s]> and occupying
-no more than <[maxsize]> characters.
-
-You control the format of the output using the string at <[format]>.
-<<*<[format]>>> can contain two kinds of specifications: text to be
-copied literally into the formatted string, and time conversion
-specifications. Time conversion specifications are two- and
-three-character sequences beginning with `<<%>>' (use `<<%%>>' to
-include a percent sign in the output). Each defined conversion
-specification selects only the specified field(s) of calendar time
-data from <<*<[timp]>>>, and converts it to a string in one of the
-following ways:
-
-o+
-o %a
-A three-letter abbreviation for the day of the week. [tm_wday]
-
-o %A
-The full name for the day of the week, one of `<<Sunday>>',
-`<<Monday>>', `<<Tuesday>>', `<<Wednesday>>', `<<Thursday>>',
-`<<Friday>>', or `<<Saturday>>'. [tm_wday]
-
-o %b
-A three-letter abbreviation for the month name. [tm_mon]
-
-o %B
-The full name of the month, one of `<<January>>', `<<February>>',
-`<<March>>', `<<April>>', `<<May>>', `<<June>>', `<<July>>',
-`<<August>>', `<<September>>', `<<October>>', `<<November>>',
-`<<December>>'. [tm_mon]
-
-o %c
-A string representing the complete date and time, in the form
-`<<"%a %b %e %H:%M:%S %Y">>' (example "Mon Apr 01 13:13:13
-1992"). [tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday]
-
-o %C
-The century, that is, the year divided by 100 then truncated. For
-4-digit years, the result is zero-padded and exactly two characters;
-but for other years, there may a negative sign or more digits. In
-this way, `<<%C%y>>' is equivalent to `<<%Y>>'. [tm_year]
-
-o %d
-The day of the month, formatted with two digits (from `<<01>>' to
-`<<31>>'). [tm_mday]
-
-o %D
-A string representing the date, in the form `<<"%m/%d/%y">>'.
-[tm_mday, tm_mon, tm_year]
-
-o %e
-The day of the month, formatted with leading space if single digit
-(from `<<1>>' to `<<31>>'). [tm_mday]
-
-o %E<<x>>
-In some locales, the E modifier selects alternative representations of
-certain modifiers <<x>>. But in the "C" locale supported by newlib,
-it is ignored, and treated as %<<x>>.
-
-o %F
-A string representing the ISO 8601:2000 date format, in the form
-`<<"%Y-%m-%d">>'. [tm_mday, tm_mon, tm_year]
-
-o %g
-The last two digits of the week-based year, see specifier %G (from
-`<<00>>' to `<<99>>'). [tm_year, tm_wday, tm_yday]
-
-o %G
-The week-based year. In the ISO 8601:2000 calendar, week 1 of the year
-includes January 4th, and begin on Mondays. Therefore, if January 1st,
-2nd, or 3rd falls on a Sunday, that day and earlier belong to the last
-week of the previous year; and if December 29th, 30th, or 31st falls
-on Monday, that day and later belong to week 1 of the next year. For
-consistency with %Y, it always has at least four characters.
-Example: "%G" for Saturday 2nd January 1999 gives "1998", and for
-Tuesday 30th December 1997 gives "1998". [tm_year, tm_wday, tm_yday]
-
-o %h
-A three-letter abbreviation for the month name (synonym for
-"%b"). [tm_mon]
-
-o %H
-The hour (on a 24-hour clock), formatted with two digits (from
-`<<00>>' to `<<23>>'). [tm_hour]
-
-o %I
-The hour (on a 12-hour clock), formatted with two digits (from
-`<<01>>' to `<<12>>'). [tm_hour]
-
-o %j
-The count of days in the year, formatted with three digits
-(from `<<001>>' to `<<366>>'). [tm_yday]
-
-o %k
-The hour (on a 24-hour clock), formatted with leading space if single
-digit (from `<<0>>' to `<<23>>'). Non-POSIX extension. [tm_hour]
-
-o %l
-The hour (on a 12-hour clock), formatted with leading space if single
-digit (from `<<1>>' to `<<12>>'). Non-POSIX extension. [tm_hour]
-
-o %m
-The month number, formatted with two digits (from `<<01>>' to `<<12>>').
-[tm_mon]
-
-o %M
-The minute, formatted with two digits (from `<<00>>' to `<<59>>'). [tm_min]
-
-o %n
-A newline character (`<<\n>>').
-
-o %O<<x>>
-In some locales, the O modifier selects alternative digit characters
-for certain modifiers <<x>>. But in the "C" locale supported by newlib, it
-is ignored, and treated as %<<x>>.
-
-o %p
-Either `<<AM>>' or `<<PM>>' as appropriate. [tm_hour]
-
-o %r
-The 12-hour time, to the second. Equivalent to "%I:%M:%S %p". [tm_sec,
-tm_min, tm_hour]
-
-o %R
-The 24-hour time, to the minute. Equivalent to "%H:%M". [tm_min, tm_hour]
-
-o %S
-The second, formatted with two digits (from `<<00>>' to `<<60>>'). The
-value 60 accounts for the occasional leap second. [tm_sec]
-
-o %t
-A tab character (`<<\t>>').
-
-o %T
-The 24-hour time, to the second. Equivalent to "%H:%M:%S". [tm_sec,
-tm_min, tm_hour]
-
-o %u
-The weekday as a number, 1-based from Monday (from `<<1>>' to
-`<<7>>'). [tm_wday]
-
-o %U
-The week number, where weeks start on Sunday, week 1 contains the first
-Sunday in a year, and earlier days are in week 0. Formatted with two
-digits (from `<<00>>' to `<<53>>'). See also <<%W>>. [tm_wday, tm_yday]
-
-o %V
-The week number, where weeks start on Monday, week 1 contains January 4th,
-and earlier days are in the previous year. Formatted with two digits
-(from `<<01>>' to `<<53>>'). See also <<%G>>. [tm_year, tm_wday, tm_yday]
-
-o %w
-The weekday as a number, 0-based from Sunday (from `<<0>>' to `<<6>>').
-[tm_wday]
-
-o %W
-The week number, where weeks start on Monday, week 1 contains the first
-Monday in a year, and earlier days are in week 0. Formatted with two
-digits (from `<<00>>' to `<<53>>'). [tm_wday, tm_yday]
-
-o %x
-A string representing the complete date, equivalent to "%m/%d/%y".
-[tm_mon, tm_mday, tm_year]
-
-o %X
-A string representing the full time of day (hours, minutes, and
-seconds), equivalent to "%H:%M:%S". [tm_sec, tm_min, tm_hour]
-
-o %y
-The last two digits of the year (from `<<00>>' to `<<99>>'). [tm_year]
-
-o %Y
-The full year, equivalent to <<%C%y>>. It will always have at least four
-characters, but may have more. The year is accurate even when tm_year
-added to the offset of 1900 overflows an int. [tm_year]
-
-o %z
-The offset from UTC. The format consists of a sign (negative is west of
-Greewich), two characters for hour, then two characters for minutes
-(-hhmm or +hhmm). If tm_isdst is negative, the offset is unknown and no
-output is generated; if it is zero, the offset is the standard offset for
-the current time zone; and if it is positive, the offset is the daylight
-savings offset for the current timezone. The offset is determined from
-the TZ environment variable, as if by calling tzset(). [tm_isdst]
-
-o %Z
-The time zone name. If tm_isdst is negative, no output is generated.
-Otherwise, the time zone name is based on the TZ environment variable,
-as if by calling tzset(). [tm_isdst]
-
-o %%
-A single character, `<<%>>'.
-o-
-
-RETURNS
-When the formatted time takes up no more than <[maxsize]> characters,
-the result is the length of the formatted string. Otherwise, if the
-formatting operation was abandoned due to lack of room, the result is
-<<0>>, and the string starting at <[s]> corresponds to just those
-parts of <<*<[format]>>> that could be completely filled in within the
-<[maxsize]> limit.
-
-PORTABILITY
-ANSI C requires <<strftime>>, but does not specify the contents of
-<<*<[s]>>> when the formatted string would require more than
-<[maxsize]> characters. Unrecognized specifiers and fields of
-<<timp>> that are out of range cause undefined results. Since some
-formats expand to 0 bytes, it is wise to set <<*<[s]>>> to a nonzero
-value beforehand to distinguish between failure and an empty string.
-This implementation does not support <<s>> being NULL, nor overlapping
-<<s>> and <<format>>.
-
-<<strftime>> requires no supporting OS subroutines.
-*/
-
-static _CONST int dname_len[7] =
-{6, 6, 7, 9, 8, 6, 8};
-
-static _CONST char *_CONST dname[7] =
-{"Sunday", "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday"};
-
-static _CONST int mname_len[12] =
-{7, 8, 5, 5, 3, 4, 4, 6, 9, 7, 8, 8};
-
-static _CONST char *_CONST mname[12] =
-{"January", "February", "March", "April",
- "May", "June", "July", "August", "September", "October", "November",
- "December"};
-
-/* Using the tm_year, tm_wday, and tm_yday components of TIM_P, return
- -1, 0, or 1 as the adjustment to add to the year for the ISO week
- numbering used in "%g%G%V", avoiding overflow. */
-static int
-_DEFUN (iso_year_adjust, (tim_p),
- _CONST struct tm *tim_p)
-{
- /* Account for fact that tm_year==0 is year 1900. */
- int leap = isleap (tim_p->tm_year + (YEAR_BASE
- - (tim_p->tm_year < 0 ? 0 : 2000)));
-
- /* Pack the yday, wday, and leap year into a single int since there are so
- many disparate cases. */
-#define PACK(yd, wd, lp) (((yd) << 4) + (wd << 1) + (lp))
- switch (PACK (tim_p->tm_yday, tim_p->tm_wday, leap))
- {
- case PACK (0, 5, 0): /* Jan 1 is Fri, not leap. */
- case PACK (0, 6, 0): /* Jan 1 is Sat, not leap. */
- case PACK (0, 0, 0): /* Jan 1 is Sun, not leap. */
- case PACK (0, 5, 1): /* Jan 1 is Fri, leap year. */
- case PACK (0, 6, 1): /* Jan 1 is Sat, leap year. */
- case PACK (0, 0, 1): /* Jan 1 is Sun, leap year. */
- case PACK (1, 6, 0): /* Jan 2 is Sat, not leap. */
- case PACK (1, 0, 0): /* Jan 2 is Sun, not leap. */
- case PACK (1, 6, 1): /* Jan 2 is Sat, leap year. */
- case PACK (1, 0, 1): /* Jan 2 is Sun, leap year. */
- case PACK (2, 0, 0): /* Jan 3 is Sun, not leap. */
- case PACK (2, 0, 1): /* Jan 3 is Sun, leap year. */
- return -1; /* Belongs to last week of previous year. */
- case PACK (362, 1, 0): /* Dec 29 is Mon, not leap. */
- case PACK (363, 1, 1): /* Dec 29 is Mon, leap year. */
- case PACK (363, 1, 0): /* Dec 30 is Mon, not leap. */
- case PACK (363, 2, 0): /* Dec 30 is Tue, not leap. */
- case PACK (364, 1, 1): /* Dec 30 is Mon, leap year. */
- case PACK (364, 2, 1): /* Dec 30 is Tue, leap year. */
- case PACK (364, 1, 0): /* Dec 31 is Mon, not leap. */
- case PACK (364, 2, 0): /* Dec 31 is Tue, not leap. */
- case PACK (364, 3, 0): /* Dec 31 is Wed, not leap. */
- case PACK (365, 1, 1): /* Dec 31 is Mon, leap year. */
- case PACK (365, 2, 1): /* Dec 31 is Tue, leap year. */
- case PACK (365, 3, 1): /* Dec 31 is Wed, leap year. */
- return 1; /* Belongs to first week of next year. */
- }
- return 0; /* Belongs to specified year. */
-#undef PACK
-}
-
-size_t
-_DEFUN (strftime, (s, maxsize, format, tim_p),
- char *s _AND
- size_t maxsize _AND
- _CONST char *format _AND
- _CONST struct tm *tim_p)
-{
- size_t count = 0;
- int i;
-
- for (;;)
- {
- while (*format && *format != '%')
- {
- if (count < maxsize - 1)
- s[count++] = *format++;
- else
- return 0;
- }
-
- if (*format == '\0')
- break;
-
- format++;
- if (*format == 'E' || *format == 'O')
- format++;
-
- switch (*format)
- {
- case 'a':
- for (i = 0; i < 3; i++)
- {
- if (count < maxsize - 1)
- s[count++] =
- dname[tim_p->tm_wday][i];
- else
- return 0;
- }
- break;
- case 'A':
- for (i = 0; i < dname_len[tim_p->tm_wday]; i++)
- {
- if (count < maxsize - 1)
- s[count++] =
- dname[tim_p->tm_wday][i];
- else
- return 0;
- }
- break;
- case 'b':
- case 'h':
- for (i = 0; i < 3; i++)
- {
- if (count < maxsize - 1)
- s[count++] =
- mname[tim_p->tm_mon][i];
- else
- return 0;
- }
- break;
- case 'B':
- for (i = 0; i < mname_len[tim_p->tm_mon]; i++)
- {
- if (count < maxsize - 1)
- s[count++] =
- mname[tim_p->tm_mon][i];
- else
- return 0;
- }
- break;
- case 'c':
- {
- /* Length is not known because of %C%y, so recurse. */
- size_t adjust = strftime (&s[count], maxsize - count,
- "%a %b %e %H:%M:%S %C%y", tim_p);
- if (adjust > 0)
- count += adjust;
- else
- return 0;
- }
- break;
- case 'C':
- {
- /* Examples of (tm_year + YEAR_BASE) that show how %Y == %C%y
- with 32-bit int.
- %Y %C %y
- 2147485547 21474855 47
- 10000 100 00
- 9999 99 99
- 0999 09 99
- 0099 00 99
- 0001 00 01
- 0000 00 00
- -001 -0 01
- -099 -0 99
- -999 -9 99
- -1000 -10 00
- -10000 -100 00
- -2147481748 -21474817 48
-
- Be careful of both overflow and sign adjustment due to the
- asymmetric range of years.
- */
- int neg = tim_p->tm_year < -YEAR_BASE;
- int century = tim_p->tm_year >= 0
- ? tim_p->tm_year / 100 + YEAR_BASE / 100
- : abs (tim_p->tm_year + YEAR_BASE) / 100;
- count += snprintf (&s[count], maxsize - count, "%s%.*d",
- neg ? "-" : "", 2 - neg, century);
- if (count >= maxsize)
- return 0;
- }
- break;
- case 'd':
- case 'e':
- if (count < maxsize - 2)
- {
- sprintf (&s[count], *format == 'd' ? "%.2d" : "%2d",
- tim_p->tm_mday);
- count += 2;
- }
- else
- return 0;
- break;
- case 'D':
- case 'x':
- /* %m/%d/%y */
- if (count < maxsize - 8)
- {
- sprintf (&s[count], "%.2d/%.2d/%.2d",
- tim_p->tm_mon + 1, tim_p->tm_mday,
- tim_p->tm_year >= 0 ? tim_p->tm_year % 100
- : abs (tim_p->tm_year + YEAR_BASE) % 100);
- count += 8;
- }
- else
- return 0;
- break;
- case 'F':
- {
- /* Length is not known because of %C%y, so recurse. */
- size_t adjust = strftime (&s[count], maxsize - count,
- "%C%y-%m-%d", tim_p);
- if (adjust > 0)
- count += adjust;
- else
- return 0;
- }
- break;
- case 'g':
- if (count < maxsize - 2)
- {
- /* Be careful of both overflow and negative years, thanks to
- the asymmetric range of years. */
- int adjust = iso_year_adjust (tim_p);
- int year = tim_p->tm_year >= 0 ? tim_p->tm_year % 100
- : abs (tim_p->tm_year + YEAR_BASE) % 100;
- if (adjust < 0 && tim_p->tm_year <= -YEAR_BASE)
- adjust = 1;
- else if (adjust > 0 && tim_p->tm_year < -YEAR_BASE)
- adjust = -1;
- sprintf (&s[count], "%.2d",
- ((year + adjust) % 100 + 100) % 100);
- count += 2;
- }
- else
- return 0;
- break;
- case 'G':
- {
- /* See the comments for 'C' and 'Y'; this is a variable length
- field. Although there is no requirement for a minimum number
- of digits, we use 4 for consistency with 'Y'. */
- int neg = tim_p->tm_year < -YEAR_BASE;
- int adjust = iso_year_adjust (tim_p);
- int century = tim_p->tm_year >= 0
- ? tim_p->tm_year / 100 + YEAR_BASE / 100
- : abs (tim_p->tm_year + YEAR_BASE) / 100;
- int year = tim_p->tm_year >= 0 ? tim_p->tm_year % 100
- : abs (tim_p->tm_year + YEAR_BASE) % 100;
- if (adjust < 0 && tim_p->tm_year <= -YEAR_BASE)
- neg = adjust = 1;
- else if (adjust > 0 && neg)
- adjust = -1;
- year += adjust;
- if (year == -1)
- {
- year = 99;
- --century;
- }
- else if (year == 100)
- {
- year = 0;
- ++century;
- }
- count += snprintf (&s[count], maxsize - count, "%s%.*d%.2d",
- neg ? "-" : "", 2 - neg, century, year);
- if (count >= maxsize)
- return 0;
- }
- break;
- case 'H':
- case 'k':
- if (count < maxsize - 2)
- {
- sprintf (&s[count], *format == 'k' ? "%2d" : "%.2d",
- tim_p->tm_hour);
- count += 2;
- }
- else
- return 0;
- break;
- case 'I':
- case 'l':
- if (count < maxsize - 2)
- {
- if (tim_p->tm_hour == 0 ||
- tim_p->tm_hour == 12)
- {
- s[count++] = '1';
- s[count++] = '2';
- }
- else
- {
- sprintf (&s[count], *format == 'I' ? "%.2d" : "%2d",
- tim_p->tm_hour % 12);
- count += 2;
- }
- }
- else
- return 0;
- break;
- case 'j':
- if (count < maxsize - 3)
- {
- sprintf (&s[count], "%.3d",
- tim_p->tm_yday + 1);
- count += 3;
- }
- else
- return 0;
- break;
- case 'm':
- if (count < maxsize - 2)
- {
- sprintf (&s[count], "%.2d",
- tim_p->tm_mon + 1);
- count += 2;
- }
- else
- return 0;
- break;
- case 'M':
- if (count < maxsize - 2)
- {
- sprintf (&s[count], "%.2d",
- tim_p->tm_min);
- count += 2;
- }
- else
- return 0;
- break;
- case 'n':
- if (count < maxsize - 1)
- s[count++] = '\n';
- else
- return 0;
- break;
- case 'p':
- if (count < maxsize - 2)
- {
- if (tim_p->tm_hour < 12)
- s[count++] = 'A';
- else
- s[count++] = 'P';
-
- s[count++] = 'M';
- }
- else
- return 0;
- break;
- case 'r':
- if (count < maxsize - 11)
- {
- if (tim_p->tm_hour == 0 ||
- tim_p->tm_hour == 12)
- {
- s[count++] = '1';
- s[count++] = '2';
- }
- else
- {
- sprintf (&s[count], "%.2d", tim_p->tm_hour % 12);
- count += 2;
- }
- s[count++] = ':';
- sprintf (&s[count], "%.2d",
- tim_p->tm_min);
- count += 2;
- s[count++] = ':';
- sprintf (&s[count], "%.2d",
- tim_p->tm_sec);
- count += 2;
- s[count++] = ' ';
- if (tim_p->tm_hour < 12)
- s[count++] = 'A';
- else
- s[count++] = 'P';
-
- s[count++] = 'M';
- }
- else
- return 0;
- break;
- case 'R':
- if (count < maxsize - 5)
- {
- sprintf (&s[count], "%.2d:%.2d", tim_p->tm_hour, tim_p->tm_min);
- count += 5;
- }
- else
- return 0;
- break;
- case 'S':
- if (count < maxsize - 2)
- {
- sprintf (&s[count], "%.2d",
- tim_p->tm_sec);
- count += 2;
- }
- else
- return 0;
- break;
- case 't':
- if (count < maxsize - 1)
- s[count++] = '\t';
- else
- return 0;
- break;
- case 'T':
- case 'X':
- if (count < maxsize - 8)
- {
- sprintf (&s[count], "%.2d:%.2d:%.2d", tim_p->tm_hour,
- tim_p->tm_min, tim_p->tm_sec);
- count += 8;
- }
- else
- return 0;
- break;
- case 'u':
- if (count < maxsize - 1)
- {
- if (tim_p->tm_wday == 0)
- s[count++] = '7';
- else
- s[count++] = '0' + tim_p->tm_wday;
- }
- else
- return 0;
- break;
- case 'U':
- if (count < maxsize - 2)
- {
- sprintf (&s[count], "%.2d",
- (tim_p->tm_yday + 7 -
- tim_p->tm_wday) / 7);
- count += 2;
- }
- else
- return 0;
- break;
- case 'V':
- if (count < maxsize - 2)
- {
- int adjust = iso_year_adjust (tim_p);
- int wday = (tim_p->tm_wday) ? tim_p->tm_wday - 1 : 6;
- int week = (tim_p->tm_yday + 10 - wday) / 7;
- if (adjust > 0)
- week = 1;
- else if (adjust < 0)
- /* Previous year has 53 weeks if current year starts on
- Fri, and also if current year starts on Sat and
- previous year was leap year. */
- week = 52 + (4 >= (wday - tim_p->tm_yday
- - isleap (tim_p->tm_year
- + (YEAR_BASE - 1
- - (tim_p->tm_year < 0
- ? 0 : 2000)))));
- sprintf (&s[count], "%.2d", week);
- count += 2;
- }
- else
- return 0;
- break;
- case 'w':
- if (count < maxsize - 1)
- s[count++] = '0' + tim_p->tm_wday;
- else
- return 0;
- break;
- case 'W':
- if (count < maxsize - 2)
- {
- int wday = (tim_p->tm_wday) ? tim_p->tm_wday - 1 : 6;
- sprintf (&s[count], "%.2d",
- (tim_p->tm_yday + 7 - wday) / 7);
- count += 2;
- }
- else
- return 0;
- break;
- case 'y':
- if (count < maxsize - 2)
- {
- /* Be careful of both overflow and negative years, thanks to
- the asymmetric range of years. */
- int year = tim_p->tm_year >= 0 ? tim_p->tm_year % 100
- : abs (tim_p->tm_year + YEAR_BASE) % 100;
- sprintf (&s[count], "%.2d", year);
- count += 2;
- }
- else
- return 0;
- break;
- case 'Y':
- {
- /* Length is not known because of %C%y, so recurse. */
- size_t adjust = strftime (&s[count], maxsize - count,
- "%C%y", tim_p);
- if (adjust > 0)
- count += adjust;
- else
- return 0;
- }
- break;
- case 'z':
-#ifndef _WIN32_WCE
- if (tim_p->tm_isdst >= 0)
- {
- if (count < maxsize - 5)
- {
- long offset;
- __tzinfo_type *tz = __gettzinfo ();
- TZ_LOCK;
- /* The sign of this is exactly opposite the envvar TZ. We
- could directly use the global _timezone for tm_isdst==0,
- but have to use __tzrule for daylight savings. */
- offset = -tz->__tzrule[tim_p->tm_isdst > 0].offset;
- TZ_UNLOCK;
- sprintf (&s[count], "%+03ld%.2ld", offset / SECSPERHOUR,
- labs (offset / SECSPERMIN) % 60L);
- count += 5;
- }
- else
- return 0;
- }
- break;
-#endif
- case 'Z':
- if (tim_p->tm_isdst >= 0)
- {
- int size;
- TZ_LOCK;
- size = strlen(_tzname[tim_p->tm_isdst > 0]);
- for (i = 0; i < size; i++)
- {
- if (count < maxsize - 1)
- s[count++] = _tzname[tim_p->tm_isdst > 0][i];
- else
- {
- TZ_UNLOCK;
- return 0;
- }
- }
- TZ_UNLOCK;
- }
- break;
- case '%':
- if (count < maxsize - 1)
- s[count++] = '%';
- else
- return 0;
- break;
- }
- if (*format)
- format++;
- else
- break;
- }
- if (maxsize)
- s[count] = '\0';
-
- return count;
-}
+++ /dev/null
-
-#ifndef INCLUDE_WINCE_COMPAT_H
-#define INCLUDE_WINCE_COMPAT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*** ANSI C library ***/
-
-/* Missing ANSI C definitions */
-
-#define BUFSIZ 4096
-
-#define ENOMEM ERROR_NOT_ENOUGH_MEMORY
-#define EBADF ERROR_INVALID_HANDLE
-#define EINVAL ERROR_INVALID_PARAMETER
-#define ENOENT ERROR_FILE_NOT_FOUND
-#define ERANGE ERROR_INSUFFICIENT_BUFFER
-#define EINTR WSAEINTR
-
-/*
- * Because we need a per-thread errno, we define a function
- * pointer that we can call to return a pointer to the errno
- * for the current thread. Then we define a macro for errno
- * that dereferences this function's result.
- *
- * This makes it syntactically just like the "real" errno.
- *
- * Using a function pointer allows us to use a very fast
- * function when there are no threads running and a slower
- * function when there are multiple threads running.
- */
-void __WinCE_Errno_New_Thread(int *Errno_Pointer);
-void __WinCE_Errno_Thread_Exit(void);
-extern int *(*__WinCE_Errno_Pointer_Function)(void);
-
-#define errno (*(*__WinCE_Errno_Pointer_Function)())
-
-char *strerror(int errnum);
-
-struct tm {
- int tm_sec; /* seconds after the minute - [0,59] */
- int tm_min; /* minutes after the hour - [0,59] */
- int tm_hour; /* hours since midnight - [0,23] */
- int tm_mday; /* day of the month - [1,31] */
- int tm_mon; /* months since January - [0,11] */
- int tm_year; /* years since 1900 */
- int tm_wday; /* days since Sunday - [0,6] */
- int tm_yday; /* days since January 1 - [0,365] */
- int tm_isdst; /* daylight savings time flag */
-};
-
-struct tm *gmtime(const time_t *TimeP); /* for future use */
-struct tm *localtime(const time_t *TimeP);
-time_t mktime(struct tm *tm);
-time_t time(time_t *TimeP);
-
-size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *tim_p);
-
-int _wrename(const wchar_t *oldname, const wchar_t *newname);
-int _wremove(const wchar_t *filename);
-
-/* Environment variables are not supported */
-#define getenv(x) (NULL)
-
-/* Redefine fileno so that it returns an integer */
-#undef fileno
-#define fileno(f) (int)_fileno(f)
-
-/* Signals are not supported */
-#define signal(num, handler) (0)
-#define SIGTERM 0
-#define SIGINT 0
-
-
-/*** POSIX API ***/
-
-/* Missing POSIX definitions */
-
-#define FILENAME_MAX MAX_PATH
-
-struct _stat {
- unsigned long st_size;
- unsigned long st_ino;
- int st_mode;
- unsigned long st_atime;
- unsigned long st_mtime;
- unsigned long st_ctime;
- unsigned short st_dev;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
-};
-
-#define S_IFMT 0170000
-#define S_IFDIR 0040000
-#define S_IFREG 0100000
-#define S_IEXEC 0000100
-#define S_IWRITE 0000200
-#define S_IREAD 0000400
-
-#define _S_IFDIR S_IFDIR /* MSVCRT compatibilit */
-
-int _fstat(int handle, struct _stat *buffer);
-int _wstat(const wchar_t *path, struct _stat *buffer);
-
-#define stat _stat /* NOTE: applies to _stat() and also struct _stat */
-#define fstat _fstat
-
-#define O_RDWR (1<<0)
-#define O_RDONLY (2<<0)
-#define O_WRONLY (3<<0)
-#define O_MODE_MASK (3<<0)
-#define O_TRUNC (1<<2)
-#define O_EXCL (1<<3)
-#define O_CREAT (1<<4)
-#define O_BINARY 0
-
-int _wopen(const wchar_t *filename, int oflag, ...);
-int _close(int handle);
-int _write(int handle, const void *buffer, unsigned int count);
-int _read(int handle, void *buffer, unsigned int count);
-long _lseek(int handle, long offset, int origin);
-
-#define close _close
-#define write _write
-#define read _read
-#define lseek _lseek
-
-/* WinCE has only a Unicode version of this function */
-FILE *fdopen(int handle, const char *mode);
-
-int _wmkdir(const wchar_t *dirname);
-
-/* WinCE has no concept of current directory so we return a constant path */
-wchar_t *_wgetcwd(wchar_t *buffer, int maxlen);
-
-#define freopen(path, mode, stream) assert(0)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* INCLUDE_WINCE_COMPAT_H */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-static int isbyte(int n) { return (n >= 0 && n <= 255); }
-
-static void
-set_acl(struct shttpd_ctx *ctx, const char *s)
-{
- struct acl *acl = NULL;
- char flag;
- int len, a, b, c, d, n, mask;
- struct llhead *lp, *tmp;
-
- /* Delete the old ACLs if any */
- LL_FOREACH_SAFE(&ctx->acl, lp, tmp)
- free(LL_ENTRY(lp, struct acl, link));
-
- FOR_EACH_WORD_IN_LIST(s, len) {
-
- mask = 32;
-
- if (sscanf(s, "%c%d.%d.%d.%d%n",&flag,&a,&b,&c,&d,&n) != 5) {
- elog(E_FATAL, NULL, "[%s]: subnet must be "
- "[+|-]x.x.x.x[/x]", s);
- } else if (flag != '+' && flag != '-') {
- elog(E_FATAL, NULL, "flag must be + or -: [%s]", s);
- } else if (!isbyte(a)||!isbyte(b)||!isbyte(c)||!isbyte(d)) {
- elog(E_FATAL, NULL, "bad ip address: [%s]", s);
- } else if ((acl = malloc(sizeof(*acl))) == NULL) {
- elog(E_FATAL, NULL, "%s", "cannot malloc subnet");
- } else if (sscanf(s + n, "/%d", &mask) == 0) {
- /* Do nothing, no mask specified */
- } else if (mask < 0 || mask > 32) {
- elog(E_FATAL, NULL, "bad subnet mask: %d [%s]", n, s);
- }
-
- acl->ip = (a << 24) | (b << 16) | (c << 8) | d;
- acl->mask = mask ? 0xffffffffU << (32 - mask) : 0;
- acl->flag = flag;
- LL_TAIL(&ctx->acl, &acl->link);
- }
-}
-
-#ifndef NO_SSL
-/*
- * Dynamically load SSL library. Set up ctx->ssl_ctx pointer.
- */
-static void
-set_ssl(struct shttpd_ctx *ctx, const char *pem)
-{
- SSL_CTX *CTX;
- void *lib;
- struct ssl_func *fp;
-
- /* Load SSL library dynamically */
- if ((lib = dlopen(SSL_LIB, RTLD_LAZY)) == NULL)
- elog(E_FATAL, NULL, "set_ssl: cannot load %s", SSL_LIB);
-
- for (fp = ssl_sw; fp->name != NULL; fp++)
- if ((fp->ptr.v_void = dlsym(lib, fp->name)) == NULL)
- elog(E_FATAL, NULL,"set_ssl: cannot find %s", fp->name);
-
- /* Initialize SSL crap */
- SSL_library_init();
-
- if ((CTX = SSL_CTX_new(SSLv23_server_method())) == NULL)
- elog(E_FATAL, NULL, "SSL_CTX_new error");
- else if (SSL_CTX_use_certificate_file(CTX, pem, SSL_FILETYPE_PEM) == 0)
- elog(E_FATAL, NULL, "cannot open %s", pem);
- else if (SSL_CTX_use_PrivateKey_file(CTX, pem, SSL_FILETYPE_PEM) == 0)
- elog(E_FATAL, NULL, "cannot open %s", pem);
- ctx->ssl_ctx = CTX;
-}
-#endif /* NO_SSL */
-
-static void
-open_log_file(FILE **fpp, const char *path)
-{
- if (*fpp != NULL)
- (void) fclose(*fpp);
-
- if (path == NULL) {
- *fpp = NULL;
- } else if ((*fpp = fopen(path, "a")) == NULL) {
- elog(E_FATAL, NULL, "cannot open log file %s: %s",
- path, strerror(errno));
- }
-}
-
-static void
-set_alog(struct shttpd_ctx *ctx, const char *path)
-{
- open_log_file(&ctx->access_log, path);
-}
-
-static void
-set_elog(struct shttpd_ctx *ctx, const char *path)
-{
- open_log_file(&ctx->error_log, path);
-}
-
-static void show_cfg_page(struct shttpd_arg *arg);
-
-static void
-set_cfg_uri(struct shttpd_ctx *ctx, const char *uri)
-{
- free_list(&ctx->registered_uris, ®istered_uri_destructor);
-
- if (uri != NULL) {
- shttpd_register_uri(ctx, uri, &show_cfg_page, ctx);
- }
-}
-
-static void
-set_ports(struct shttpd_ctx *ctx, const char *p)
-{
- int len, is_ssl;
-
- free_list(&ctx->listeners, &listener_destructor);
-
- FOR_EACH_WORD_IN_LIST(p, len) {
- is_ssl = p[len - 1] == 's' ? 1 : 0;
- if (shttpd_listen(ctx, atoi(p), is_ssl) == -1)
- elog(E_FATAL, NULL,
- "Cannot open socket on port %d", atoi(p));
- }
-}
-
-static const struct opt {
- int index; /* Index in shttpd_ctx */
- const char *name; /* Option name in config file */
- const char *description; /* Description */
- const char *default_value; /* Default option value */
- void (*setter)(struct shttpd_ctx *, const char *);
-} known_options[] = {
- {OPT_ROOT, "root", "\tWeb root directory", ".", NULL},
- {OPT_INDEX_FILES, "index_files", "Index files", INDEX_FILES, NULL},
- {OPT_PORTS, "ports", "Listening ports", LISTENING_PORTS, set_ports},
- {OPT_DIR_LIST, "dir_list", "Directory listing", "1", NULL},
- {OPT_CFG_URI, "cfg_uri", "Config uri", NULL, set_cfg_uri},
- {OPT_PROTECT, "protect", "URI to htpasswd mapping", NULL, NULL},
-#ifndef NO_CGI
- {OPT_CGI_EXTENSIONS, "cgi_ext", "CGI extensions", CGI_EXT, NULL},
- {OPT_CGI_INTERPRETER, "cgi_interp", "CGI interpreter", NULL, NULL},
- {OPT_CGI_ENVIRONMENT, "cgi_env", "Additional CGI env vars", NULL, NULL},
-#endif /* NO_CGI */
- {OPT_SSI_EXTENSIONS, "ssi_ext", "SSI extensions", SSI_EXT, NULL},
-#ifndef NO_AUTH
- {OPT_AUTH_REALM, "auth_realm", "Authentication domain name",REALM,NULL},
- {OPT_AUTH_GPASSWD, "auth_gpass", "Global passwords file", NULL, NULL},
- {OPT_AUTH_PUT, "auth_PUT", "PUT,DELETE auth file", NULL, NULL},
-#endif /* !NO_AUTH */
- {OPT_ACCESS_LOG, "access_log", "Access log file", NULL, set_alog},
- {OPT_ERROR_LOG, "error_log", "Error log file", NULL, set_elog},
- {OPT_MIME_TYPES, "mime_types", "Additional mime types list", NULL,NULL},
-#ifndef NO_SSL
- {OPT_SSL_CERTIFICATE, "ssl_cert", "SSL certificate file", NULL,set_ssl},
-#endif /* NO_SSL */
- {OPT_ALIASES, "aliases", "Path=URI mappings", NULL, NULL},
- {OPT_ACL, "acl", "\tAllow/deny IP addresses/subnets", NULL, set_acl},
-#ifdef _WIN32
-#else
- {OPT_INETD, "inetd", "Inetd mode", "0", NULL},
- {OPT_UID, "uid", "\tRun as user", NULL, NULL},
-#endif /* _WIN32 */
- {-1, NULL, NULL, NULL, NULL}
-};
-
-void shttpd_set_option(struct shttpd_ctx *ctx, const char *opt, const char *val)
-{
- const struct opt *o;
-
- for (o = known_options; o->name != NULL; o++)
- if (!strcmp(opt, o->name))
- break;
-
- if (o->name == NULL)
- elog(E_FATAL, NULL, "no such option: [%s]", opt);
-
- /* Call option setter first, so it can use both new and old values */
- if (o->setter != NULL)
- o->setter(ctx, val);
-
- /* Free old value if any */
- if (ctx->options[o->index] != NULL)
- free(ctx->options[o->index]);
-
- /* Set new option value */
- ctx->options[o->index] = val ? my_strdup(val) : NULL;
-}
-
-static void
-show_cfg_page(struct shttpd_arg *arg)
-{
- struct shttpd_ctx *ctx = arg->user_data;
- char opt_name[20], value[BUFSIZ];
- const struct opt *o;
-
- opt_name[0] = value[0] = '\0';
-
- if (!strcmp(shttpd_get_env(arg, "REQUEST_METHOD"), "POST")) {
- if (arg->flags & SHTTPD_MORE_POST_DATA)
- return;
- (void) shttpd_get_var("o", arg->in.buf, arg->in.len,
- opt_name, sizeof(opt_name));
- (void) shttpd_get_var("v", arg->in.buf, arg->in.len,
- value, sizeof(value));
- shttpd_set_option(ctx, opt_name, value[0] ? value : NULL);
- }
-
- shttpd_printf(arg, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"
- "<html><body><h1>SHTTPD v. %s</h1>", shttpd_version());
-
- shttpd_printf(arg, "%s", "<table border=1"
- "<tr><th>Option</th><th>Description</th>"
- "<th colspan=2>Value</th></tr>");
-
- if (opt_name[0] != '\0' && value[0] != '\0')
- shttpd_printf(arg, "<p style='color: green'>Saved: %s=%s</p>",
- opt_name, value[0] ? value : "NULL");
-
-
- for (o = known_options; o->name != NULL; o++) {
- shttpd_printf(arg,
- "<form method=post><tr><td>%s</td><td>%s</td>"
- "<input type=hidden name=o value='%s'>"
- "<td><input type=text name=v value='%s'></td>"
- "<td><input type=submit value=save></td></form></tr>",
- o->name, o->description, o->name,
- ctx->options[o->index] ? ctx->options[o->index] : "");
- }
-
- shttpd_printf(arg, "%s", "</table></body></html>");
- arg->flags |= SHTTPD_END_OF_OUTPUT;
-}
-/*
- * Show usage string and exit.
- */
-void
-usage(const char *prog)
-{
- const struct opt *o;
-
- (void) fprintf(stderr,
- "SHTTPD version %s (c) Sergey Lyubka\n"
- "usage: %s [options] [config_file]\n", VERSION, prog);
-
-#if !defined(NO_AUTH)
- fprintf(stderr, " -A <htpasswd_file> <realm> <user> <passwd>\n");
-#endif /* NO_AUTH */
-
- for (o = known_options; o->name != NULL; o++) {
- (void) fprintf(stderr, " -%s\t%s", o->name, o->description);
- if (o->default_value != NULL)
- fprintf(stderr, " (default: %s)", o->default_value);
- fputc('\n', stderr);
- }
-
- exit(EXIT_FAILURE);
-}
-
-struct shttpd_ctx *shttpd_init(void)
-{
- struct shttpd_ctx *ctx;
- struct tm *tm;
- const struct opt *o;
-
- if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
- elog(E_FATAL, NULL, "cannot allocate shttpd context");
-
- /* Set default values */
- for (o = known_options; o->name != NULL; o++) {
- ctx->options[o->index] = o->default_value == NULL ?
- NULL : my_strdup(o->default_value);
- }
-
- current_time = ctx->start_time = time(NULL);
- tm = localtime(¤t_time);
- tz_offset = 0;
-#if 0
- tm->tm_gmtoff - 3600 * (tm->tm_isdst > 0 ? 1 : 0);
-#endif
-
- InitializeCriticalSection(&ctx->mutex);
-
- LL_INIT(&ctx->connections);
- LL_INIT(&ctx->registered_uris);
- LL_INIT(&ctx->error_handlers);
- LL_INIT(&ctx->acl);
- LL_INIT(&ctx->ssi_funcs);
- LL_INIT(&ctx->listeners);
-
-#ifdef _WIN32
- {WSADATA data; WSAStartup(MAKEWORD(2,2), &data);}
-#endif /* _WIN32 */
-
- return (ctx);
-}
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#ifndef CONFIG_HEADER_DEFINED
-#define CONFIG_HEADER_DEFINED
-
-#define VERSION "1.39" /* Version */
-#define CONFIG_FILE "shttpd.conf" /* Configuration file */
-#define HTPASSWD ".htpasswd" /* Passwords file name */
-#define URI_MAX 16384 /* Default max request size */
-#define LISTENING_PORTS "80" /* Default listening ports */
-#define INDEX_FILES "index.html,index.htm,index.php,index.cgi"
-#define CGI_EXT "cgi,pl,php" /* Default CGI extensions */
-#define SSI_EXT "shtml,shtm" /* Default SSI extensions */
-#define REALM "mydomain.com" /* Default authentication realm */
-#define DELIM_CHARS " ," /* Separators for lists */
-#define EXPIRE_TIME 3600 /* Expiration time, seconds */
-#define ENV_MAX 4096 /* Size of environment block */
-#define CGI_ENV_VARS 64 /* Maximum vars passed to CGI */
-
-#endif /* CONFIG_HEADER_DEFINED */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#ifndef DEFS_HEADER_DEFINED
-#define DEFS_HEADER_DEFINED
-
-#include "std_includes.h"
-#include "llist.h"
-#include "io.h"
-#include "shttpd.h"
-#include "md5.h"
-#include "config.h"
-
-#define NELEMS(ar) (sizeof(ar) / sizeof(ar[0]))
-
-#ifdef _DEBUG
-#define DBG(x) do { printf x ; putchar('\n'); fflush(stdout); } while (0)
-#else
-#define DBG(x)
-#endif /* DEBUG */
-
-#ifdef EMBEDDED
-#include "shttpd.h"
-#endif /* EMBEDDED */
-
-/*
- * Darwin prior to 7.0 and Win32 do not have socklen_t
- */
-#ifdef NO_SOCKLEN_T
-typedef int socklen_t;
-#endif /* NO_SOCKLEN_T */
-
-/*
- * For parsing. This guy represents a substring.
- */
-struct vec {
- const char *ptr;
- int len;
-};
-
-#if !defined(_WIN32)
-enum {FALSE, TRUE};
-#endif /* _WIN32 */
-enum {METHOD_GET, METHOD_POST, METHOD_PUT, METHOD_DELETE, METHOD_HEAD};
-enum {HDR_DATE, HDR_INT, HDR_STRING}; /* HTTP header types */
-enum {E_FATAL = 1, E_LOG = 2}; /* Flags for elog() function */
-typedef unsigned long big_int_t; /* Type for Content-Length */
-
-/*
- * Unified socket address
- */
-struct usa {
- socklen_t len;
- union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- } u;
-};
-
-/*
- * This thing is aimed to hold values of any type.
- * Used to store parsed headers' values.
- */
-union variant {
- char *v_str;
- int v_int;
- big_int_t v_big_int;
- time_t v_time;
- void (*v_func)(void);
- void *v_void;
- struct vec v_vec;
-};
-
-/*
- * This is used only in embedded configuration. This structure holds a
- * registered URI, associated callback function with callback data.
- * For non-embedded compilation shttpd_callback_t is not defined, so
- * we use union variant to keep the compiler silent.
- */
-struct registered_uri {
- struct llhead link;
- const char *uri;
- union variant callback;
- void *callback_data;
-};
-
-/*
- * User may want to handle certain errors. This structure holds the
- * handlers for corresponding error codes.
- */
-struct error_handler {
- struct llhead link;
- int code;
- union variant callback;
- void *callback_data;
-};
-
-struct http_header {
- int len; /* Header name length */
- int type; /* Header type */
- size_t offset; /* Value placeholder */
- const char *name; /* Header name */
-};
-
-/*
- * This guy holds parsed HTTP headers
- */
-struct headers {
- union variant cl; /* Content-Length: */
- union variant ct; /* Content-Type: */
- union variant connection; /* Connection: */
- union variant ims; /* If-Modified-Since: */
- union variant user; /* Remote user name */
- union variant auth; /* Authorization */
- union variant useragent; /* User-Agent: */
- union variant referer; /* Referer: */
- union variant cookie; /* Cookie: */
- union variant location; /* Location: */
- union variant range; /* Range: */
- union variant status; /* Status: */
- union variant transenc; /* Transfer-Encoding: */
-};
-
-/* Must go after union variant definition */
-#include "ssl.h"
-
-/*
- * The communication channel
- */
-union channel {
- int fd; /* Regular static file */
- int sock; /* Connected socket */
- struct {
- int sock; /* XXX important. must be first */
- SSL *ssl; /* shttpd_poll() assumes that */
- } ssl; /* SSL-ed socket */
- struct {
- DIR *dirp;
- char *path;
- } dir; /* Opened directory */
- struct {
- void *state; /* For keeping state */
- union variant func; /* User callback function */
- void *data; /* User defined parameters */
- } emb; /* Embedded, user callback */
-};
-
-struct stream;
-
-/*
- * IO class descriptor (file, directory, socket, SSL, CGI, etc)
- * These classes are defined in io_*.c files.
- */
-struct io_class {
- const char *name;
- int (*read)(struct stream *, void *buf, size_t len);
- int (*write)(struct stream *, const void *buf, size_t len);
- void (*close)(struct stream *);
-};
-
-/*
- * Data exchange stream. It is backed by some communication channel:
- * opened file, socket, etc. The 'read' and 'write' methods are
- * determined by a communication channel.
- */
-struct stream {
- struct conn *conn;
- union channel chan; /* Descriptor */
- struct io io; /* IO buffer */
- const struct io_class *io_class; /* IO class */
- int nread_last; /* Bytes last read */
- int headers_len;
- big_int_t content_len;
- unsigned int flags;
-#define FLAG_HEADERS_PARSED 1
-#define FLAG_SSL_ACCEPTED 2
-#define FLAG_R 4 /* Can read in general */
-#define FLAG_W 8 /* Can write in general */
-#define FLAG_CLOSED 16
-#define FLAG_DONT_CLOSE 32
-#define FLAG_ALWAYS_READY 64 /* File, dir, user_func */
-};
-
-struct conn {
- struct llhead link; /* Connections chain */
- struct shttpd_ctx *ctx; /* Context this conn belongs to */
- struct usa sa; /* Remote socket address */
- time_t birth_time; /* Creation time */
- time_t expire_time; /* Expiration time */
-
- int loc_port; /* Local port */
- int status; /* Reply status code */
- int method; /* Request method */
- char *uri; /* Decoded URI */
- unsigned long major_version; /* Major HTTP version number */
- unsigned long minor_version; /* Minor HTTP version number */
- char *request; /* Request line */
- char *headers; /* Request headers */
- char *query; /* QUERY_STRING part of the URI */
- char *path_info; /* PATH_INFO thing */
- struct vec mime_type; /* Mime type */
-
- struct headers ch; /* Parsed client headers */
-
- struct stream loc; /* Local stream */
- struct stream rem; /* Remote stream */
-
-#if !defined(NO_SSI)
- void *ssi; /* SSI descriptor */
-#endif /* NO_SSI */
-};
-
-enum {
- OPT_ROOT, OPT_INDEX_FILES, OPT_PORTS, OPT_DIR_LIST,
- OPT_CGI_EXTENSIONS, OPT_CGI_INTERPRETER, OPT_CGI_ENVIRONMENT,
- OPT_SSI_EXTENSIONS, OPT_AUTH_REALM, OPT_AUTH_GPASSWD,
- OPT_AUTH_PUT, OPT_ACCESS_LOG, OPT_ERROR_LOG, OPT_MIME_TYPES,
- OPT_SSL_CERTIFICATE, OPT_ALIASES, OPT_ACL, OPT_INETD, OPT_UID,
- OPT_CFG_URI, OPT_PROTECT,
- NUM_OPTIONS
-};
-
-/*
- * SHTTPD context
- */
-struct shttpd_ctx {
- time_t start_time; /* Start time */
- int nactive; /* # of connections now */
- unsigned long nrequests; /* Requests made */
- uint64_t in, out; /* IN/OUT traffic counters */
- SSL_CTX *ssl_ctx; /* SSL context */
- struct llhead connections; /* List of connections */
-
- struct llhead registered_uris;/* User urls */
- struct llhead error_handlers; /* Embedded error handlers */
- struct llhead acl; /* Access control list */
- struct llhead ssi_funcs; /* SSI callback functions */
- struct llhead listeners; /* Listening sockets */
-
- FILE *access_log; /* Access log stream */
- FILE *error_log; /* Error log stream */
-
- char *options[NUM_OPTIONS]; /* Configurable options */
-
-#if defined(_WIN32)
- CRITICAL_SECTION mutex; /* For MT case */
- HANDLE ev[2]; /* For thread synchronization */
-#elif defined(__rtems__)
- rtems_id mutex;
-#endif /* _WIN32 */
-};
-
-#define IS_TRUE(ctx, opt) ((ctx)->options[opt] && (ctx)->options[opt][0] =='1')
-
-/*
- * In SHTTPD, list of values are represented as comma or space separated
- * string. For example, list of CGI extensions can be represented as
- * ".cgi,.php,.pl", or ".cgi .php .pl". The macro that follows allows to
- * loop through the individual values in that list.
- *
- * A "const char *" pointer and size_t variable must be passed to the macro.
- * Spaces or commas can be used as delimiters (macro DELIM_CHARS).
- *
- * In every iteration of the loop, "s" points to the current value, and
- * "len" specifies its length. The code inside loop must not change
- * "s" and "len" parameters.
- */
-#define FOR_EACH_WORD_IN_LIST(s,len) \
- for (; s != NULL && (len = strcspn(s, DELIM_CHARS)) != 0; \
- s += len, s+= strspn(s, DELIM_CHARS))
-
-/*
- * IPv4 ACL entry. Specifies subnet with deny/allow flag
- */
-struct acl {
- struct llhead link;
- uint32_t ip; /* IP, in network byte order */
- uint32_t mask; /* Also in network byte order */
- int flag; /* Either '+' or '-' */
-};
-
-/*
- * shttpd.c
- */
-extern time_t current_time; /* Current UTC time */
-extern int tz_offset; /* Offset from GMT time zone */
-extern const struct vec known_http_methods[];
-
-extern void stop_stream(struct stream *stream);
-extern int url_decode(const char *, int, char *dst, int);
-extern void send_server_error(struct conn *, int code, const char *reason);
-extern int get_headers_len(const char *buf, size_t buflen);
-extern void parse_headers(const char *s, int len, struct headers *parsed);
-extern void open_listening_ports(struct shttpd_ctx *ctx);
-extern void get_mime_type(struct shttpd_ctx *, const char *, int, struct vec *);
-extern void free_list(struct llhead *head, void (*)(struct llhead *));
-extern void registered_uri_destructor(struct llhead *);
-extern void listener_destructor(struct llhead *);
-
-/*
- * config.c
- */
-extern void usage(const char *prog);
-
-/*
- * log.c
- */
-extern void elog(int flags, struct conn *c, const char *fmt, ...);
-extern void log_access(FILE *fp, const struct conn *c);
-
-/*
- * string.c
- */
-extern void my_strlcpy(register char *, register const char *, size_t);
-extern int my_strncasecmp(register const char *,
- register const char *, size_t);
-extern char *my_strndup(const char *ptr, size_t len);
-extern char *my_strdup(const char *str);
-extern int my_snprintf(char *buf, size_t buflen, const char *fmt, ...);
-extern int match_extension(const char *path, const char *ext_list);
-
-/*
- * compat_*.c
- */
-extern void set_close_on_exec(int fd);
-extern int set_non_blocking_mode(int fd);
-extern int my_stat(const char *, struct stat *stp);
-extern int my_open(const char *, int flags, int mode);
-extern int my_remove(const char *);
-extern int my_rename(const char *, const char *);
-extern int my_mkdir(const char *, int);
-extern char * my_getcwd(char *, int);
-extern int spawn_process(struct conn *c, const char *prog,
- char *envblk, char *envp[], int sock, const char *dir);
-
-/*
- * io_*.c
- */
-extern const struct io_class io_file;
-extern const struct io_class io_socket;
-extern const struct io_class io_ssl;
-extern const struct io_class io_cgi;
-extern const struct io_class io_dir;
-extern const struct io_class io_embedded;
-extern const struct io_class io_ssi;
-
-extern int put_dir(const char *path);
-extern void get_dir(struct conn *c);
-extern void get_file(struct conn *c, struct stat *stp);
-extern void ssl_handshake(struct stream *stream);
-extern void setup_embedded_stream(struct conn *, union variant, void *);
-extern struct registered_uri *is_registered_uri(struct shttpd_ctx *,
- const char *uri);
-extern void do_ssi(struct conn *);
-extern void ssi_func_destructor(struct llhead *lp);
-
-/*
- * auth.c
- */
-extern int check_authorization(struct conn *c, const char *path);
-extern int is_authorized_for_put(struct conn *c);
-extern void send_authorization_request(struct conn *c);
-extern int edit_passwords(const char *fname, const char *domain,
- const char *user, const char *pass);
-
-/*
- * cgi.c
- */
-extern int run_cgi(struct conn *c, const char *prog);
-extern void do_cgi(struct conn *c);
-
-#define CGI_REPLY "HTTP/1.1 OK\r\n"
-#define CGI_REPLY_LEN (sizeof(CGI_REPLY) - 1)
-
-#endif /* DEFS_HEADER_DEFINED */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * $Id: shttpd.h,v 1.9 2008/02/13 20:44:32 drozd Exp $
- */
-
-#ifndef SHTTPD_HEADER_INCLUDED
-#define SHTTPD_HEADER_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-struct ubuf {
- char *buf; /* Buffer pointer */
- int len; /* Size of a buffer */
- int num_bytes; /* Bytes processed by callback */
-};
-
-/*
- * This structure is passed to the user callback function
- */
-struct shttpd_arg {
- void *priv; /* Private! Do not touch! */
- void *state; /* User state */
- void *user_data; /* User-defined data */
- struct ubuf in; /* Input is here, POST data */
- struct ubuf out; /* Output goes here */
- unsigned int flags;
-#define SHTTPD_END_OF_OUTPUT 1
-#define SHTTPD_CONNECTION_ERROR 2
-#define SHTTPD_MORE_POST_DATA 4
-#define SHTTPD_POST_BUFFER_FULL 8
-#define SHTTPD_SSI_EVAL_TRUE 16
-};
-
-/*
- * User callback function. Called when certain registered URLs have been
- * requested. These are the requirements to the callback function:
- *
- * 1. it must copy data into 'out.buf' buffer, not more than 'out.len' bytes,
- * and record how many bytes are copied, into 'out.num_bytes'
- * 2. it must not block the execution
- * 3. it must set SHTTPD_END_OF_OUTPUT flag when finished
- * 4. for POST requests, it must process the incoming data (in.buf) of length
- * 'in.len', and set 'in.num_bytes', which is how many bytes of POST
- * data is read and can be discarded by SHTTPD.
- * 5. If callback allocates arg->state, to keep state, it must deallocate it
- * at the end of coonection SHTTPD_CONNECTION_ERROR or SHTTPD_END_OF_OUTPUT
- */
-typedef void (*shttpd_callback_t)(struct shttpd_arg *);
-
-/*
- * shttpd_init Initialize shttpd context.
- * shttpd_set_option Set new value for option.
- * shttpd_fini Dealocate the context
- * shttpd_register_uri Setup the callback function for specified URL.
- * shtppd_listen Setup a listening socket in the SHTTPD context
- * shttpd_poll Do connections processing
- * shttpd_version return string with SHTTPD version
- * shttpd_get_var Fetch POST/GET variable value by name. Return value len
- * shttpd_get_header return value of the specified HTTP header
- * shttpd_get_env return string values for the following
- * pseudo-variables: "REQUEST_METHOD", "REQUEST_URI",
- * "REMOTE_USER" and "REMOTE_ADDR".
- */
-
-struct shttpd_ctx;
-
-struct shttpd_ctx *shttpd_init(void);
-void shttpd_set_option(struct shttpd_ctx *, const char *opt, const char *val);
-void shttpd_fini(struct shttpd_ctx *);
-int shttpd_listen(struct shttpd_ctx *ctx, int port, int is_ssl);
-void shttpd_register_uri(struct shttpd_ctx *ctx, const char *uri,
- shttpd_callback_t callback, void *const user_data);
-void shttpd_poll(struct shttpd_ctx *, int milliseconds);
-const char *shttpd_version(void);
-int shttpd_get_var(const char *var, const char *buf, int buf_len,
- char *value, int value_len);
-const char *shttpd_get_header(struct shttpd_arg *, const char *header_name);
-const char *shttpd_get_env(struct shttpd_arg *, const char *name);
-void shttpd_get_http_version(struct shttpd_arg *,
- unsigned long *major, unsigned long *minor);
-size_t shttpd_printf(struct shttpd_arg *, const char *fmt, ...);
-void shttpd_handle_error(struct shttpd_ctx *ctx, int status,
- shttpd_callback_t func, void *const data);
-void shttpd_register_ssi_func(struct shttpd_ctx *ctx, const char *name,
- shttpd_callback_t func, void *const user_data);
-
-/*
- * The following three functions are for applications that need to
- * load-balance the connections on their own. Many threads may be spawned
- * with one SHTTPD context per thread. Boss thread may only wait for
- * new connections by means of shttpd_accept(). Then it may scan thread
- * pool for the idle thread by means of shttpd_active(), and add new
- * connection to the context by means of shttpd_add().
- */
-void shttpd_add_socket(struct shttpd_ctx *, int sock, int is_ssl);
-int shttpd_accept(int lsn_sock, int milliseconds);
-int shttpd_active(struct shttpd_ctx *);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* SHTTPD_HEADER_INCLUDED */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#ifndef IO_HEADER_INCLUDED
-#define IO_HEADER_INCLUDED
-
-#include <assert.h>
-#include <stddef.h>
-
-/*
- * I/O buffer descriptor
- */
-struct io {
- char *buf; /* IO Buffer */
- size_t size; /* IO buffer size */
- size_t head; /* Bytes read */
- size_t tail; /* Bytes written */
- size_t total; /* Total bytes read */
-};
-
-static __inline void
-io_clear(struct io *io)
-{
- assert(io->buf != NULL);
- assert(io->size > 0);
- io->total = io->tail = io->head = 0;
-}
-
-static __inline char *
-io_space(struct io *io)
-{
- assert(io->buf != NULL);
- assert(io->size > 0);
- assert(io->head <= io->size);
- return (io->buf + io->head);
-}
-
-static __inline char *
-io_data(struct io *io)
-{
- assert(io->buf != NULL);
- assert(io->size > 0);
- assert(io->tail <= io->size);
- return (io->buf + io->tail);
-}
-
-static __inline size_t
-io_space_len(const struct io *io)
-{
- assert(io->buf != NULL);
- assert(io->size > 0);
- assert(io->head <= io->size);
- return (io->size - io->head);
-}
-
-static __inline size_t
-io_data_len(const struct io *io)
-{
- assert(io->buf != NULL);
- assert(io->size > 0);
- assert(io->head <= io->size);
- assert(io->tail <= io->head);
- return (io->head - io->tail);
-}
-
-static __inline void
-io_inc_tail(struct io *io, size_t n)
-{
- assert(io->buf != NULL);
- assert(io->size > 0);
- assert(io->tail <= io->head);
- assert(io->head <= io->size);
- io->tail += n;
- assert(io->tail <= io->head);
- if (io->tail == io->head)
- io->head = io->tail = 0;
-}
-
-static __inline void
-io_inc_head(struct io *io, size_t n)
-{
- assert(io->buf != NULL);
- assert(io->size > 0);
- assert(io->tail <= io->head);
- io->head += n;
- io->total += n;
- assert(io->head <= io->size);
-}
-
-#endif /* IO_HEADER_INCLUDED */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-static int
-write_cgi(struct stream *stream, const void *buf, size_t len)
-{
- assert(stream->chan.sock != -1);
- assert(stream->flags & FLAG_W);
-
- return (send(stream->chan.sock, buf, len, 0));
-}
-
-static int
-read_cgi(struct stream *stream, void *buf, size_t len)
-{
- struct headers parsed;
- char status[4];
- int n;
-
- assert(stream->chan.sock != -1);
- assert(stream->flags & FLAG_R);
-
- stream->flags &= ~FLAG_DONT_CLOSE;
-
- n = recv(stream->chan.sock, buf, len, 0);
-
- if (stream->flags & FLAG_HEADERS_PARSED)
- return (n);
-
- if (n <= 0 && ERRNO != EWOULDBLOCK) {
- send_server_error(stream->conn, 500, "Error running CGI");
- return (n);
- }
-
- /*
- * CGI script may output Status: and Location: headers, which
- * may alter the status code. Buffer in headers, parse
- * them, send correct status code and then forward all data
- * from CGI script back to the remote end.
- * Reply line was alredy appended to the IO buffer in
- * decide_what_to_do(), with blank status code.
- */
-
- stream->flags |= FLAG_DONT_CLOSE;
- io_inc_head(&stream->io, n);
-
- stream->headers_len = get_headers_len(stream->io.buf, stream->io.head);
- if (stream->headers_len < 0) {
- stream->flags &= ~FLAG_DONT_CLOSE;
- send_server_error(stream->conn, 500, "Bad headers sent");
- elog(E_LOG, stream->conn, "CGI script sent invalid headers: "
- "[%.*s]", stream->io.head - CGI_REPLY_LEN,
- stream->io.buf + CGI_REPLY_LEN);
- return (0);
- }
-
- /*
- * If we did not received full headers yet, we must not send any
- * data read from the CGI back to the client. Suspend sending by
- * setting tail = head, which tells that there is no data in IO buffer
- */
-
- if (stream->headers_len == 0) {
- stream->io.tail = stream->io.head;
- return (0);
- }
-
- /* Received all headers. Set status code for the connection. */
- (void) memset(&parsed, 0, sizeof(parsed));
- parse_headers(stream->io.buf, stream->headers_len, &parsed);
- stream->content_len = parsed.cl.v_big_int;
- stream->conn->status = (int) parsed.status.v_big_int;
-
- /* If script outputs 'Location:' header, set status code to 302 */
- if (parsed.location.v_vec.len > 0)
- stream->conn->status = 302;
-
- /*
- * If script did not output neither 'Location:' nor 'Status' headers,
- * set the default status code 200, which means 'success'.
- */
- if (stream->conn->status == 0)
- stream->conn->status = 200;
-
- /* Append the status line to the beginning of the output */
- (void) my_snprintf(status, sizeof(status), "%3d", stream->conn->status);
- (void) memcpy(stream->io.buf + 9, status, 3);
- DBG(("read_cgi: content len %lu status %s",
- stream->content_len, status));
-
- /* Next time, pass output directly back to the client */
- assert((big_int_t) stream->headers_len <= stream->io.total);
- stream->io.total -= stream->headers_len;
- stream->io.tail = 0;
- stream->flags |= FLAG_HEADERS_PARSED;
-
- /* Return 0 because we've already shifted the head */
- return (0);
-}
-
-static void
-close_cgi(struct stream *stream)
-{
- assert(stream->chan.sock != -1);
- (void) closesocket(stream->chan.sock);
-}
-
-const struct io_class io_cgi = {
- "cgi",
- read_cgi,
- write_cgi,
- close_cgi
-};
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-/*
- * For a given PUT path, create all intermediate subdirectories
- * for given path. Return 0 if the path itself is a directory,
- * or -1 on error, 1 if OK.
- */
-int
-put_dir(const char *path)
-{
- char buf[FILENAME_MAX];
- const char *s, *p;
- struct stat st;
- size_t len;
-
- for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
- len = p - path;
- assert(len < sizeof(buf));
- (void) memcpy(buf, path, len);
- buf[len] = '\0';
-
- /* Try to create intermediate directory */
- if (my_stat(buf, &st) == -1 && my_mkdir(buf, 0755) != 0)
- return (-1);
-
- /* Is path itself a directory ? */
- if (p[1] == '\0')
- return (0);
- }
-
- return (1);
-}
-
-static int
-read_dir(struct stream *stream, void *buf, size_t len)
-{
- struct dirent *dp = NULL;
- char file[FILENAME_MAX], line[FILENAME_MAX + 512],
- size[64], mod[64];
- struct stat st;
- struct conn *c = stream->conn;
- int n, nwritten = 0;
- const char *slash = "";
-
- assert(stream->chan.dir.dirp != NULL);
- assert(stream->conn->uri[0] != '\0');
-
- do {
- if (len < sizeof(line))
- break;
-
- if ((dp = readdir(stream->chan.dir.dirp)) == NULL) {
- stream->flags |= FLAG_CLOSED;
- break;
- }
- DBG(("read_dir: %s", dp->d_name));
-
- /* Do not show current dir and passwords file */
- if (strcmp(dp->d_name, ".") == 0 ||
- strcmp(dp->d_name, HTPASSWD) == 0)
- continue;
-
- (void) my_snprintf(file, sizeof(file),
- "%s%s%s", stream->chan.dir.path, slash, dp->d_name);
- (void) my_stat(file, &st);
- if (S_ISDIR(st.st_mode)) {
- my_snprintf(size,sizeof(size),"%s","<DIR>");
- } else {
- if (st.st_size < 1024)
- (void) my_snprintf(size, sizeof(size),
- "%lu", (unsigned long) st.st_size);
- else if (st.st_size < 1024 * 1024)
- (void) my_snprintf(size, sizeof(size), "%luk",
- (unsigned long) (st.st_size >> 10) + 1);
- else
- (void) my_snprintf(size, sizeof(size),
- "%.1fM", (float) st.st_size / 1048576);
- }
- (void) strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M",
- localtime(&st.st_mtime));
-
- n = my_snprintf(line, sizeof(line),
- "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
- "<td> %s</td><td> %s</td></tr>\n",
- c->uri, slash, dp->d_name, dp->d_name,
- S_ISDIR(st.st_mode) ? "/" : "", mod, size);
- (void) memcpy(buf, line, n);
- buf = (char *) buf + n;
- nwritten += n;
- len -= n;
- } while (dp != NULL);
-
- return (nwritten);
-}
-
-static void
-close_dir(struct stream *stream)
-{
- assert(stream->chan.dir.dirp != NULL);
- assert(stream->chan.dir.path != NULL);
- (void) closedir(stream->chan.dir.dirp);
- free(stream->chan.dir.path);
-}
-
-void
-get_dir(struct conn *c)
-{
- if ((c->loc.chan.dir.dirp = opendir(c->loc.chan.dir.path)) == NULL) {
- (void) free(c->loc.chan.dir.path);
- send_server_error(c, 500, "Cannot open directory");
- } else {
- c->loc.io.head = my_snprintf(c->loc.io.buf, c->loc.io.size,
- "HTTP/1.1 200 OK\r\n"
- "Connection: close\r\n"
- "Content-Type: text/html; charset=utf-8\r\n\r\n"
- "<html><head><title>Index of %s</title>"
- "<style>th {text-align: left;}</style></head>"
- "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
- "<tr><th>Name</th><th>Modified</th><th>Size</th></tr>"
- "<tr><td colspan=\"3\"><hr></td></tr>",
- c->uri, c->uri);
- io_clear(&c->rem.io);
- c->status = 200;
- c->loc.io_class = &io_dir;
- c->loc.flags |= FLAG_R | FLAG_ALWAYS_READY;
- }
-}
-
-const struct io_class io_dir = {
- "dir",
- read_dir,
- NULL,
- close_dir
-};
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-const char *
-shttpd_version(void)
-{
- return (VERSION);
-}
-
-static void
-call_user(struct conn *c, struct shttpd_arg *arg, shttpd_callback_t func)
-{
- arg->priv = c;
- arg->state = c->loc.chan.emb.state;
- arg->out.buf = io_space(&c->loc.io);
- arg->out.len = io_space_len(&c->loc.io);
- arg->out.num_bytes = 0;
- arg->in.buf = io_data(&c->rem.io);;
- arg->in.len = io_data_len(&c->rem.io);
- arg->in.num_bytes = 0;
-
- if (io_data_len(&c->rem.io) >= c->rem.io.size)
- arg->flags |= SHTTPD_POST_BUFFER_FULL;
-
- if (c->rem.content_len > 0 && c->rem.io.total < c->rem.content_len)
- arg->flags |= SHTTPD_MORE_POST_DATA;
-
- func(arg);
-
- io_inc_head(&c->loc.io, arg->out.num_bytes);
- io_inc_tail(&c->rem.io, arg->in.num_bytes);
- c->loc.chan.emb.state = arg->state; /* Save state */
-
- /*
- * If callback finished output, that means it did all cleanup.
- * If the connection is terminated unexpectedly, we canna call
- * the callback via the stream close() method from disconnect.
- * However, if cleanup is already done, we set close() method to
- * NULL, to prevent the call from disconnect().
- */
-
- if (arg->flags & SHTTPD_END_OF_OUTPUT)
- c->loc.flags &= ~FLAG_DONT_CLOSE;
- else
- c->loc.flags |= FLAG_DONT_CLOSE;
-}
-
-static int
-do_embedded(struct stream *stream, void *buf, size_t len)
-{
- struct shttpd_arg arg;
- buf = NULL; len = 0; /* Squash warnings */
-
- arg.user_data = stream->conn->loc.chan.emb.data;
- arg.flags = 0;
-
- call_user(stream->conn, &arg, (shttpd_callback_t)
- stream->conn->loc.chan.emb.func.v_func);
-
- return (0);
-}
-
-static void
-close_embedded(struct stream *stream)
-{
- struct shttpd_arg arg;
- struct conn *c = stream->conn;
-
- arg.flags = SHTTPD_CONNECTION_ERROR;
- arg.user_data = c->loc.chan.emb.data;
-
- /*
- * Do not call the user function if SHTTPD_END_OF_OUTPUT was set,
- * i.e. the callback already terminated correctly
- */
- if (stream->flags & FLAG_DONT_CLOSE)
- call_user(stream->conn, &arg, (shttpd_callback_t)
- c->loc.chan.emb.func.v_func);
-}
-
-size_t
-shttpd_printf(struct shttpd_arg *arg, const char *fmt, ...)
-{
- struct conn *c = arg->priv;
- struct io *io = &c->loc.io;
- char *buf = arg->out.buf + arg->out.num_bytes;
- int buflen = arg->out.len - arg->out.num_bytes, len = 0;
- va_list ap;
-
- assert(buf <= io->buf + io->size);
-
- if (buflen > 0) {
- va_start(ap, fmt);
- len = vsnprintf(buf, buflen, fmt, ap);
- va_end(ap);
-
- if (len < 0 || len > buflen)
- len = buflen;
- arg->out.num_bytes += len;
- }
-
- return (len);
-}
-
-const char *
-shttpd_get_header(struct shttpd_arg *arg, const char *header_name)
-{
- struct conn *c = arg->priv;
- char *p, *s, *e;
- size_t len;
-
- p = c->headers;
- e = c->request + c->rem.headers_len;
- len = strlen(header_name);
-
- while (p < e) {
- if ((s = strchr(p, '\n')) != NULL)
- s[s[-1] == '\r' ? -1 : 0] = '\0';
- if (my_strncasecmp(header_name, p, len) == 0)
- return (p + len + 2);
-
- p += strlen(p) + 1;
- }
-
- return (NULL);
-}
-
-const char *
-shttpd_get_env(struct shttpd_arg *arg, const char *env_name)
-{
- struct conn *c = arg->priv;
- struct vec *vec;
-
- if (strcmp(env_name, "REQUEST_METHOD") == 0) {
- return (known_http_methods[c->method].ptr);
- } else if (strcmp(env_name, "REQUEST_URI") == 0) {
- return (c->uri);
- } else if (strcmp(env_name, "QUERY_STRING") == 0) {
- return (c->query);
- } else if (strcmp(env_name, "REMOTE_USER") == 0) {
- vec = &c->ch.user.v_vec;
- if (vec->len > 0) {
- ((char *) vec->ptr)[vec->len] = '\0';
- return (vec->ptr);
- }
- } else if (strcmp(env_name, "REMOTE_ADDR") == 0) {
- return (inet_ntoa(c->sa.u.sin.sin_addr));/* FIXME NOT MT safe */
- }
-
- return (NULL);
-}
-
-void
-shttpd_get_http_version(struct shttpd_arg *arg, unsigned long *major, unsigned long *minor)
-{
- struct conn *c = arg->priv;
-
- *major = c->major_version;
- *minor = c->minor_version;
-}
-
-void
-shttpd_register_uri(struct shttpd_ctx *ctx,
- const char *uri, shttpd_callback_t callback, void *data)
-{
- struct registered_uri *e;
-
- if ((e = malloc(sizeof(*e))) != NULL) {
- e->uri = my_strdup(uri);
- e->callback.v_func = (void (*)(void)) callback;
- e->callback_data = data;
- LL_TAIL(&ctx->registered_uris, &e->link);
- }
-}
-
-int
-shttpd_get_var(const char *var, const char *buf, int buf_len,
- char *value, int value_len)
-{
- const char *p, *e, *s;
- size_t var_len;
-
- var_len = strlen(var);
- e = buf + buf_len; /* End of QUERY_STRING buffer */
-
- /* buf is "var1=val1&var2=val2...". Find variable first */
- for (p = buf; p + var_len < e; p++)
- if ((p == buf || p[-1] == '&') &&
- p[var_len] == '=' &&
- !my_strncasecmp(var, p, var_len)) {
-
- /* Point 'p' to var value, 's' to the end of value */
- p += var_len + 1;
- if ((s = memchr(p, '&', e - p)) == NULL)
- s = e;
-
- /* URL-decode value. Return result length */
- return (url_decode(p, s - p, value, value_len));
- }
-
- return (-1);
-}
-
-static int
-match_regexp(const char *regexp, const char *text)
-{
- if (*regexp == '\0')
- return (*text == '\0');
-
- if (*regexp == '*')
- do {
- if (match_regexp(regexp + 1, text))
- return (1);
- } while (*text++ != '\0');
-
- if (*text != '\0' && *regexp == *text)
- return (match_regexp(regexp + 1, text + 1));
-
- return (0);
-}
-
-struct registered_uri *
-is_registered_uri(struct shttpd_ctx *ctx, const char *uri)
-{
- struct llhead *lp;
- struct registered_uri *reg_uri;
-
- LL_FOREACH(&ctx->registered_uris, lp) {
- reg_uri = LL_ENTRY(lp, struct registered_uri, link);
- if (match_regexp(reg_uri->uri, uri))
- return (reg_uri);
- }
-
- return (NULL);
-}
-
-void
-setup_embedded_stream(struct conn *c, union variant func, void *data)
-{
- c->loc.chan.emb.state = NULL;
- c->loc.chan.emb.func = func;
- c->loc.chan.emb.data = data;
- c->loc.io_class = &io_embedded;
- c->loc.flags |= FLAG_R | FLAG_W |FLAG_ALWAYS_READY;
-}
-
-void
-shttpd_handle_error(struct shttpd_ctx *ctx, int code,
- shttpd_callback_t func, void *data)
-{
- struct error_handler *e;
-
- if ((e = malloc(sizeof(*e))) != NULL) {
- e->code = code;
- e->callback.v_func = (void (*)(void)) func;
- e->callback_data = data;
- LL_TAIL(&ctx->error_handlers, &e->link);
- }
-}
-
-const struct io_class io_embedded = {
- "embedded",
- do_embedded,
- (int (*)(struct stream *, const void *, size_t)) do_embedded,
- close_embedded
-};
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-static int
-write_file(struct stream *stream, const void *buf, size_t len)
-{
- struct stat st;
- struct stream *rem = &stream->conn->rem;
- int n, fd = stream->chan.fd;
-
- assert(fd != -1);
- n = write(fd, buf, len);
-
- DBG(("put_file(%p, %d): %d bytes", (void *) stream, len, n));
-
- if (n <= 0 || (rem->io.total >= (big_int_t) rem->headers_len)) {
- (void) fstat(fd, &st);
- stream->io.head = stream->headers_len =
- my_snprintf(stream->io.buf,
- stream->io.size, "HTTP/1.1 %d OK\r\n"
- "Content-Length: %lu\r\nConnection: close\r\n\r\n",
- stream->conn->status, st.st_size);
- stop_stream(stream);
- }
-
- return (n);
-}
-
-static int
-read_file(struct stream *stream, void *buf, size_t len)
-{
-#ifdef USE_SENDFILE
- struct iovec vec;
- struct sf_hdtr hd = {&vec, 1, NULL, 0}, *hdp = &hd;
- int sock, fd, n;
- size_t nbytes;
- off_t sent;
-
- sock = stream->conn->rem.chan.sock;
- fd = stream->chan.fd;
-
- /* If this is the first call for this file, send the headers */
- vec.iov_base = stream->io.buf;
- vec.iov_len = stream->headers_len;
- if (stream->io.total > 0)
- hdp = NULL;
-
- nbytes = stream->content_len - stream->io.total;
- n = sendfile(fd, sock, lseek(fd, 0, SEEK_CUR), nbytes, hdp, &sent, 0);
-
- if (n == -1 && ERRNO != EAGAIN) {
- stream->flags &= ~FLAG_DONT_CLOSE;
- return (n);
- }
-
- stream->conn->ctx->out += sent;
-
- /* If we have sent the HTTP headers in this turn, clear them off */
- if (stream->io.total == 0) {
- assert(sent >= stream->headers_len);
- sent -= stream->headers_len;
- io_clear(&stream->io);
- }
-
- (void) lseek(fd, sent, SEEK_CUR);
- stream->io.total += sent;
- stream->flags |= FLAG_DONT_CLOSE;
-
- return (0);
-#endif /* USE_SENDFILE */
-
- assert(stream->chan.fd != -1);
- return (read(stream->chan.fd, buf, len));
-}
-
-static void
-close_file(struct stream *stream)
-{
- assert(stream->chan.fd != -1);
- (void) close(stream->chan.fd);
-}
-
-void
-get_file(struct conn *c, struct stat *stp)
-{
- char date[64], lm[64], etag[64], range[64] = "";
- size_t n, status = 200;
- unsigned long r1, r2;
- const char *fmt = "%a, %d %b %Y %H:%M:%S GMT", *msg = "OK";
- big_int_t cl; /* Content-Length */
-
- if (c->mime_type.len == 0)
- get_mime_type(c->ctx, c->uri, strlen(c->uri), &c->mime_type);
- cl = (big_int_t) stp->st_size;
-
- /* If Range: header specified, act accordingly */
- if (c->ch.range.v_vec.len > 0 &&
- (n = sscanf(c->ch.range.v_vec.ptr,"bytes=%lu-%lu",&r1, &r2)) > 0) {
- status = 206;
- (void) lseek(c->loc.chan.fd, r1, SEEK_SET);
- cl = n == 2 ? r2 - r1 + 1: cl - r1;
- (void) my_snprintf(range, sizeof(range),
- "Content-Range: bytes %lu-%lu/%lu\r\n",
- r1, r1 + cl - 1, (unsigned long) stp->st_size);
- msg = "Partial Content";
- }
-
- /* Prepare Etag, Date, Last-Modified headers */
- (void) strftime(date, sizeof(date), fmt, localtime(¤t_time));
- (void) strftime(lm, sizeof(lm), fmt, localtime(&stp->st_mtime));
- (void) my_snprintf(etag, sizeof(etag), "%lx.%lx",
- (unsigned long) stp->st_mtime, (unsigned long) stp->st_size);
-
- /*
- * We do not do io_inc_head here, because it will increase 'total'
- * member in io. We want 'total' to be equal to the content size,
- * and exclude the headers length from it.
- */
- c->loc.io.head = c->loc.headers_len = my_snprintf(c->loc.io.buf,
- c->loc.io.size,
- "HTTP/1.1 %d %s\r\n"
- "Date: %s\r\n"
- "Last-Modified: %s\r\n"
- "Etag: \"%s\"\r\n"
- "Content-Type: %.*s\r\n"
- "Content-Length: %lu\r\n"
- "Accept-Ranges: bytes\r\n"
- "%s\r\n",
- status, msg, date, lm, etag,
- c->mime_type.len, c->mime_type.ptr, cl, range);
-
- c->status = status;
- c->loc.content_len = cl;
- c->loc.io_class = &io_file;
- c->loc.flags |= FLAG_R | FLAG_ALWAYS_READY;
-
- if (c->method == METHOD_HEAD)
- stop_stream(&c->loc);
-}
-
-const struct io_class io_file = {
- "file",
- read_file,
- write_file,
- close_file
-};
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-static int
-read_socket(struct stream *stream, void *buf, size_t len)
-{
- assert(stream->chan.sock != -1);
- return (recv(stream->chan.sock, buf, len, 0));
-}
-
-static int
-write_socket(struct stream *stream, const void *buf, size_t len)
-{
- assert(stream->chan.sock != -1);
- return (send(stream->chan.sock, buf, len, 0));
-}
-
-static void
-close_socket(struct stream *stream)
-{
- assert(stream->chan.sock != -1);
- (void) closesocket(stream->chan.sock);
-}
-
-const struct io_class io_socket = {
- "socket",
- read_socket,
- write_socket,
- close_socket
-};
+++ /dev/null
-/*
- * Copyright (c) 2006,2007 Steven Johnson <sjohnson@sakuraindustries.com>
- * Copyright (c) 2007 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-#define CMDBUFSIZ 512 /* SSI command buffer size */
-#define NEST_MAX 6 /* Maximum nesting level */
-
-struct ssi_func {
- struct llhead link;
- void *user_data;
- char *name;
- shttpd_callback_t func;
-};
-
-struct ssi_inc {
- int state; /* Buffering state */
- int cond; /* Conditional state */
- FILE *fp; /* Icluded file stream */
- char buf[CMDBUFSIZ]; /* SSI command buffer */
- size_t nbuf; /* Bytes in a command buffer */
- FILE *pipe; /* #exec stream */
- struct ssi_func func; /* #call function */
-};
-
-struct ssi {
- struct conn *conn; /* Connection we belong to */
- int nest; /* Current nesting level */
- struct ssi_inc incs[NEST_MAX]; /* Nested includes */
-};
-
-enum { SSI_PASS, SSI_BUF, SSI_EXEC, SSI_CALL };
-enum { SSI_GO, SSI_STOP }; /* Conditional states */
-
-static const struct vec st = {"<!--#", 5};
-
-void
-shttpd_register_ssi_func(struct shttpd_ctx *ctx, const char *name,
- shttpd_callback_t func, void *user_data)
-{
- struct ssi_func *e;
-
- if ((e = malloc(sizeof(*e))) != NULL) {
- e->name = my_strdup(name);
- e->func = func;
- e->user_data = user_data;
- LL_TAIL(&ctx->ssi_funcs, &e->link);
- }
-}
-
-void
-ssi_func_destructor(struct llhead *lp)
-{
- struct ssi_func *e = LL_ENTRY(lp, struct ssi_func, link);
-
- free(e->name);
- free(e);
-}
-
-static const struct ssi_func *
-find_ssi_func(struct ssi *ssi, const char *name)
-{
- struct ssi_func *e;
- struct llhead *lp;
-
- LL_FOREACH(&ssi->conn->ctx->ssi_funcs, lp) {
- e = LL_ENTRY(lp, struct ssi_func, link);
- if (!strcmp(name, e->name))
- return (e);
- }
-
- return (NULL);
-}
-
-static void
-call(struct ssi *ssi, const char *name,
- struct shttpd_arg *arg, char *buf, int len)
-{
- const struct ssi_func *ssi_func;
-
- (void) memset(arg, 0, sizeof(*arg));
-
- /*
- * SSI function may be called with parameters. These parameters
- * are passed as arg->in.buf, arg->in.len vector.
- */
- arg->in.buf = strchr(name, ' ');
- if (arg->in.buf != NULL) {
- *arg->in.buf++ = '\0';
- arg->in.len = strlen(arg->in.buf);
- }
-
- if ((ssi_func = find_ssi_func(ssi, name)) != NULL) {
- arg->priv = ssi->conn;
- arg->user_data = ssi_func->user_data;
- arg->out.buf = buf;
- arg->out.len = len;
- ssi_func->func(arg);
- }
-}
-
-static int
-evaluate(struct ssi *ssi, const char *name)
-{
- struct shttpd_arg arg;
-
- call(ssi, name, &arg, NULL, 0);
-
- return (arg.flags & SHTTPD_SSI_EVAL_TRUE);
-}
-
-static void
-pass(struct ssi_inc *inc, void *buf, int *n)
-{
- if (inc->cond == SSI_GO) {
- (void) memcpy(buf, inc->buf, inc->nbuf);
- (*n) += inc->nbuf;
- }
- inc->nbuf = 0;
- inc->state = SSI_PASS;
-}
-
-static int
-get_path(struct conn *conn, const char *src,
- int src_len, char *dst, int dst_len)
-{
- static struct vec accepted[] = {
- {"\"", 1}, /* Relative to webserver CWD */
- {"file=\"", 6}, /* Relative to current URI */
- {"virtual=\"", 9}, /* Relative to document root */
- {NULL, 0},
- };
- struct vec *vec;
- const char *p, *root = conn->ctx->options[OPT_ROOT];
- int len;
-
- for (vec = accepted; vec->len > 0; vec++)
- if (src_len > vec->len && !memcmp(src, vec->ptr, vec->len)) {
- src += vec->len;
- src_len -= vec->len;
- if ((p = memchr(src, '"', src_len)) == NULL)
- break;
- if (vec->len == 6) {
- len = my_snprintf(dst, dst_len, "%s%c%s",
- root, DIRSEP, conn->uri);
- while (len > 0 && dst[len] != '/')
- len--;
- dst += len;
- dst_len -= len;
- } else if (vec->len == 9) {
- len = my_snprintf(dst, dst_len, "%s%c",
- root, DIRSEP);
- dst += len;
- dst_len -= len;
- }
- url_decode(src, p - src, dst, dst_len);
- return (1);
- }
-
- return (0);
-}
-
-static void
-do_include(struct ssi *ssi)
-{
- struct ssi_inc *inc = ssi->incs + ssi->nest;
- char buf[FILENAME_MAX];
- FILE *fp;
-
- assert(inc->nbuf >= 13);
-
- if (inc->cond == SSI_STOP) {
- /* Do nothing - conditional FALSE */
- } else if (ssi->nest >= (int) NELEMS(ssi->incs) - 1) {
- elog(E_LOG, ssi->conn,
- "ssi: #include: maximum nested level reached");
- } else if (!get_path(ssi->conn,
- inc->buf + 13, inc->nbuf - 13, buf, sizeof(buf))) {
- elog(E_LOG, ssi->conn, "ssi: bad #include: [%.*s]",
- inc->nbuf, inc->buf);
- } else if ((fp = fopen(buf, "r")) == NULL) {
- elog(E_LOG, ssi->conn,
- "ssi: fopen(%s): %s", buf, strerror(errno));
- } else {
- ssi->nest++;
- ssi->incs[ssi->nest].fp = fp;
- ssi->incs[ssi->nest].nbuf = 0;
- ssi->incs[ssi->nest].cond = SSI_GO;
- }
-}
-
-static char *
-trim_spaces(struct ssi_inc *inc)
-{
- char *p = inc->buf + inc->nbuf - 2;
-
- /* Trim spaces from the right */
- *p-- = '\0';
- while (isspace(* (unsigned char *) p))
- *p-- = '\0';
-
- /* Shift pointer to the start of attributes */
- for (p = inc->buf; !isspace(* (unsigned char *) p); p++);
- while (*p && isspace(* (unsigned char *) p)) p++;
-
- return (p);
-}
-
-static void
-do_if(struct ssi *ssi)
-{
- struct ssi_inc *inc = ssi->incs + ssi->nest;
- char *name = trim_spaces(inc);
-
- inc->cond = evaluate(ssi, name) ? SSI_GO : SSI_STOP;
-}
-
-static void
-do_elif(struct ssi *ssi)
-{
- struct ssi_inc *inc = ssi->incs + ssi->nest;
- char *name = trim_spaces(inc);
-
- if (inc->cond == SSI_STOP && evaluate(ssi, name))
- inc->cond = SSI_GO;
- else
- inc->cond = SSI_STOP;
-}
-static void
-do_endif(struct ssi *ssi)
-{
- ssi->incs[ssi->nest].cond = SSI_GO;
-}
-
-static void
-do_else(struct ssi *ssi)
-{
- struct ssi_inc *inc = ssi->incs + ssi->nest;
-
- inc->cond = inc->cond == SSI_GO ? SSI_STOP : SSI_GO;
-}
-
-static void
-do_call2(struct ssi *ssi, char *buf, int len, int *n)
-{
- struct ssi_inc *inc = ssi->incs + ssi->nest;
- struct shttpd_arg arg;
-
- call(ssi, inc->buf, &arg, buf, len);
- (*n) += arg.out.num_bytes;
- if (arg.flags & SHTTPD_END_OF_OUTPUT)
- inc->state = SSI_PASS;
-}
-
-static void
-do_call(struct ssi *ssi, char *buf, int len, int *n)
-{
- struct ssi_inc *inc = ssi->incs + ssi->nest;
- char *name = trim_spaces(inc);
-
- if (inc->cond == SSI_GO) {
- (void) memmove(inc->buf, name, strlen(name) + 1);
- inc->state = SSI_CALL;
- do_call2(ssi, buf, len, n);
- }
-}
-
-static void
-do_exec2(struct ssi *ssi, char *buf, int len, int *n)
-{
- struct ssi_inc *inc = ssi->incs + ssi->nest;
- int i, ch;
-
- for (i = 0; i < len; i++) {
- if ((ch = fgetc(inc->pipe)) == EOF) {
- inc->state = SSI_PASS;
- (void) pclose(inc->pipe);
- inc->pipe = NULL;
- break;
- }
- *buf++ = ch;
- (*n)++;
- }
-}
-
-static void
-do_exec(struct ssi *ssi, char *buf, int len, int *n)
-{
- struct ssi_inc *inc = ssi->incs + ssi->nest;
- char cmd[sizeof(inc->buf)], *e, *p;
-
- p = trim_spaces(inc);
-
- if (inc->cond == SSI_STOP) {
- /* Do nothing - conditional FALSE */
- } else if (*p != '"' || (e = strchr(p + 1, '"')) == NULL) {
- elog(E_LOG, ssi->conn, "ssi: bad exec(%s)", p);
- } else if (!url_decode(p + 1, e - p - 1, cmd, sizeof(cmd))) {
- elog(E_LOG, ssi->conn, "ssi: cannot url_decode: exec(%s)", p);
- } else if ((inc->pipe = popen(cmd, "r")) == NULL) {
- elog(E_LOG, ssi->conn, "ssi: popen(%s)", cmd);
- } else {
- inc->state = SSI_EXEC;
- do_exec2(ssi, buf, len, n);
- }
-}
-
-static const struct ssi_cmd {
- struct vec vec;
- void (*func)();
-} known_ssi_commands [] = {
- {{"include ", 8}, do_include },
- {{"if ", 3}, do_if },
- {{"elif ", 5}, do_elif },
- {{"else", 4}, do_else },
- {{"endif", 5}, do_endif },
- {{"call ", 5}, do_call },
- {{"exec ", 5}, do_exec },
- {{NULL, 0}, NULL }
-};
-
-static void
-do_command(struct ssi *ssi, char *buf, size_t len, int *n)
-{
- struct ssi_inc *inc = ssi->incs + ssi->nest;
- const struct ssi_cmd *cmd;
-
- assert(len > 0);
- assert(inc->nbuf <= len);
- inc->state = SSI_PASS;
-
- for (cmd = known_ssi_commands; cmd->func != NULL; cmd++)
- if (inc->nbuf > (size_t) st.len + cmd->vec.len &&
- !memcmp(inc->buf + st.len, cmd->vec.ptr, cmd->vec.len)) {
- cmd->func(ssi, buf, len, n);
- break;
- }
-
- if (cmd->func == NULL)
- pass(inc, buf, n);
-
- inc->nbuf = 0;
-}
-
-static int
-read_ssi(struct stream *stream, void *vbuf, size_t len)
-{
- struct ssi *ssi = stream->conn->ssi;
- struct ssi_inc *inc = ssi->incs + ssi->nest;
- char *buf = vbuf;
- int ch = EOF, n = 0;
-
-again:
-
- if (inc->state == SSI_CALL)
- do_call2(ssi, buf, len, &n);
- else if (inc->state == SSI_EXEC)
- do_exec2(ssi, buf, len, &n);
-
- while (n + inc->nbuf < len && (ch = fgetc(inc->fp)) != EOF)
-
- switch (inc->state) {
-
- case SSI_PASS:
- if (ch == '<') {
- inc->nbuf = 0;
- inc->buf[inc->nbuf++] = ch;
- inc->state = SSI_BUF;
- } else if (inc->cond == SSI_GO) {
- buf[n++] = ch;
- }
- break;
-
- /*
- * We are buffering whole SSI command, until closing "-->".
- * That means that when do_command() is called, we can rely
- * on that full command with arguments is buffered in and
- * there is no need for streaming.
- * Restrictions:
- * 1. The command must fit in CMDBUFSIZ
- * 2. HTML comments inside the command ? Not sure about this.
- */
- case SSI_BUF:
- if (inc->nbuf >= sizeof(inc->buf) - 1) {
- pass(inc, buf + n, &n);
- } else if (ch == '>' &&
- !memcmp(inc->buf + inc->nbuf - 2, "--", 2)) {
- do_command(ssi, buf + n, len - n, &n);
- inc = ssi->incs + ssi->nest;
- } else {
- inc->buf[inc->nbuf++] = ch;
-
- /* If not SSI tag, pass it */
- if (inc->nbuf <= (size_t) st.len &&
- memcmp(inc->buf, st.ptr, inc->nbuf) != 0)
- pass(inc, buf + n, &n);
- }
- break;
-
- case SSI_EXEC:
- case SSI_CALL:
- break;
-
- default:
- /* Never happens */
- abort();
- break;
- }
-
- if (ssi->nest > 0 && n + inc->nbuf < len && ch == EOF) {
- (void) fclose(inc->fp);
- inc->fp = NULL;
- ssi->nest--;
- inc--;
- goto again;
- }
-
- return (n);
-}
-
-static void
-close_ssi(struct stream *stream)
-{
- struct ssi *ssi = stream->conn->ssi;
- size_t i;
-
- for (i = 0; i < NELEMS(ssi->incs); i++) {
- if (ssi->incs[i].fp != NULL)
- (void) fclose(ssi->incs[i].fp);
- if (ssi->incs[i].pipe != NULL)
- (void) pclose(ssi->incs[i].pipe);
- }
-
- free(ssi);
-}
-
-void
-do_ssi(struct conn *c)
-{
- char date[64];
- struct ssi *ssi;
-
- (void) strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S GMT",
- localtime(¤t_time));
-
- c->loc.io.head = c->loc.headers_len = my_snprintf(c->loc.io.buf,
- c->loc.io.size,
- "HTTP/1.1 200 OK\r\n"
- "Date: %s\r\n"
- "Content-Type: text/html\r\n"
- "Connection: close\r\n\r\n",
- date);
-
- c->status = 200;
- c->loc.io_class = &io_ssi;
- c->loc.flags |= FLAG_R | FLAG_ALWAYS_READY;
-
- if (c->method == METHOD_HEAD) {
- stop_stream(&c->loc);
- } else if ((ssi = calloc(1, sizeof(struct ssi))) == NULL) {
- send_server_error(c, 500, "Cannot allocate SSI descriptor");
- } else {
- ssi->incs[0].fp = fdopen(c->loc.chan.fd, "r");
- ssi->conn = c;
- c->ssi = ssi;
- }
-}
-
-const struct io_class io_ssi = {
- "ssi",
- read_ssi,
- NULL,
- close_ssi
-};
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-#if !defined(NO_SSL)
-struct ssl_func ssl_sw[] = {
- {"SSL_free", {0}},
- {"SSL_accept", {0}},
- {"SSL_connect", {0}},
- {"SSL_read", {0}},
- {"SSL_write", {0}},
- {"SSL_get_error", {0}},
- {"SSL_set_fd", {0}},
- {"SSL_new", {0}},
- {"SSL_CTX_new", {0}},
- {"SSLv23_server_method", {0}},
- {"SSL_library_init", {0}},
- {"SSL_CTX_use_PrivateKey_file", {0}},
- {"SSL_CTX_use_certificate_file",{0}},
- {NULL, {0}}
-};
-
-void
-ssl_handshake(struct stream *stream)
-{
- int n;
-
- if ((n = SSL_accept(stream->chan.ssl.ssl)) == 0) {
- n = SSL_get_error(stream->chan.ssl.ssl, n);
- if (n != SSL_ERROR_WANT_READ && n != SSL_ERROR_WANT_WRITE)
- stream->flags |= FLAG_CLOSED;
- elog(E_LOG, stream->conn, "SSL_accept error %d", n);
- } else {
- DBG(("handshake: SSL accepted"));
- stream->flags |= FLAG_SSL_ACCEPTED;
- }
-}
-
-static int
-read_ssl(struct stream *stream, void *buf, size_t len)
-{
- int nread = 0;
-
- assert(stream->chan.ssl.ssl != NULL);
-
- if (!(stream->flags & FLAG_SSL_ACCEPTED))
- ssl_handshake(stream);
-
- if (stream->flags & FLAG_SSL_ACCEPTED)
- nread = SSL_read(stream->chan.ssl.ssl, buf, len);
-
- return (nread);
-}
-
-static int
-write_ssl(struct stream *stream, const void *buf, size_t len)
-{
- assert(stream->chan.ssl.ssl != NULL);
- return (SSL_write(stream->chan.ssl.ssl, buf, len));
-}
-
-static void
-close_ssl(struct stream *stream)
-{
- assert(stream->chan.ssl.sock != -1);
- assert(stream->chan.ssl.ssl != NULL);
- (void) closesocket(stream->chan.ssl.sock);
- SSL_free(stream->chan.ssl.ssl);
-}
-
-const struct io_class io_ssl = {
- "ssl",
- read_ssl,
- write_ssl,
- close_ssl
-};
-#endif /* !NO_SSL */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#ifndef LLIST_HEADER_INCLUDED
-#define LLIST_HEADER_INCLUDED
-
-/*
- * Linked list macros.
- */
-struct llhead {
- struct llhead *prev;
- struct llhead *next;
-};
-
-#define LL_INIT(N) ((N)->next = (N)->prev = (N))
-
-#define LL_HEAD(H) struct llhead H = { &H, &H }
-
-#define LL_ENTRY(P,T,N) ((T *)((char *)(P) - offsetof(T, N)))
-
-#define LL_ADD(H, N) \
- do { \
- ((H)->next)->prev = (N); \
- (N)->next = ((H)->next); \
- (N)->prev = (H); \
- (H)->next = (N); \
- } while (0)
-
-#define LL_TAIL(H, N) \
- do { \
- ((H)->prev)->next = (N); \
- (N)->prev = ((H)->prev); \
- (N)->next = (H); \
- (H)->prev = (N); \
- } while (0)
-
-#define LL_DEL(N) \
- do { \
- ((N)->next)->prev = ((N)->prev); \
- ((N)->prev)->next = ((N)->next); \
- LL_INIT(N); \
- } while (0)
-
-#define LL_EMPTY(N) ((N)->next == (N))
-
-#define LL_FOREACH(H,N) for (N = (H)->next; N != (H); N = (N)->next)
-
-#define LL_FOREACH_SAFE(H,N,T) \
- for (N = (H)->next, T = (N)->next; N != (H); \
- N = (T), T = (N)->next)
-
-#endif /* LLIST_HEADER_INCLUDED */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-/*
- * Log function
- */
-void
-elog(int flags, struct conn *c, const char *fmt, ...)
-{
- char date[64], buf[URI_MAX];
- int len;
- FILE *fp = c == NULL ? NULL : c->ctx->error_log;
- va_list ap;
-
- /* Print to stderr */
- if (c == NULL || !IS_TRUE(c->ctx, OPT_INETD)) {
- va_start(ap, fmt);
- (void) vfprintf(stderr, fmt, ap);
- (void) fputc('\n', stderr);
- va_end(ap);
- }
-
- strftime(date, sizeof(date), "%a %b %d %H:%M:%S %Y",
- localtime(¤t_time));
-
- len = my_snprintf(buf, sizeof(buf),
- "[%s] [error] [client %s] \"%s\" ",
- date, c ? inet_ntoa(c->sa.u.sin.sin_addr) : "-",
- c && c->request ? c->request : "-");
-
- va_start(ap, fmt);
- (void) vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
- va_end(ap);
-
- buf[sizeof(buf) - 1] = '\0';
-
- if (fp != NULL && (flags & (E_FATAL | E_LOG))) {
- (void) fprintf(fp, "%s\n", buf);
- (void) fflush(fp);
- }
-
- if (flags & E_FATAL)
- exit(EXIT_FAILURE);
-}
-
-void
-log_access(FILE *fp, const struct conn *c)
-{
- static const struct vec dash = {"-", 1};
-
- const struct vec *user = &c->ch.user.v_vec;
- const struct vec *referer = &c->ch.referer.v_vec;
- const struct vec *user_agent = &c->ch.useragent.v_vec;
- char date[64], buf[URI_MAX], *q1 = "\"", *q2 = "\"";
-
- if (user->len == 0)
- user = ‐
-
- if (referer->len == 0) {
- referer = ‐
- q1 = "";
- }
-
- if (user_agent->len == 0) {
- user_agent = ‐
- q2 = "";
- }
-
- (void) strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S",
- localtime(&c->birth_time));
-
- (void) my_snprintf(buf, sizeof(buf),
- "%s - %.*s [%s %+05d] \"%s\" %d %lu %s%.*s%s %s%.*s%s",
- inet_ntoa(c->sa.u.sin.sin_addr), user->len, user->ptr,
- date, tz_offset, c->request ? c->request : "-",
- c->status, (unsigned long) c->loc.io.total,
- q1, referer->len, referer->ptr, q1,
- q2, user_agent->len, user_agent->ptr, q2);
-
- if (fp != NULL) {
- (void) fprintf(fp, "%s\n", buf);
- (void) fflush(fp);
- }
-}
+++ /dev/null
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-#include "defs.h"
-
-#ifndef HAVE_MD5
-#if __BYTE_ORDER == 1234
-#define byteReverse(buf, len) /* Nothing */
-#else
-/*
- * Note: this code is harmless on little-endian machines.
- */
-static void byteReverse(unsigned char *buf, unsigned longs)
-{
- uint32_t t;
- do {
- t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
- ((unsigned) buf[1] << 8 | buf[0]);
- *(uint32_t *) buf = t;
- buf += 4;
- } while (--longs);
-}
-#endif /* __BYTE_ORDER */
-
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
-( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
-
-/*
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-void MD5Init(MD5_CTX *ctx)
-{
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
-
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
-{
- register uint32_t a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-void
-MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len)
-{
- uint32_t t;
-
- /* Update bitcount */
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
-
- /* Handle any leading odd-sized chunks */
-
- if (t) {
- unsigned char *p = (unsigned char *) ctx->in + t;
-
- t = 64 - t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += t;
- len -= t;
- }
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-void
-MD5Final(unsigned char digest[16], MD5_CTX *ctx)
-{
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count - 8);
- }
- byteReverse(ctx->in, 14);
-
- /* Append length in bits and transform */
- ((uint32_t *) ctx->in)[14] = ctx->bits[0];
- ((uint32_t *) ctx->in)[15] = ctx->bits[1];
-
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- byteReverse((unsigned char *) ctx->buf, 4);
- memcpy(digest, ctx->buf, 16);
- memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */
-}
-
-#endif /* !HAVE_MD5 */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#ifndef MD5_HEADER_INCLUDED
-#define MD5_HEADER_INCLUDED
-
-typedef struct MD5Context {
- uint32_t buf[4];
- uint32_t bits[2];
- unsigned char in[64];
-} MD5_CTX;
-
-extern void MD5Init(MD5_CTX *ctx);
-extern void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len);
-extern void MD5Final(unsigned char digest[16], MD5_CTX *ctx);
-
-#endif /*MD5_HEADER_INCLUDED */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-/*
- * Small and portable HTTP server, http://shttpd.sourceforge.net
- * $Id: shttpd.c,v 1.28 2008/02/17 21:45:09 drozd Exp $
- */
-
-#include "defs.h"
-
-time_t current_time; /* Current UTC time */
-int tz_offset; /* Time zone offset from UTC */
-
-const struct vec known_http_methods[] = {
- {"GET", 3},
- {"POST", 4},
- {"PUT", 3},
- {"DELETE", 6},
- {"HEAD", 4},
- {NULL, 0}
-};
-
-struct listener {
- struct llhead link;
- struct shttpd_ctx *ctx; /* Context that socket belongs */
- int sock; /* Listening socket */
- int is_ssl; /* Should be SSL-ed */
-};
-
-/*
- * This structure tells how HTTP headers must be parsed.
- * Used by parse_headers() function.
- */
-#define OFFSET(x) offsetof(struct headers, x)
-static const struct http_header http_headers[] = {
- {16, HDR_INT, OFFSET(cl), "Content-Length: " },
- {14, HDR_STRING, OFFSET(ct), "Content-Type: " },
- {12, HDR_STRING, OFFSET(useragent), "User-Agent: " },
- {19, HDR_DATE, OFFSET(ims), "If-Modified-Since: " },
- {15, HDR_STRING, OFFSET(auth), "Authorization: " },
- {9, HDR_STRING, OFFSET(referer), "Referer: " },
- {8, HDR_STRING, OFFSET(cookie), "Cookie: " },
- {10, HDR_STRING, OFFSET(location), "Location: " },
- {8, HDR_INT, OFFSET(status), "Status: " },
- {7, HDR_STRING, OFFSET(range), "Range: " },
- {12, HDR_STRING, OFFSET(connection), "Connection: " },
- {19, HDR_STRING, OFFSET(transenc), "Transfer-Encoding: " },
- {0, HDR_INT, 0, NULL }
-};
-
-struct shttpd_ctx *init_ctx(const char *config_file, int argc, char *argv[]);
-static void process_connection(struct conn *, int, int);
-
-int
-url_decode(const char *src, int src_len, char *dst, int dst_len)
-{
- int i, j, a, b;
-#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
-
- for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++)
- switch (src[i]) {
- case '%':
- if (isxdigit(((unsigned char *) src)[i + 1]) &&
- isxdigit(((unsigned char *) src)[i + 2])) {
- a = tolower(((unsigned char *)src)[i + 1]);
- b = tolower(((unsigned char *)src)[i + 2]);
- dst[j] = (HEXTOI(a) << 4) | HEXTOI(b);
- i += 2;
- } else {
- dst[j] = '%';
- }
- break;
- default:
- dst[j] = src[i];
- break;
- }
-
- dst[j] = '\0'; /* Null-terminate the destination */
-
- return (j);
-}
-
-static const char *
-is_alias(struct shttpd_ctx *ctx, const char *uri,
- struct vec *a_uri, struct vec *a_path)
-{
- const char *p, *s = ctx->options[OPT_ALIASES];
- size_t len;
-
- DBG(("is_alias: aliases [%s]", s == NULL ? "" : s));
-
- FOR_EACH_WORD_IN_LIST(s, len) {
-
- if ((p = memchr(s, '=', len)) == NULL || p >= s + len || p == s)
- continue;
-
- if (memcmp(uri, s, p - s) == 0) {
- a_uri->ptr = s;
- a_uri->len = p - s;
- a_path->ptr = ++p;
- a_path->len = (s + len) - p;
- return (s);
- }
- }
-
- return (NULL);
-}
-
-void
-stop_stream(struct stream *stream)
-{
- if (stream->io_class != NULL && stream->io_class->close != NULL)
- stream->io_class->close(stream);
-
- stream->io_class= NULL;
- stream->flags |= FLAG_CLOSED;
- stream->flags &= ~(FLAG_R | FLAG_W | FLAG_ALWAYS_READY);
-
- DBG(("%d %s stopped. %lu of content data, %d now in a buffer",
- stream->conn->rem.chan.sock,
- stream->io_class ? stream->io_class->name : "(null)",
- (unsigned long) stream->io.total, io_data_len(&stream->io)));
-}
-
-/*
- * Setup listening socket on given port, return socket
- */
-static int
-open_listening_port(int port)
-{
- int sock, on = 1;
- struct usa sa;
-
-#ifdef _WIN32
- {WSADATA data; WSAStartup(MAKEWORD(2,2), &data);}
-#endif /* _WIN32 */
-
- sa.len = sizeof(sa.u.sin);
- sa.u.sin.sin_family = AF_INET;
- sa.u.sin.sin_port = htons((uint16_t) port);
- sa.u.sin.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if ((sock = socket(PF_INET, SOCK_STREAM, 6)) == -1)
- goto fail;
- if (set_non_blocking_mode(sock) != 0)
- goto fail;
- if (setsockopt(sock, SOL_SOCKET,
- SO_REUSEADDR,(char *) &on, sizeof(on)) != 0)
- goto fail;
- if (bind(sock, &sa.u.sa, sa.len) < 0)
- goto fail;
- if (listen(sock, 128) != 0)
- goto fail;
-
-#ifndef _WIN32
- (void) fcntl(sock, F_SETFD, FD_CLOEXEC);
-#endif /* !_WIN32 */
-
- return (sock);
-fail:
- if (sock != -1)
- (void) closesocket(sock);
- elog(E_LOG, NULL, "open_listening_port(%d): %s", port, strerror(errno));
- return (-1);
-}
-
-/*
- * Check whether full request is buffered Return headers length, or 0
- */
-int
-get_headers_len(const char *buf, size_t buflen)
-{
- const char *s, *e;
- int len = 0;
-
- for (s = buf, e = s + buflen - 1; len == 0 && s < e; s++)
- /* Control characters are not allowed but >=128 is. */
- if (!isprint(* (unsigned char *) s) && *s != '\r' &&
- *s != '\n' && * (unsigned char *) s < 128)
- len = -1;
- else if (s[0] == '\n' && s[1] == '\n')
- len = s - buf + 2;
- else if (s[0] == '\n' && &s[1] < e &&
- s[1] == '\r' && s[2] == '\n')
- len = s - buf + 3;
-
- return (len);
-}
-
-/*
- * Send error message back to a client.
- */
-void
-send_server_error(struct conn *c, int status, const char *reason)
-{
- struct llhead *lp;
- struct error_handler *e;
-
- LL_FOREACH(&c->ctx->error_handlers, lp) {
- e = LL_ENTRY(lp, struct error_handler, link);
-
- if (e->code == status) {
- if (c->loc.io_class != NULL &&
- c->loc.io_class->close != NULL)
- c->loc.io_class->close(&c->loc);
- io_clear(&c->loc.io);
- setup_embedded_stream(c, e->callback, e->callback_data);
- return;
- }
- }
-
- io_clear(&c->loc.io);
- c->loc.io.head = my_snprintf(c->loc.io.buf, c->loc.io.size,
- "HTTP/1.1 %d %s\r\n"
- "Content-Type: text/plain\r\n"
- "Content-Length: 12\r\n"
- "\r\n"
- "Error: %03d\r\n",
- status, reason, status);
- c->loc.content_len = 10;
- c->status = status;
- stop_stream(&c->loc);
-}
-
-/*
- * Convert month to the month number. Return -1 on error, or month number
- */
-static int
-montoi(const char *s)
-{
- static const char *ar[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- size_t i;
-
- for (i = 0; i < sizeof(ar) / sizeof(ar[0]); i++)
- if (!strcmp(s, ar[i]))
- return (i);
-
- return (-1);
-}
-
-/*
- * Parse date-time string, and return the corresponding time_t value
- */
-static time_t
-date_to_epoch(const char *s)
-{
- struct tm tm, *tmp;
- char mon[32];
- int sec, min, hour, mday, month, year;
-
- (void) memset(&tm, 0, sizeof(tm));
- sec = min = hour = mday = month = year = 0;
-
- if (((sscanf(s, "%d/%3s/%d %d:%d:%d",
- &mday, mon, &year, &hour, &min, &sec) == 6) ||
- (sscanf(s, "%d %3s %d %d:%d:%d",
- &mday, mon, &year, &hour, &min, &sec) == 6) ||
- (sscanf(s, "%*3s, %d %3s %d %d:%d:%d",
- &mday, mon, &year, &hour, &min, &sec) == 6) ||
- (sscanf(s, "%d-%3s-%d %d:%d:%d",
- &mday, mon, &year, &hour, &min, &sec) == 6)) &&
- (month = montoi(mon)) != -1) {
- tm.tm_mday = mday;
- tm.tm_mon = month;
- tm.tm_year = year;
- tm.tm_hour = hour;
- tm.tm_min = min;
- tm.tm_sec = sec;
- }
-
- if (tm.tm_year > 1900)
- tm.tm_year -= 1900;
- else if (tm.tm_year < 70)
- tm.tm_year += 100;
-
- /* Set Daylight Saving Time field */
- tmp = localtime(¤t_time);
- tm.tm_isdst = tmp->tm_isdst;
-
- return (mktime(&tm));
-}
-
-static void
-remove_double_dots(char *s)
-{
- char *p = s;
-
- while (*s != '\0') {
- *p++ = *s++;
- if (s[-1] == '/' || s[-1] == '\\')
- while (*s == '.' || *s == '/' || *s == '\\')
- s++;
- }
- *p = '\0';
-}
-
-void
-parse_headers(const char *s, int len, struct headers *parsed)
-{
- const struct http_header *h;
- union variant *v;
- const char *p, *e = s + len;
-
- DBG(("parsing headers (len %d): [%.*s]", len, len, s));
-
- /* Loop through all headers in the request */
- while (s < e) {
-
- /* Find where this header ends */
- for (p = s; p < e && *p != '\n'; ) p++;
-
- /* Is this header known to us ? */
- for (h = http_headers; h->len != 0; h++)
- if (e - s > h->len &&
- !my_strncasecmp(s, h->name, h->len))
- break;
-
- /* If the header is known to us, store its value */
- if (h->len != 0) {
-
- /* Shift to where value starts */
- s += h->len;
-
- /* Find place to store the value */
- v = (union variant *) ((char *) parsed + h->offset);
-
- /* Fetch header value into the connection structure */
- if (h->type == HDR_STRING) {
- v->v_vec.ptr = s;
- v->v_vec.len = p - s;
- if (p[-1] == '\r' && v->v_vec.len > 0)
- v->v_vec.len--;
- } else if (h->type == HDR_INT) {
- v->v_big_int = strtoul(s, NULL, 10);
- } else if (h->type == HDR_DATE) {
- v->v_time = date_to_epoch(s);
- }
- }
-
- s = p + 1; /* Shift to the next header */
- }
-}
-
-static const struct {
- const char *extension;
- int ext_len;
- const char *mime_type;
-} builtin_mime_types[] = {
- {"html", 4, "text/html" },
- {"htm", 3, "text/html" },
- {"txt", 3, "text/plain" },
- {"css", 3, "text/css" },
- {"ico", 3, "image/x-icon" },
- {"gif", 3, "image/gif" },
- {"jpg", 3, "image/jpeg" },
- {"jpeg", 4, "image/jpeg" },
- {"png", 3, "image/png" },
- {"svg", 3, "image/svg+xml" },
- {"torrent", 7, "application/x-bittorrent" },
- {"wav", 3, "audio/x-wav" },
- {"mp3", 3, "audio/x-mp3" },
- {"mid", 3, "audio/mid" },
- {"m3u", 3, "audio/x-mpegurl" },
- {"ram", 3, "audio/x-pn-realaudio" },
- {"ra", 2, "audio/x-pn-realaudio" },
- {"doc", 3, "application/msword", },
- {"exe", 3, "application/octet-stream" },
- {"zip", 3, "application/x-zip-compressed" },
- {"xls", 3, "application/excel" },
- {"tgz", 3, "application/x-tar-gz" },
- {"tar.gz", 6, "application/x-tar-gz" },
- {"tar", 3, "application/x-tar" },
- {"gz", 2, "application/x-gunzip" },
- {"arj", 3, "application/x-arj-compressed" },
- {"rar", 3, "application/x-arj-compressed" },
- {"rtf", 3, "application/rtf" },
- {"pdf", 3, "application/pdf" },
- {"swf", 3, "application/x-shockwave-flash" },
- {"mpg", 3, "video/mpeg" },
- {"mpeg", 4, "video/mpeg" },
- {"asf", 3, "video/x-ms-asf" },
- {"avi", 3, "video/x-msvideo" },
- {"bmp", 3, "image/bmp" },
- {NULL, 0, NULL }
-};
-
-void
-get_mime_type(struct shttpd_ctx *ctx, const char *uri, int len, struct vec *vec)
-{
- const char *eq, *p = ctx->options[OPT_MIME_TYPES];
- int i, n, ext_len;
-
- /* Firt, loop through the custom mime types if any */
- FOR_EACH_WORD_IN_LIST(p, n) {
- if ((eq = memchr(p, '=', n)) == NULL || eq >= p + n || eq == p)
- continue;
- ext_len = eq - p;
- if (len > ext_len && uri[len - ext_len - 1] == '.' &&
- !my_strncasecmp(p, &uri[len - ext_len], ext_len)) {
- vec->ptr = eq + 1;
- vec->len = p + n - vec->ptr;
- return;
- }
- }
-
- /* If no luck, try built-in mime types */
- for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
- ext_len = builtin_mime_types[i].ext_len;
- if (len > ext_len && uri[len - ext_len - 1] == '.' &&
- !my_strncasecmp(builtin_mime_types[i].extension,
- &uri[len - ext_len], ext_len)) {
- vec->ptr = builtin_mime_types[i].mime_type;
- vec->len = strlen(vec->ptr);
- return;
- }
- }
-
- /* Oops. This extension is unknown to us. Fallback to text/plain */
- vec->ptr = "text/plain";
- vec->len = strlen(vec->ptr);
-}
-
-/*
- * For given directory path, substitute it to valid index file.
- * Return 0 if index file has been found, -1 if not found
- */
-static int
-find_index_file(struct conn *c, char *path, size_t maxpath, struct stat *stp)
-{
- char buf[FILENAME_MAX];
- const char *s = c->ctx->options[OPT_INDEX_FILES];
- size_t len;
-
- FOR_EACH_WORD_IN_LIST(s, len) {
- my_snprintf(buf, sizeof(buf), "%s%c%.*s",path, DIRSEP, len, s);
- if (my_stat(buf, stp) == 0) {
- my_strlcpy(path, buf, maxpath);
- get_mime_type(c->ctx, s, len, &c->mime_type);
- return (0);
- }
- }
-
- return (-1);
-}
-
-/*
- * Try to open requested file, return 0 if OK, -1 if error.
- * If the file is given arguments using PATH_INFO mechanism,
- * initialize pathinfo pointer.
- */
-static int
-get_path_info(struct conn *c, char *path, struct stat *stp)
-{
- char *p, *e;
-
- if (my_stat(path, stp) == 0)
- return (0);
-
- p = path + strlen(path);
- e = path + strlen(c->ctx->options[OPT_ROOT]) + 2;
-
- /* Strip directory parts of the path one by one */
- for (; p > e; p--)
- if (*p == '/') {
- *p = '\0';
- if (!my_stat(path, stp) && !S_ISDIR(stp->st_mode)) {
- c->path_info = p + 1;
- return (0);
- } else {
- *p = '/';
- }
- }
-
- return (-1);
-}
-
-
-static void
-decide_what_to_do(struct conn *c)
-{
- char path[URI_MAX], buf[1024], *root;
- struct vec alias_uri, alias_path;
- struct stat st;
- int rc;
- struct registered_uri *ruri;
-
- DBG(("decide_what_to_do: [%s]", c->uri));
-
- if ((c->query = strchr(c->uri, '?')) != NULL)
- *c->query++ = '\0';
-
- url_decode(c->uri, strlen(c->uri), c->uri, strlen(c->uri) + 1);
- remove_double_dots(c->uri);
-
- root = c->ctx->options[OPT_ROOT];
- if (strlen(c->uri) + strlen(root) >= sizeof(path)) {
- send_server_error(c, 400, "URI is too long");
- return;
- }
-
- (void) my_snprintf(path, sizeof(path), "%s%s", root, c->uri);
-
- /* User may use the aliases - check URI for mount point */
- if (is_alias(c->ctx, c->uri, &alias_uri, &alias_path) != NULL) {
- (void) my_snprintf(path, sizeof(path), "%.*s%s",
- alias_path.len, alias_path.ptr, c->uri + alias_uri.len);
- DBG(("using alias %.*s -> %.*s", alias_uri.len, alias_uri.ptr,
- alias_path.len, alias_path.ptr));
- }
-
-#if !defined(NO_AUTH)
- if (check_authorization(c, path) != 1) {
- send_authorization_request(c);
- } else
-#endif /* NO_AUTH */
- if ((ruri = is_registered_uri(c->ctx, c->uri)) != NULL) {
- setup_embedded_stream(c, ruri->callback, ruri->callback_data);
- } else
- if (strstr(path, HTPASSWD)) {
- /* Do not allow to view passwords files */
- send_server_error(c, 403, "Forbidden");
- } else
-#if !defined(NO_AUTH)
- if ((c->method == METHOD_PUT || c->method == METHOD_DELETE) &&
- (c->ctx->options[OPT_AUTH_PUT] == NULL ||
- !is_authorized_for_put(c))) {
- send_authorization_request(c);
- } else
-#endif /* NO_AUTH */
- if (c->method == METHOD_PUT) {
- c->status = my_stat(path, &st) == 0 ? 200 : 201;
-
- if (c->ch.range.v_vec.len > 0) {
- send_server_error(c, 501, "PUT Range Not Implemented");
- } else if ((rc = put_dir(path)) == 0) {
- send_server_error(c, 200, "OK");
- } else if (rc == -1) {
- send_server_error(c, 500, "PUT Directory Error");
- } else if (c->rem.content_len == 0) {
- send_server_error(c, 411, "Length Required");
- } else if ((c->loc.chan.fd = my_open(path, O_WRONLY | O_BINARY |
- O_CREAT | O_NONBLOCK | O_TRUNC, 0644)) == -1) {
- send_server_error(c, 500, "PUT Error");
- } else {
- DBG(("PUT file [%s]", c->uri));
- c->loc.io_class = &io_file;
- c->loc.flags |= FLAG_W | FLAG_ALWAYS_READY ;
- }
- } else if (c->method == METHOD_DELETE) {
- DBG(("DELETE [%s]", c->uri));
- if (my_remove(path) == 0)
- send_server_error(c, 200, "OK");
- else
- send_server_error(c, 500, "DELETE Error");
- } else if (get_path_info(c, path, &st) != 0) {
- send_server_error(c, 404, "Not Found");
- } else if (S_ISDIR(st.st_mode) && path[strlen(path) - 1] != '/') {
- (void) my_snprintf(buf, sizeof(buf),
- "Moved Permanently\r\nLocation: %s/", c->uri);
- send_server_error(c, 301, buf);
- } else if (S_ISDIR(st.st_mode) &&
- find_index_file(c, path, sizeof(path) - 1, &st) == -1 &&
- !IS_TRUE(c->ctx, OPT_DIR_LIST)) {
- send_server_error(c, 403, "Directory Listing Denied");
- } else if (S_ISDIR(st.st_mode) && IS_TRUE(c->ctx, OPT_DIR_LIST)) {
- if ((c->loc.chan.dir.path = my_strdup(path)) != NULL)
- get_dir(c);
- else
- send_server_error(c, 500, "GET Directory Error");
- } else if (S_ISDIR(st.st_mode) && !IS_TRUE(c->ctx, OPT_DIR_LIST)) {
- send_server_error(c, 403, "Directory listing denied");
-#if !defined(NO_CGI)
- } else if (match_extension(path, c->ctx->options[OPT_CGI_EXTENSIONS])) {
- if (c->method != METHOD_POST && c->method != METHOD_GET) {
- send_server_error(c, 501, "Bad method ");
- } else if ((run_cgi(c, path)) == -1) {
- send_server_error(c, 500, "Cannot exec CGI");
- } else {
- do_cgi(c);
- }
-#endif /* NO_CGI */
-#if !defined(NO_SSI)
- } else if (match_extension(path, c->ctx->options[OPT_SSI_EXTENSIONS])) {
- if ((c->loc.chan.fd = my_open(path,
- O_RDONLY | O_BINARY, 0644)) == -1) {
- send_server_error(c, 500, "SSI open error");
- } else {
- do_ssi(c);
- }
-#endif /* NO_CGI */
- } else if (c->ch.ims.v_time && st.st_mtime <= c->ch.ims.v_time) {
- send_server_error(c, 304, "Not Modified");
- } else if ((c->loc.chan.fd = my_open(path,
- O_RDONLY | O_BINARY, 0644)) != -1) {
- get_file(c, &st);
- } else {
- send_server_error(c, 500, "Internal Error");
- }
-}
-
-static int
-set_request_method(struct conn *c)
-{
- const struct vec *v;
-
- /* Set the request method */
- for (v = known_http_methods; v->ptr != NULL; v++)
- if (!memcmp(c->rem.io.buf, v->ptr, v->len)) {
- c->method = v - known_http_methods;
- break;
- }
-
- return (v->ptr == NULL);
-}
-
-static void
-parse_http_request(struct conn *c)
-{
- char *s, *e, *p, *start;
- int uri_len, req_len, n;
-
- s = io_data(&c->rem.io);;
- req_len = c->rem.headers_len =
- get_headers_len(s, io_data_len(&c->rem.io));
-
- if (req_len == 0 && io_space_len(&c->rem.io) == 0) {
- io_clear(&c->rem.io);
- send_server_error(c, 400, "Request is too big");
- }
-
- io_inc_tail(&c->rem.io, req_len);
-
- if (req_len == 0) {
- return;
- } else if (req_len < 16) { /* Minimal: "GET / HTTP/1.0\n\n" */
- send_server_error(c, 400, "Bad request");
- } else if (set_request_method(c)) {
- send_server_error(c, 501, "Method Not Implemented");
- } else if ((c->request = my_strndup(s, req_len)) == NULL) {
- send_server_error(c, 500, "Cannot allocate request");
- }
-
- if (c->loc.flags & FLAG_CLOSED)
- return;
-
- DBG(("Conn %d: parsing request: [%.*s]", c->rem.chan.sock, req_len, s));
- c->rem.flags |= FLAG_HEADERS_PARSED;
-
- /* Set headers pointer. Headers follow the request line */
- c->headers = memchr(c->request, '\n', req_len);
- assert(c->headers != NULL);
- assert(c->headers < c->request + req_len);
- if (c->headers > c->request && c->headers[-1] == '\r')
- c->headers[-1] = '\0';
- *c->headers++ = '\0';
-
- /*
- * Now make a copy of the URI, because it will be URL-decoded,
- * and we need a copy of unmodified URI for the access log.
- * First, we skip the REQUEST_METHOD and shift to the URI.
- */
- for (p = c->request, e = p + req_len; *p != ' ' && p < e; p++);
- while (p < e && *p == ' ')
- p++;
-
- /* Now remember where URI starts, and shift to the end of URI */
- for (start = p; p < e && !isspace((unsigned char)*p); ) p++;
- uri_len = p - start;
-
- /* Skip space following the URI */
- while (p < e && *p == ' ')
- p++;
-
- /* Now comes the HTTP-Version in the form HTTP/<major>.<minor> */
- if (sscanf(p, "HTTP/%lu.%lu%n",
- &c->major_version, &c->minor_version, &n) != 2 || p[n] != '\0') {
- send_server_error(c, 400, "Bad HTTP version");
- } else if (c->major_version > 1 ||
- (c->major_version == 1 && c->minor_version > 1)) {
- send_server_error(c, 505, "HTTP version not supported");
- } else if (uri_len <= 0) {
- send_server_error(c, 400, "Bad URI");
- } else if ((c->uri = malloc(uri_len + 1)) == NULL) {
- send_server_error(c, 500, "Cannot allocate URI");
- } else {
- my_strlcpy(c->uri, (char *) start, uri_len + 1);
- parse_headers(c->headers,
- (c->request + req_len) - c->headers, &c->ch);
-
- /* Remove the length of request from total, count only data */
- assert(c->rem.io.total >= (big_int_t) req_len);
- c->rem.io.total -= req_len;
- c->rem.content_len = c->ch.cl.v_big_int;
- decide_what_to_do(c);
- }
-}
-
-void
-shttpd_add_socket(struct shttpd_ctx *ctx, int sock, int is_ssl)
-{
- struct conn *c;
- struct usa sa;
- int l = IS_TRUE(ctx, OPT_INETD) ? E_FATAL : E_LOG;
-#if !defined(NO_SSL)
- SSL *ssl = NULL;
-#endif /* NO_SSL */
-
- sa.len = sizeof(sa.u.sin);
- (void) set_non_blocking_mode(sock);
-
- if (getpeername(sock, &sa.u.sa, &sa.len)) {
- elog(l, NULL, "add_socket: %s", strerror(errno));
-#if !defined(NO_SSL)
- } else if (is_ssl && (ssl = SSL_new(ctx->ssl_ctx)) == NULL) {
- elog(l, NULL, "add_socket: SSL_new: %s", strerror(ERRNO));
- (void) closesocket(sock);
- } else if (is_ssl && SSL_set_fd(ssl, sock) == 0) {
- elog(l, NULL, "add_socket: SSL_set_fd: %s", strerror(ERRNO));
- (void) closesocket(sock);
- SSL_free(ssl);
-#endif /* NO_SSL */
- } else if ((c = calloc(1, sizeof(*c) + 2 * URI_MAX)) == NULL) {
-#if !defined(NO_SSL)
- if (ssl)
- SSL_free(ssl);
-#endif /* NO_SSL */
- (void) closesocket(sock);
- elog(l, NULL, "add_socket: calloc: %s", strerror(ERRNO));
- } else {
- ctx->nrequests++;
- c->rem.conn = c->loc.conn = c;
- c->ctx = ctx;
- c->sa = sa;
- c->birth_time = current_time;
- c->expire_time = current_time + EXPIRE_TIME;
-
- (void) getsockname(sock, &sa.u.sa, &sa.len);
- c->loc_port = sa.u.sin.sin_port;
-
- set_close_on_exec(sock);
-
- c->loc.io_class = NULL;
-
- c->rem.io_class = &io_socket;
- c->rem.chan.sock = sock;
-
- /* Set IO buffers */
- c->loc.io.buf = (char *) (c + 1);
- c->rem.io.buf = c->loc.io.buf + URI_MAX;
- c->loc.io.size = c->rem.io.size = URI_MAX;
-
-#if !defined(NO_SSL)
- if (is_ssl) {
- c->rem.io_class = &io_ssl;
- c->rem.chan.ssl.sock = sock;
- c->rem.chan.ssl.ssl = ssl;
- ssl_handshake(&c->rem);
- }
-#endif /* NO_SSL */
-
- EnterCriticalSection(&ctx->mutex);
- LL_TAIL(&ctx->connections, &c->link);
- ctx->nactive++;
- LeaveCriticalSection(&ctx->mutex);
-
- DBG(("%s:%hu connected (socket %d)",
- inet_ntoa(* (struct in_addr *) &sa.u.sin.sin_addr.s_addr),
- ntohs(sa.u.sin.sin_port), sock));
- }
-}
-
-int
-shttpd_active(struct shttpd_ctx *ctx)
-{
- return (ctx->nactive);
-}
-
-/*
- * Setup a listening socket on given port. Return opened socket or -1
- */
-int
-shttpd_listen(struct shttpd_ctx *ctx, int port, int is_ssl)
-{
- struct listener *l;
- int sock;
-
- if ((sock = open_listening_port(port)) == -1) {
- elog(E_FATAL, NULL, "cannot open port %d", port);
- } else if ((l = calloc(1, sizeof(*l))) == NULL) {
- (void) closesocket(sock);
- elog(E_FATAL, NULL, "cannot allocate listener");
- } else if (is_ssl && ctx->ssl_ctx == NULL) {
- (void) closesocket(sock);
- elog(E_FATAL, NULL, "cannot add SSL socket, "
- "please specify certificate file");
- } else {
- l->is_ssl = is_ssl;
- l->sock = sock;
- l->ctx = ctx;
- LL_TAIL(&ctx->listeners, &l->link);
- DBG(("shttpd_listen: added socket %d", sock));
- }
-
- return (sock);
-}
-
-int
-shttpd_accept(int lsn_sock, int milliseconds)
-{
- struct timeval tv;
- struct usa sa;
- fd_set read_set;
- int sock = -1;
-
- tv.tv_sec = milliseconds / 1000;
- tv.tv_usec = milliseconds % 1000;
- sa.len = sizeof(sa.u.sin);
- FD_ZERO(&read_set);
- FD_SET(lsn_sock, &read_set);
-
- if (select(lsn_sock + 1, &read_set, NULL, NULL, &tv) == 1)
- sock = accept(lsn_sock, &sa.u.sa, &sa.len);
-
- return (sock);
-}
-
-static void
-read_stream(struct stream *stream)
-{
- int n, len;
-
- len = io_space_len(&stream->io);
- assert(len > 0);
-
- /* Do not read more that needed */
- if (stream->content_len > 0 &&
- stream->io.total + len > stream->content_len)
- len = stream->content_len - stream->io.total;
-
- /* Read from underlying channel */
- n = stream->nread_last = stream->io_class->read(stream,
- io_space(&stream->io), len);
-
- if (n > 0)
- io_inc_head(&stream->io, n);
- else if (n == -1 && (ERRNO == EINTR || ERRNO == EWOULDBLOCK))
- n = n; /* Ignore EINTR and EAGAIN */
- else if (!(stream->flags & FLAG_DONT_CLOSE))
- stop_stream(stream);
-
- DBG(("read_stream (%d %s): read %d/%d/%lu bytes (errno %d)",
- stream->conn->rem.chan.sock,
- stream->io_class ? stream->io_class->name : "(null)",
- n, len, (unsigned long) stream->io.total, ERRNO));
-
- /*
- * Close the local stream if everything was read
- * XXX We do not close the remote stream though! It may be
- * a POST data completed transfer, we do not want the socket
- * to be closed.
- */
- if (stream->content_len > 0 && stream == &stream->conn->loc) {
- assert(stream->io.total <= stream->content_len);
- if (stream->io.total == stream->content_len)
- stop_stream(stream);
- }
-
- stream->conn->expire_time = current_time + EXPIRE_TIME;
-}
-
-static void
-write_stream(struct stream *from, struct stream *to)
-{
- int n, len;
-
- len = io_data_len(&from->io);
- assert(len > 0);
-
- /* TODO: should be assert on CAN_WRITE flag */
- n = to->io_class->write(to, io_data(&from->io), len);
- to->conn->expire_time = current_time + EXPIRE_TIME;
- DBG(("write_stream (%d %s): written %d/%d bytes (errno %d)",
- to->conn->rem.chan.sock,
- to->io_class ? to->io_class->name : "(null)", n, len, ERRNO));
-
- if (n > 0)
- io_inc_tail(&from->io, n);
- else if (n == -1 && (ERRNO == EINTR || ERRNO == EWOULDBLOCK))
- n = n; /* Ignore EINTR and EAGAIN */
- else if (!(to->flags & FLAG_DONT_CLOSE))
- stop_stream(to);
-}
-
-
-static void
-disconnect(struct llhead *lp)
-{
- struct conn *c = LL_ENTRY(lp, struct conn, link);
- static const struct vec vec = {"close", 5};
- int do_close;
-
- DBG(("Disconnecting %d (%.*s)", c->rem.chan.sock,
- c->ch.connection.v_vec.len, c->ch.connection.v_vec.ptr));
-
- if (c->request != NULL && c->ctx->access_log != NULL)
- log_access(c->ctx->access_log, c);
-
- /* In inetd mode, exit if request is finished. */
- if (IS_TRUE(c->ctx, OPT_INETD))
- exit(0);
-
- if (c->loc.io_class != NULL && c->loc.io_class->close != NULL)
- c->loc.io_class->close(&c->loc);
-
- /*
- * Check the "Connection: " header before we free c->request
- * If it its 'keep-alive', then do not close the connection
- */
- do_close = (c->ch.connection.v_vec.len >= vec.len &&
- !my_strncasecmp(vec.ptr, c->ch.connection.v_vec.ptr, vec.len)) ||
- (c->major_version < 1 ||
- (c->major_version >= 1 && c->minor_version < 1));
-
- if (c->request)
- free(c->request);
- if (c->uri)
- free(c->uri);
-
- /* Keep the connection open only if we have Content-Length set */
- if (!do_close && c->loc.content_len > 0) {
- c->loc.io_class = NULL;
- c->loc.flags = 0;
- c->loc.content_len = 0;
- c->rem.flags = FLAG_W | FLAG_R;
- c->query = c->request = c->uri = c->path_info = NULL;
- c->mime_type.len = 0;
- (void) memset(&c->ch, 0, sizeof(c->ch));
- io_clear(&c->loc.io);
- c->birth_time = current_time;
- if (io_data_len(&c->rem.io) > 0)
- process_connection(c, 0, 0);
- } else {
- if (c->rem.io_class != NULL)
- c->rem.io_class->close(&c->rem);
-
- EnterCriticalSection(&c->ctx->mutex);
- LL_DEL(&c->link);
- c->ctx->nactive--;
- assert(c->ctx->nactive >= 0);
- LeaveCriticalSection(&c->ctx->mutex);
-
- free(c);
- }
-}
-
-static int
-is_allowed(const struct shttpd_ctx *ctx, const struct usa *usa)
-{
- const struct acl *acl;
- const struct llhead *lp;
- int allowed = '+';
- uint32_t ip;
-
- LL_FOREACH(&ctx->acl, lp) {
- acl = LL_ENTRY(lp, struct acl, link);
- (void) memcpy(&ip, &usa->u.sin.sin_addr, sizeof(ip));
- if (acl->ip == (ntohl(ip) & acl->mask))
- allowed = acl->flag;
- }
-
- return (allowed == '+');
-}
-
-static void
-add_to_set(int fd, fd_set *set, int *max_fd)
-{
- FD_SET(fd, set);
- if (fd > *max_fd)
- *max_fd = fd;
-}
-
-static void
-process_connection(struct conn *c, int remote_ready, int local_ready)
-{
- /* Read from remote end if it is ready */
- if (remote_ready && io_space_len(&c->rem.io))
- read_stream(&c->rem);
-
- /* If the request is not parsed yet, do so */
- if (!(c->rem.flags & FLAG_HEADERS_PARSED))
- parse_http_request(c);
-
- DBG(("loc: %u [%.*s]", io_data_len(&c->loc.io),
- io_data_len(&c->loc.io), io_data(&c->loc.io)));
- DBG(("rem: %u [%.*s]", io_data_len(&c->rem.io),
- io_data_len(&c->rem.io), io_data(&c->rem.io)));
-
- /* Read from the local end if it is ready */
- if (local_ready && io_space_len(&c->loc.io))
- read_stream(&c->loc);
-
- if (io_data_len(&c->rem.io) > 0 && (c->loc.flags & FLAG_W) &&
- c->loc.io_class != NULL && c->loc.io_class->write != NULL)
- write_stream(&c->rem, &c->loc);
-
- if (io_data_len(&c->loc.io) > 0 && c->rem.io_class != NULL)
- write_stream(&c->loc, &c->rem);
-
- if (c->rem.nread_last > 0)
- c->ctx->in += c->rem.nread_last;
- if (c->loc.nread_last > 0)
- c->ctx->out += c->loc.nread_last;
-
- /* Check whether we should close this connection */
- if ((current_time > c->expire_time) ||
- (c->rem.flags & FLAG_CLOSED) ||
- ((c->loc.flags & FLAG_CLOSED) && !io_data_len(&c->loc.io)))
- disconnect(&c->link);
-}
-
-/*
- * One iteration of server loop. This is the core of the data exchange.
- */
-void
-shttpd_poll(struct shttpd_ctx *ctx, int milliseconds)
-{
- struct llhead *lp, *tmp;
- struct listener *l;
- struct conn *c;
- struct timeval tv; /* Timeout for select() */
- fd_set read_set, write_set;
- int sock, max_fd = -1, msec = milliseconds;
- struct usa sa;
-
- current_time = time(0);
- FD_ZERO(&read_set);
- FD_ZERO(&write_set);
-
- /* Add listening sockets to the read set */
- LL_FOREACH(&ctx->listeners, lp) {
- l = LL_ENTRY(lp, struct listener, link);
- FD_SET(l->sock, &read_set);
- if (l->sock > max_fd)
- max_fd = l->sock;
- DBG(("FD_SET(%d) (listening)", l->sock));
- }
-
- /* Multiplex streams */
- LL_FOREACH(&ctx->connections, lp) {
- c = LL_ENTRY(lp, struct conn, link);
-
- /* If there is a space in remote IO, check remote socket */
- if (io_space_len(&c->rem.io))
- add_to_set(c->rem.chan.fd, &read_set, &max_fd);
-
-#if !defined(NO_CGI)
- /*
- * If there is a space in local IO, and local endpoint is
- * CGI, check local socket for read availability
- */
- if (io_space_len(&c->loc.io) && (c->loc.flags & FLAG_R) &&
- c->loc.io_class == &io_cgi)
- add_to_set(c->loc.chan.fd, &read_set, &max_fd);
-
- /*
- * If there is some data read from remote socket, and
- * local endpoint is CGI, check local for write availability
- */
- if (io_data_len(&c->rem.io) && (c->loc.flags & FLAG_W) &&
- c->loc.io_class == &io_cgi)
- add_to_set(c->loc.chan.fd, &write_set, &max_fd);
-#endif /* NO_CGI */
-
- /*
- * If there is some data read from local endpoint, check the
- * remote socket for write availability
- */
- if (io_data_len(&c->loc.io))
- add_to_set(c->rem.chan.fd, &write_set, &max_fd);
-
- if (io_space_len(&c->loc.io) && (c->loc.flags & FLAG_R) &&
- (c->loc.flags & FLAG_ALWAYS_READY))
- msec = 0;
-
- if (io_data_len(&c->rem.io) && (c->loc.flags & FLAG_W) &&
- (c->loc.flags & FLAG_ALWAYS_READY))
- msec = 0;
- }
-
- tv.tv_sec = msec / 1000;
- tv.tv_usec = (msec % 1000) * 1000;
-
- /* Check IO readiness */
- if (select(max_fd + 1, &read_set, &write_set, NULL, &tv) < 0) {
-#ifdef _WIN32
- /*
- * On windows, if read_set and write_set are empty,
- * select() returns "Invalid parameter" error
- * (at least on my Windows XP Pro). So in this case,
- * we sleep here.
- */
- Sleep(milliseconds);
-#endif /* _WIN32 */
- DBG(("select: %d", ERRNO));
- return;
- }
-
- /* Check for incoming connections on listener sockets */
- LL_FOREACH(&ctx->listeners, lp) {
- l = LL_ENTRY(lp, struct listener, link);
- if (!FD_ISSET(l->sock, &read_set))
- continue;
- do {
- sa.len = sizeof(sa.u.sin);
- if ((sock = accept(l->sock, &sa.u.sa, &sa.len)) != -1) {
-#if defined(_WIN32)
- if (!is_allowed(ctx, &sa)) {
- elog(E_LOG, NULL, "shttpd_poll: %s "
- "is not allowed to connect",
- inet_ntoa(sa.u.sin.sin_addr));
- (void) closesocket(sock);
- } else {
- shttpd_add_socket(ctx, sock, l->is_ssl);
- }
-#else
- if (sock >= (int) FD_SETSIZE) {
- elog(E_LOG, NULL,
- "shttpd_poll: ctx %p: disarding "
- "socket %d, too busy", ctx, sock);
- (void) closesocket(sock);
- } else if (!is_allowed(ctx, &sa)) {
- elog(E_LOG, NULL, "shttpd_poll: %s "
- "is not allowed to connect",
- inet_ntoa(sa.u.sin.sin_addr));
- (void) closesocket(sock);
- } else {
- shttpd_add_socket(ctx, sock, l->is_ssl);
- }
-#endif /* _WIN32 */
- }
- } while (sock != -1);
- }
-
- /* Process all connections */
- LL_FOREACH_SAFE(&ctx->connections, lp, tmp) {
- c = LL_ENTRY(lp, struct conn, link);
- process_connection(c, FD_ISSET(c->rem.chan.fd, &read_set),
- ((c->loc.flags & FLAG_ALWAYS_READY)
-#if !defined(NO_CGI)
- || (c->loc.io_class == &io_cgi &&
- FD_ISSET(c->loc.chan.fd, &read_set))
-#endif /* NO_CGI */
- ));
- }
-}
-
-void
-free_list(struct llhead *head, void (*dtor)(struct llhead *))
-{
- struct llhead *lp, *tmp;
-
- LL_FOREACH_SAFE(head, lp, tmp) {
- LL_DEL(lp);
- dtor(lp);
- }
-}
-
-void
-listener_destructor(struct llhead *lp)
-{
- struct listener *listener = LL_ENTRY(lp, struct listener, link);
-
- (void) closesocket(listener->sock);
- free(listener);
-}
-
-void
-registered_uri_destructor(struct llhead *lp)
-{
- struct registered_uri *ruri = LL_ENTRY(lp, struct registered_uri, link);
-
- free((void *) ruri->uri);
- free(ruri);
-}
-
-static void
-acl_destructor(struct llhead *lp)
-{
- struct acl *acl = LL_ENTRY(lp, struct acl, link);
- free(acl);
-}
-
-/*
- * Deallocate shttpd object, free up the resources
- */
-void
-shttpd_fini(struct shttpd_ctx *ctx)
-{
- size_t i;
-
- free_list(&ctx->connections, disconnect);
- free_list(&ctx->registered_uris, registered_uri_destructor);
- free_list(&ctx->acl, acl_destructor);
- free_list(&ctx->listeners, listener_destructor);
- free_list(&ctx->ssi_funcs, ssi_func_destructor);
-
- for (i = 0; i < NELEMS(ctx->options); i++)
- if (ctx->options[i] != NULL)
- free(ctx->options[i]);
-
- if (ctx->access_log) (void) fclose(ctx->access_log);
- if (ctx->error_log) (void) fclose(ctx->error_log);
-
- /* TODO: free SSL context */
-
- free(ctx);
-}
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * $Id: shttpd.h,v 1.9 2008/02/13 20:44:32 drozd Exp $
- */
-
-#ifndef SHTTPD_HEADER_INCLUDED
-#define SHTTPD_HEADER_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-struct ubuf {
- char *buf; /* Buffer pointer */
- int len; /* Size of a buffer */
- int num_bytes; /* Bytes processed by callback */
-};
-
-/*
- * This structure is passed to the user callback function
- */
-struct shttpd_arg {
- void *priv; /* Private! Do not touch! */
- void *state; /* User state */
- void *user_data; /* User-defined data */
- struct ubuf in; /* Input is here, POST data */
- struct ubuf out; /* Output goes here */
- unsigned int flags;
-#define SHTTPD_END_OF_OUTPUT 1
-#define SHTTPD_CONNECTION_ERROR 2
-#define SHTTPD_MORE_POST_DATA 4
-#define SHTTPD_POST_BUFFER_FULL 8
-#define SHTTPD_SSI_EVAL_TRUE 16
-};
-
-/*
- * User callback function. Called when certain registered URLs have been
- * requested. These are the requirements to the callback function:
- *
- * 1. it must copy data into 'out.buf' buffer, not more than 'out.len' bytes,
- * and record how many bytes are copied, into 'out.num_bytes'
- * 2. it must not block the execution
- * 3. it must set SHTTPD_END_OF_OUTPUT flag when finished
- * 4. for POST requests, it must process the incoming data (in.buf) of length
- * 'in.len', and set 'in.num_bytes', which is how many bytes of POST
- * data is read and can be discarded by SHTTPD.
- * 5. If callback allocates arg->state, to keep state, it must deallocate it
- * at the end of coonection SHTTPD_CONNECTION_ERROR or SHTTPD_END_OF_OUTPUT
- */
-typedef void (*shttpd_callback_t)(struct shttpd_arg *);
-
-/*
- * shttpd_init Initialize shttpd context.
- * shttpd_set_option Set new value for option.
- * shttpd_fini Dealocate the context
- * shttpd_register_uri Setup the callback function for specified URL.
- * shtppd_listen Setup a listening socket in the SHTTPD context
- * shttpd_poll Do connections processing
- * shttpd_version return string with SHTTPD version
- * shttpd_get_var Fetch POST/GET variable value by name. Return value len
- * shttpd_get_header return value of the specified HTTP header
- * shttpd_get_env return string values for the following
- * pseudo-variables: "REQUEST_METHOD", "REQUEST_URI",
- * "REMOTE_USER" and "REMOTE_ADDR".
- */
-
-struct shttpd_ctx;
-
-struct shttpd_ctx *shttpd_init(void);
-void shttpd_set_option(struct shttpd_ctx *, const char *opt, const char *val);
-void shttpd_fini(struct shttpd_ctx *);
-int shttpd_listen(struct shttpd_ctx *ctx, int port, int is_ssl);
-void shttpd_register_uri(struct shttpd_ctx *ctx, const char *uri,
- shttpd_callback_t callback, void *const user_data);
-void shttpd_poll(struct shttpd_ctx *, int milliseconds);
-const char *shttpd_version(void);
-int shttpd_get_var(const char *var, const char *buf, int buf_len,
- char *value, int value_len);
-const char *shttpd_get_header(struct shttpd_arg *, const char *header_name);
-const char *shttpd_get_env(struct shttpd_arg *, const char *name);
-void shttpd_get_http_version(struct shttpd_arg *,
- unsigned long *major, unsigned long *minor);
-size_t shttpd_printf(struct shttpd_arg *, const char *fmt, ...);
-void shttpd_handle_error(struct shttpd_ctx *ctx, int status,
- shttpd_callback_t func, void *const data);
-void shttpd_register_ssi_func(struct shttpd_ctx *ctx, const char *name,
- shttpd_callback_t func, void *const user_data);
-
-/*
- * The following three functions are for applications that need to
- * load-balance the connections on their own. Many threads may be spawned
- * with one SHTTPD context per thread. Boss thread may only wait for
- * new connections by means of shttpd_accept(). Then it may scan thread
- * pool for the idle thread by means of shttpd_active(), and add new
- * connection to the context by means of shttpd_add().
- */
-void shttpd_add_socket(struct shttpd_ctx *, int sock, int is_ssl);
-int shttpd_accept(int lsn_sock, int milliseconds);
-int shttpd_active(struct shttpd_ctx *);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* SHTTPD_HEADER_INCLUDED */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-/*
- * Snatched from OpenSSL includes. I put the prototypes here to be independent
- * from the OpenSSL source installation. Having this, shttpd + SSL can be
- * built on any system with binary SSL libraries installed.
- */
-
-typedef struct ssl_st SSL;
-typedef struct ssl_method_st SSL_METHOD;
-typedef struct ssl_ctx_st SSL_CTX;
-
-#define SSL_ERROR_WANT_READ 2
-#define SSL_ERROR_WANT_WRITE 3
-#define SSL_FILETYPE_PEM 1
-
-/*
- * Dynamically loaded SSL functionality
- */
-struct ssl_func {
- const char *name; /* SSL function name */
- union variant ptr; /* Function pointer */
-};
-
-extern struct ssl_func ssl_sw[];
-
-#define FUNC(x) ssl_sw[x].ptr.v_func
-
-#define SSL_free(x) (* (void (*)(SSL *)) FUNC(0))(x)
-#define SSL_accept(x) (* (int (*)(SSL *)) FUNC(1))(x)
-#define SSL_connect(x) (* (int (*)(SSL *)) FUNC(2))(x)
-#define SSL_read(x,y,z) (* (int (*)(SSL *, void *, int)) FUNC(3))((x),(y),(z))
-#define SSL_write(x,y,z) \
- (* (int (*)(SSL *, const void *,int)) FUNC(4))((x), (y), (z))
-#define SSL_get_error(x,y)(* (int (*)(SSL *, int)) FUNC(5))((x), (y))
-#define SSL_set_fd(x,y) (* (int (*)(SSL *, int)) FUNC(6))((x), (y))
-#define SSL_new(x) (* (SSL * (*)(SSL_CTX *)) FUNC(7))(x)
-#define SSL_CTX_new(x) (* (SSL_CTX * (*)(SSL_METHOD *)) FUNC(8))(x)
-#define SSLv23_server_method() (* (SSL_METHOD * (*)(void)) FUNC(9))()
-#define SSL_library_init() (* (int (*)(void)) FUNC(10))()
-#define SSL_CTX_use_PrivateKey_file(x,y,z) (* (int (*)(SSL_CTX *, \
- const char *, int)) FUNC(11))((x), (y), (z))
-#define SSL_CTX_use_certificate_file(x,y,z) (* (int (*)(SSL_CTX *, \
- const char *, int)) FUNC(12))((x), (y), (z))
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#ifndef STD_HEADERS_INCLUDED
-#define STD_HEADERS_INCLUDED
-
-#ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-#endif /* _WIN32_WCE */
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <wchar.h>
-
-#if defined(_WIN32) /* Windows specific */
-#include "compat_win32.h"
-#elif defined(__rtems__) /* RTEMS specific */
-#include "compat_rtems.h"
-#else /* UNIX specific */
-#include "compat_unix.h"
-#endif /* _WIN32 */
-
-#endif /* STD_HEADERS_INCLUDED */
+++ /dev/null
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * All rights reserved
- *
- * "THE BEER-WARE LICENSE" (Revision 42):
- * Sergey Lyubka wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.
- */
-
-#include "defs.h"
-
-void
-my_strlcpy(register char *dst, register const char *src, size_t n)
-{
- for (; *src != '\0' && n > 1; n--)
- *dst++ = *src++;
- *dst = '\0';
-}
-
-int
-my_strncasecmp(const char *str1, const char *str2, size_t len)
-{
- register const unsigned char *s1 = (unsigned char *) str1,
- *s2 = (unsigned char *) str2, *e;
- int ret;
-
- for (e = s1 + len - 1; s1 < e && *s1 != '\0' && *s2 != '\0' &&
- tolower(*s1) == tolower(*s2); s1++, s2++) ;
- ret = tolower(*s1) - tolower(*s2);
-
- return (ret);
-}
-
-char *
-my_strndup(const char *ptr, size_t len)
-{
- char *p;
-
- if ((p = malloc(len + 1)) != NULL)
- my_strlcpy(p, ptr, len + 1);
-
- return (p);
-
-}
-
-char *
-my_strdup(const char *str)
-{
- return (my_strndup(str, strlen(str)));
-}
-
-/*
- * Sane snprintf(). Acts like snprintf(), but never return -1 or the
- * value bigger than supplied buffer.
- * Thanks Adam Zeldis to pointing snprintf()-caused vulnerability
- * in his audit report.
- */
-int
-my_snprintf(char *buf, size_t buflen, const char *fmt, ...)
-{
- va_list ap;
- int n;
-
- if (buflen == 0)
- return (0);
-
- va_start(ap, fmt);
- n = vsnprintf(buf, buflen, fmt, ap);
- va_end(ap);
-
- if (n < 0 || (size_t) n >= buflen)
- n = buflen - 1;
- buf[n] = '\0';
-
- return (n);
-}
-
-/*
- * Verify that given file has certain extension
- */
-int
-match_extension(const char *path, const char *ext_list)
-{
- size_t len, path_len;
-
- path_len = strlen(path);
-
- FOR_EACH_WORD_IN_LIST(ext_list, len)
- if (len < path_len && path[path_len - len - 1] == '.' &&
- !my_strncasecmp(path + path_len - len, ext_list, len))
- return (TRUE);
-
- return (FALSE);
-}
+++ /dev/null
-/*
-www.sourceforge.net/projects/tinyxml
-Original file by Yves Berquin.
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-/*
- * THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005.
- */
-
-
-#ifndef TIXML_USE_STL
-
-#include "tinystr.h"
-
-// Error value for find primitive
-const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
-
-
-// Null rep.
-TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
-
-
-void TiXmlString::reserve (size_type cap)
-{
- if (cap > capacity())
- {
- TiXmlString tmp;
- tmp.init(length(), cap);
- memcpy(tmp.start(), data(), length());
- swap(tmp);
- }
-}
-
-
-TiXmlString& TiXmlString::assign(const char* str, size_type len)
-{
- size_type cap = capacity();
- if (len > cap || cap > 3*(len + 8))
- {
- TiXmlString tmp;
- tmp.init(len);
- memcpy(tmp.start(), str, len);
- swap(tmp);
- }
- else
- {
- memmove(start(), str, len);
- set_size(len);
- }
- return *this;
-}
-
-
-TiXmlString& TiXmlString::append(const char* str, size_type len)
-{
- size_type newsize = length() + len;
- if (newsize > capacity())
- {
- reserve (newsize + capacity());
- }
- memmove(finish(), str, len);
- set_size(newsize);
- return *this;
-}
-
-
-TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
-{
- TiXmlString tmp;
- tmp.reserve(a.length() + b.length());
- tmp += a;
- tmp += b;
- return tmp;
-}
-
-TiXmlString operator + (const TiXmlString & a, const char* b)
-{
- TiXmlString tmp;
- TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
- tmp.reserve(a.length() + b_len);
- tmp += a;
- tmp.append(b, b_len);
- return tmp;
-}
-
-TiXmlString operator + (const char* a, const TiXmlString & b)
-{
- TiXmlString tmp;
- TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
- tmp.reserve(a_len + b.length());
- tmp.append(a, a_len);
- tmp += b;
- return tmp;
-}
-
-
-#endif // TIXML_USE_STL
+++ /dev/null
-/*
-www.sourceforge.net/projects/tinyxml
-Original file by Yves Berquin.
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-/*
- * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
- *
- * - completely rewritten. compact, clean, and fast implementation.
- * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
- * - fixed reserve() to work as per specification.
- * - fixed buggy compares operator==(), operator<(), and operator>()
- * - fixed operator+=() to take a const ref argument, following spec.
- * - added "copy" constructor with length, and most compare operators.
- * - added swap(), clear(), size(), capacity(), operator+().
- */
-
-#ifndef TIXML_USE_STL
-
-#ifndef TIXML_STRING_INCLUDED
-#define TIXML_STRING_INCLUDED
-
-#include <assert.h>
-#include <string.h>
-
-/* The support for explicit isn't that universal, and it isn't really
- required - it is used to check that the TiXmlString class isn't incorrectly
- used. Be nice to old compilers and macro it here:
-*/
-#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
- // Microsoft visual studio, version 6 and higher.
- #define TIXML_EXPLICIT explicit
-#elif defined(__GNUC__) && (__GNUC__ >= 3 )
- // GCC version 3 and higher.s
- #define TIXML_EXPLICIT explicit
-#else
- #define TIXML_EXPLICIT
-#endif
-
-
-/*
- TiXmlString is an emulation of a subset of the std::string template.
- Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
- Only the member functions relevant to the TinyXML project have been implemented.
- The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
- a string and there's no more room, we allocate a buffer twice as big as we need.
-*/
-class TiXmlString
-{
- public :
- // The size type used
- typedef size_t size_type;
-
- // Error value for find primitive
- static const size_type npos; // = -1;
-
-
- // TiXmlString empty constructor
- TiXmlString () : rep_(&nullrep_)
- {
- }
-
- // TiXmlString copy constructor
- TiXmlString ( const TiXmlString & copy) : rep_(0)
- {
- init(copy.length());
- memcpy(start(), copy.data(), length());
- }
-
- // TiXmlString constructor, based on a string
- TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
- {
- init( static_cast<size_type>( strlen(copy) ));
- memcpy(start(), copy, length());
- }
-
- // TiXmlString constructor, based on a string
- TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
- {
- init(len);
- memcpy(start(), str, len);
- }
-
- // TiXmlString destructor
- ~TiXmlString ()
- {
- quit();
- }
-
- // = operator
- TiXmlString& operator = (const char * copy)
- {
- return assign( copy, (size_type)strlen(copy));
- }
-
- // = operator
- TiXmlString& operator = (const TiXmlString & copy)
- {
- return assign(copy.start(), copy.length());
- }
-
-
- // += operator. Maps to append
- TiXmlString& operator += (const char * suffix)
- {
- return append(suffix, static_cast<size_type>( strlen(suffix) ));
- }
-
- // += operator. Maps to append
- TiXmlString& operator += (char single)
- {
- return append(&single, 1);
- }
-
- // += operator. Maps to append
- TiXmlString& operator += (const TiXmlString & suffix)
- {
- return append(suffix.data(), suffix.length());
- }
-
-
- // Convert a TiXmlString into a null-terminated char *
- const char * c_str () const { return rep_->str; }
-
- // Convert a TiXmlString into a char * (need not be null terminated).
- const char * data () const { return rep_->str; }
-
- // Return the length of a TiXmlString
- size_type length () const { return rep_->size; }
-
- // Alias for length()
- size_type size () const { return rep_->size; }
-
- // Checks if a TiXmlString is empty
- bool empty () const { return rep_->size == 0; }
-
- // Return capacity of string
- size_type capacity () const { return rep_->capacity; }
-
-
- // single char extraction
- const char& at (size_type index) const
- {
- assert( index < length() );
- return rep_->str[ index ];
- }
-
- // [] operator
- char& operator [] (size_type index) const
- {
- assert( index < length() );
- return rep_->str[ index ];
- }
-
- // find a char in a string. Return TiXmlString::npos if not found
- size_type find (char lookup) const
- {
- return find(lookup, 0);
- }
-
- // find a char in a string from an offset. Return TiXmlString::npos if not found
- size_type find (char tofind, size_type offset) const
- {
- if (offset >= length()) return npos;
-
- for (const char* p = c_str() + offset; *p != '\0'; ++p)
- {
- if (*p == tofind) return static_cast< size_type >( p - c_str() );
- }
- return npos;
- }
-
- void clear ()
- {
- //Lee:
- //The original was just too strange, though correct:
- // TiXmlString().swap(*this);
- //Instead use the quit & re-init:
- quit();
- init(0,0);
- }
-
- /* Function to reserve a big amount of data when we know we'll need it. Be aware that this
- function DOES NOT clear the content of the TiXmlString if any exists.
- */
- void reserve (size_type cap);
-
- TiXmlString& assign (const char* str, size_type len);
-
- TiXmlString& append (const char* str, size_type len);
-
- void swap (TiXmlString& other)
- {
- Rep* r = rep_;
- rep_ = other.rep_;
- other.rep_ = r;
- }
-
- private:
-
- void init(size_type sz) { init(sz, sz); }
- void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
- char* start() const { return rep_->str; }
- char* finish() const { return rep_->str + rep_->size; }
-
- struct Rep
- {
- size_type size, capacity;
- char str[1];
- };
-
- void init(size_type sz, size_type cap)
- {
- if (cap)
- {
- // Lee: the original form:
- // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
- // doesn't work in some cases of new being overloaded. Switching
- // to the normal allocation, although use an 'int' for systems
- // that are overly picky about structure alignment.
- const size_type bytesNeeded = sizeof(Rep) + cap;
- const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
- rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
-
- rep_->str[ rep_->size = sz ] = '\0';
- rep_->capacity = cap;
- }
- else
- {
- rep_ = &nullrep_;
- }
- }
-
- void quit()
- {
- if (rep_ != &nullrep_)
- {
- // The rep_ is really an array of ints. (see the allocator, above).
- // Cast it back before delete, so the compiler won't incorrectly call destructors.
- delete [] ( reinterpret_cast<int*>( rep_ ) );
- }
- }
-
- Rep * rep_;
- static Rep nullrep_;
-
-} ;
-
-
-inline bool operator == (const TiXmlString & a, const TiXmlString & b)
-{
- return ( a.length() == b.length() ) // optimization on some platforms
- && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
-}
-inline bool operator < (const TiXmlString & a, const TiXmlString & b)
-{
- return strcmp(a.c_str(), b.c_str()) < 0;
-}
-
-inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
-inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
-inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
-inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
-
-inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
-inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
-inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
-inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
-
-TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
-TiXmlString operator + (const TiXmlString & a, const char* b);
-TiXmlString operator + (const char* a, const TiXmlString & b);
-
-
-/*
- TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
- Only the operators that we need for TinyXML have been developped.
-*/
-class TiXmlOutStream : public TiXmlString
-{
-public :
-
- // TiXmlOutStream << operator.
- TiXmlOutStream & operator << (const TiXmlString & in)
- {
- *this += in;
- return *this;
- }
-
- // TiXmlOutStream << operator.
- TiXmlOutStream & operator << (const char * in)
- {
- *this += in;
- return *this;
- }
-
-} ;
-
-#endif // TIXML_STRING_INCLUDED
-#endif // TIXML_USE_STL
+++ /dev/null
-/*
-www.sourceforge.net/projects/tinyxml
-Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-#include <ctype.h>
-
-#ifdef TIXML_USE_STL
-#include <sstream>
-#include <iostream>
-#endif
-
-#include "tinyxml.h"
-
-
-bool TiXmlBase::condenseWhiteSpace = true;
-
-// Microsoft compiler security
-FILE* TiXmlFOpen( const char* filename, const char* mode )
-{
- #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
- FILE* fp = 0;
- errno_t err = fopen_s( &fp, filename, mode );
- if ( !err && fp )
- return fp;
- return 0;
- #else
- return fopen( filename, mode );
- #endif
-}
-
-void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
-{
- int i=0;
-
- while( i<(int)str.length() )
- {
- unsigned char c = (unsigned char) str[i];
-
- if ( c == '&'
- && i < ( (int)str.length() - 2 )
- && str[i+1] == '#'
- && str[i+2] == 'x' )
- {
- // Hexadecimal character reference.
- // Pass through unchanged.
- // © -- copyright symbol, for example.
- //
- // The -1 is a bug fix from Rob Laveaux. It keeps
- // an overflow from happening if there is no ';'.
- // There are actually 2 ways to exit this loop -
- // while fails (error case) and break (semicolon found).
- // However, there is no mechanism (currently) for
- // this function to return an error.
- while ( i<(int)str.length()-1 )
- {
- outString->append( str.c_str() + i, 1 );
- ++i;
- if ( str[i] == ';' )
- break;
- }
- }
- else if ( c == '&' )
- {
- outString->append( entity[0].str, entity[0].strLength );
- ++i;
- }
- else if ( c == '<' )
- {
- outString->append( entity[1].str, entity[1].strLength );
- ++i;
- }
- else if ( c == '>' )
- {
- outString->append( entity[2].str, entity[2].strLength );
- ++i;
- }
- else if ( c == '\"' )
- {
- outString->append( entity[3].str, entity[3].strLength );
- ++i;
- }
- else if ( c == '\'' )
- {
- outString->append( entity[4].str, entity[4].strLength );
- ++i;
- }
- else if ( c < 32 )
- {
- // Easy pass at non-alpha/numeric/symbol
- // Below 32 is symbolic.
- char buf[ 32 ];
-
- #if defined(TIXML_SNPRINTF)
- TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
- #else
- sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
- #endif
-
- //*ME: warning C4267: convert 'size_t' to 'int'
- //*ME: Int-Cast to make compiler happy ...
- outString->append( buf, (int)strlen( buf ) );
- ++i;
- }
- else
- {
- //char realc = (char) c;
- //outString->append( &realc, 1 );
- *outString += (char) c; // somewhat more efficient function call.
- ++i;
- }
- }
-}
-
-
-TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
-{
- parent = 0;
- type = _type;
- firstChild = 0;
- lastChild = 0;
- prev = 0;
- next = 0;
-}
-
-
-TiXmlNode::~TiXmlNode()
-{
- TiXmlNode* node = firstChild;
- TiXmlNode* temp = 0;
-
- while ( node )
- {
- temp = node;
- node = node->next;
- delete temp;
- }
-}
-
-
-void TiXmlNode::CopyTo( TiXmlNode* target ) const
-{
- target->SetValue (value.c_str() );
- target->userData = userData;
-}
-
-
-void TiXmlNode::Clear()
-{
- TiXmlNode* node = firstChild;
- TiXmlNode* temp = 0;
-
- while ( node )
- {
- temp = node;
- node = node->next;
- delete temp;
- }
-
- firstChild = 0;
- lastChild = 0;
-}
-
-
-TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
-{
- assert( node->parent == 0 || node->parent == this );
- assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
-
- if ( node->Type() == TiXmlNode::DOCUMENT )
- {
- delete node;
- if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
- return 0;
- }
-
- node->parent = this;
-
- node->prev = lastChild;
- node->next = 0;
-
- if ( lastChild )
- lastChild->next = node;
- else
- firstChild = node; // it was an empty list.
-
- lastChild = node;
- return node;
-}
-
-
-TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
-{
- if ( addThis.Type() == TiXmlNode::DOCUMENT )
- {
- if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
- return 0;
- }
- TiXmlNode* node = addThis.Clone();
- if ( !node )
- return 0;
-
- return LinkEndChild( node );
-}
-
-
-TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
-{
- if ( !beforeThis || beforeThis->parent != this ) {
- return 0;
- }
- if ( addThis.Type() == TiXmlNode::DOCUMENT )
- {
- if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
- return 0;
- }
-
- TiXmlNode* node = addThis.Clone();
- if ( !node )
- return 0;
- node->parent = this;
-
- node->next = beforeThis;
- node->prev = beforeThis->prev;
- if ( beforeThis->prev )
- {
- beforeThis->prev->next = node;
- }
- else
- {
- assert( firstChild == beforeThis );
- firstChild = node;
- }
- beforeThis->prev = node;
- return node;
-}
-
-
-TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
-{
- if ( !afterThis || afterThis->parent != this ) {
- return 0;
- }
- if ( addThis.Type() == TiXmlNode::DOCUMENT )
- {
- if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
- return 0;
- }
-
- TiXmlNode* node = addThis.Clone();
- if ( !node )
- return 0;
- node->parent = this;
-
- node->prev = afterThis;
- node->next = afterThis->next;
- if ( afterThis->next )
- {
- afterThis->next->prev = node;
- }
- else
- {
- assert( lastChild == afterThis );
- lastChild = node;
- }
- afterThis->next = node;
- return node;
-}
-
-
-TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
-{
- if ( replaceThis->parent != this )
- return 0;
-
- TiXmlNode* node = withThis.Clone();
- if ( !node )
- return 0;
-
- node->next = replaceThis->next;
- node->prev = replaceThis->prev;
-
- if ( replaceThis->next )
- replaceThis->next->prev = node;
- else
- lastChild = node;
-
- if ( replaceThis->prev )
- replaceThis->prev->next = node;
- else
- firstChild = node;
-
- delete replaceThis;
- node->parent = this;
- return node;
-}
-
-
-bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
-{
- if ( removeThis->parent != this )
- {
- assert( 0 );
- return false;
- }
-
- if ( removeThis->next )
- removeThis->next->prev = removeThis->prev;
- else
- lastChild = removeThis->prev;
-
- if ( removeThis->prev )
- removeThis->prev->next = removeThis->next;
- else
- firstChild = removeThis->next;
-
- delete removeThis;
- return true;
-}
-
-const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
-{
- const TiXmlNode* node;
- for ( node = firstChild; node; node = node->next )
- {
- if ( strcmp( node->Value(), _value ) == 0 )
- return node;
- }
- return 0;
-}
-
-
-const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
-{
- const TiXmlNode* node;
- for ( node = lastChild; node; node = node->prev )
- {
- if ( strcmp( node->Value(), _value ) == 0 )
- return node;
- }
- return 0;
-}
-
-
-const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
-{
- if ( !previous )
- {
- return FirstChild();
- }
- else
- {
- assert( previous->parent == this );
- return previous->NextSibling();
- }
-}
-
-
-const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
-{
- if ( !previous )
- {
- return FirstChild( val );
- }
- else
- {
- assert( previous->parent == this );
- return previous->NextSibling( val );
- }
-}
-
-
-const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
-{
- const TiXmlNode* node;
- for ( node = next; node; node = node->next )
- {
- if ( strcmp( node->Value(), _value ) == 0 )
- return node;
- }
- return 0;
-}
-
-
-const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
-{
- const TiXmlNode* node;
- for ( node = prev; node; node = node->prev )
- {
- if ( strcmp( node->Value(), _value ) == 0 )
- return node;
- }
- return 0;
-}
-
-
-void TiXmlElement::RemoveAttribute( const char * name )
-{
- #ifdef TIXML_USE_STL
- TIXML_STRING str( name );
- TiXmlAttribute* node = attributeSet.Find( str );
- #else
- TiXmlAttribute* node = attributeSet.Find( name );
- #endif
- if ( node )
- {
- attributeSet.Remove( node );
- delete node;
- }
-}
-
-const TiXmlElement* TiXmlNode::FirstChildElement() const
-{
- const TiXmlNode* node;
-
- for ( node = FirstChild();
- node;
- node = node->NextSibling() )
- {
- if ( node->ToElement() )
- return node->ToElement();
- }
- return 0;
-}
-
-
-const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
-{
- const TiXmlNode* node;
-
- for ( node = FirstChild( _value );
- node;
- node = node->NextSibling( _value ) )
- {
- if ( node->ToElement() )
- return node->ToElement();
- }
- return 0;
-}
-
-
-const TiXmlElement* TiXmlNode::NextSiblingElement() const
-{
- const TiXmlNode* node;
-
- for ( node = NextSibling();
- node;
- node = node->NextSibling() )
- {
- if ( node->ToElement() )
- return node->ToElement();
- }
- return 0;
-}
-
-
-const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
-{
- const TiXmlNode* node;
-
- for ( node = NextSibling( _value );
- node;
- node = node->NextSibling( _value ) )
- {
- if ( node->ToElement() )
- return node->ToElement();
- }
- return 0;
-}
-
-
-const TiXmlDocument* TiXmlNode::GetDocument() const
-{
- const TiXmlNode* node;
-
- for( node = this; node; node = node->parent )
- {
- if ( node->ToDocument() )
- return node->ToDocument();
- }
- return 0;
-}
-
-
-TiXmlElement::TiXmlElement (const char * _value)
- : TiXmlNode( TiXmlNode::ELEMENT )
-{
- firstChild = lastChild = 0;
- value = _value;
-}
-
-
-#ifdef TIXML_USE_STL
-TiXmlElement::TiXmlElement( const std::string& _value )
- : TiXmlNode( TiXmlNode::ELEMENT )
-{
- firstChild = lastChild = 0;
- value = _value;
-}
-#endif
-
-
-TiXmlElement::TiXmlElement( const TiXmlElement& copy)
- : TiXmlNode( TiXmlNode::ELEMENT )
-{
- firstChild = lastChild = 0;
- copy.CopyTo( this );
-}
-
-
-void TiXmlElement::operator=( const TiXmlElement& base )
-{
- ClearThis();
- base.CopyTo( this );
-}
-
-
-TiXmlElement::~TiXmlElement()
-{
- ClearThis();
-}
-
-
-void TiXmlElement::ClearThis()
-{
- Clear();
- while( attributeSet.First() )
- {
- TiXmlAttribute* node = attributeSet.First();
- attributeSet.Remove( node );
- delete node;
- }
-}
-
-
-const char* TiXmlElement::Attribute( const char* name ) const
-{
- const TiXmlAttribute* node = attributeSet.Find( name );
- if ( node )
- return node->Value();
- return 0;
-}
-
-
-#ifdef TIXML_USE_STL
-const std::string* TiXmlElement::Attribute( const std::string& name ) const
-{
- const TiXmlAttribute* node = attributeSet.Find( name );
- if ( node )
- return &node->ValueStr();
- return 0;
-}
-#endif
-
-
-const char* TiXmlElement::Attribute( const char* name, int* i ) const
-{
- const char* s = Attribute( name );
- if ( i )
- {
- if ( s ) {
- *i = atoi( s );
- }
- else {
- *i = 0;
- }
- }
- return s;
-}
-
-
-#ifdef TIXML_USE_STL
-const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
-{
- const std::string* s = Attribute( name );
- if ( i )
- {
- if ( s ) {
- *i = atoi( s->c_str() );
- }
- else {
- *i = 0;
- }
- }
- return s;
-}
-#endif
-
-
-const char* TiXmlElement::Attribute( const char* name, double* d ) const
-{
- const char* s = Attribute( name );
- if ( d )
- {
- if ( s ) {
- *d = atof( s );
- }
- else {
- *d = 0;
- }
- }
- return s;
-}
-
-
-#ifdef TIXML_USE_STL
-const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
-{
- const std::string* s = Attribute( name );
- if ( d )
- {
- if ( s ) {
- *d = atof( s->c_str() );
- }
- else {
- *d = 0;
- }
- }
- return s;
-}
-#endif
-
-
-int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
-{
- const TiXmlAttribute* node = attributeSet.Find( name );
- if ( !node )
- return TIXML_NO_ATTRIBUTE;
- return node->QueryIntValue( ival );
-}
-
-
-#ifdef TIXML_USE_STL
-int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
-{
- const TiXmlAttribute* node = attributeSet.Find( name );
- if ( !node )
- return TIXML_NO_ATTRIBUTE;
- return node->QueryIntValue( ival );
-}
-#endif
-
-
-int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
-{
- const TiXmlAttribute* node = attributeSet.Find( name );
- if ( !node )
- return TIXML_NO_ATTRIBUTE;
- return node->QueryDoubleValue( dval );
-}
-
-
-#ifdef TIXML_USE_STL
-int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
-{
- const TiXmlAttribute* node = attributeSet.Find( name );
- if ( !node )
- return TIXML_NO_ATTRIBUTE;
- return node->QueryDoubleValue( dval );
-}
-#endif
-
-
-void TiXmlElement::SetAttribute( const char * name, int val )
-{
- char buf[64];
- #if defined(TIXML_SNPRINTF)
- TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
- #else
- sprintf( buf, "%d", val );
- #endif
- SetAttribute( name, buf );
-}
-
-
-#ifdef TIXML_USE_STL
-void TiXmlElement::SetAttribute( const std::string& name, int val )
-{
- std::ostringstream oss;
- oss << val;
- SetAttribute( name, oss.str() );
-}
-#endif
-
-
-void TiXmlElement::SetDoubleAttribute( const char * name, double val )
-{
- char buf[256];
- #if defined(TIXML_SNPRINTF)
- TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
- #else
- sprintf( buf, "%f", val );
- #endif
- SetAttribute( name, buf );
-}
-
-
-void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
-{
- #ifdef TIXML_USE_STL
- TIXML_STRING _name( cname );
- TIXML_STRING _value( cvalue );
- #else
- const char* _name = cname;
- const char* _value = cvalue;
- #endif
-
- TiXmlAttribute* node = attributeSet.Find( _name );
- if ( node )
- {
- node->SetValue( _value );
- return;
- }
-
- TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
- if ( attrib )
- {
- attributeSet.Add( attrib );
- }
- else
- {
- TiXmlDocument* document = GetDocument();
- if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
- }
-}
-
-
-#ifdef TIXML_USE_STL
-void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
-{
- TiXmlAttribute* node = attributeSet.Find( name );
- if ( node )
- {
- node->SetValue( _value );
- return;
- }
-
- TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
- if ( attrib )
- {
- attributeSet.Add( attrib );
- }
- else
- {
- TiXmlDocument* document = GetDocument();
- if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
- }
-}
-#endif
-
-
-void TiXmlElement::Print( FILE* cfile, int depth ) const
-{
- int i;
- assert( cfile );
- for ( i=0; i<depth; i++ ) {
- fprintf( cfile, " " );
- }
-
- fprintf( cfile, "<%s", value.c_str() );
-
- const TiXmlAttribute* attrib;
- for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
- {
- fprintf( cfile, " " );
- attrib->Print( cfile, depth );
- }
-
- // There are 3 different formatting approaches:
- // 1) An element without children is printed as a <foo /> node
- // 2) An element with only a text child is printed as <foo> text </foo>
- // 3) An element with children is printed on multiple lines.
- TiXmlNode* node;
- if ( !firstChild )
- {
- fprintf( cfile, " />" );
- }
- else if ( firstChild == lastChild && firstChild->ToText() )
- {
- fprintf( cfile, ">" );
- firstChild->Print( cfile, depth + 1 );
- fprintf( cfile, "</%s>", value.c_str() );
- }
- else
- {
- fprintf( cfile, ">" );
-
- for ( node = firstChild; node; node=node->NextSibling() )
- {
- if ( !node->ToText() )
- {
- fprintf( cfile, "\n" );
- }
- node->Print( cfile, depth+1 );
- }
- fprintf( cfile, "\n" );
- for( i=0; i<depth; ++i ) {
- fprintf( cfile, " " );
- }
- fprintf( cfile, "</%s>", value.c_str() );
- }
-}
-
-
-void TiXmlElement::CopyTo( TiXmlElement* target ) const
-{
- // superclass:
- TiXmlNode::CopyTo( target );
-
- // Element class:
- // Clone the attributes, then clone the children.
- const TiXmlAttribute* attribute = 0;
- for( attribute = attributeSet.First();
- attribute;
- attribute = attribute->Next() )
- {
- target->SetAttribute( attribute->Name(), attribute->Value() );
- }
-
- TiXmlNode* node = 0;
- for ( node = firstChild; node; node = node->NextSibling() )
- {
- target->LinkEndChild( node->Clone() );
- }
-}
-
-bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
-{
- if ( visitor->VisitEnter( *this, attributeSet.First() ) )
- {
- for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
- {
- if ( !node->Accept( visitor ) )
- break;
- }
- }
- return visitor->VisitExit( *this );
-}
-
-
-TiXmlNode* TiXmlElement::Clone() const
-{
- TiXmlElement* clone = new TiXmlElement( Value() );
- if ( !clone )
- return 0;
-
- CopyTo( clone );
- return clone;
-}
-
-
-const char* TiXmlElement::GetText() const
-{
- const TiXmlNode* child = this->FirstChild();
- if ( child ) {
- const TiXmlText* childText = child->ToText();
- if ( childText ) {
- return childText->Value();
- }
- }
- return 0;
-}
-
-
-TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
-{
- tabsize = 4;
- useMicrosoftBOM = false;
- ClearError();
-}
-
-TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
-{
- tabsize = 4;
- useMicrosoftBOM = false;
- value = documentName;
- ClearError();
-}
-
-
-#ifdef TIXML_USE_STL
-TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
-{
- tabsize = 4;
- useMicrosoftBOM = false;
- value = documentName;
- ClearError();
-}
-#endif
-
-
-TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
-{
- copy.CopyTo( this );
-}
-
-
-void TiXmlDocument::operator=( const TiXmlDocument& copy )
-{
- Clear();
- copy.CopyTo( this );
-}
-
-
-bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
-{
- // See STL_STRING_BUG below.
- //StringToBuffer buf( value );
-
- return LoadFile( Value(), encoding );
-}
-
-
-bool TiXmlDocument::SaveFile() const
-{
- // See STL_STRING_BUG below.
-// StringToBuffer buf( value );
-//
-// if ( buf.buffer && SaveFile( buf.buffer ) )
-// return true;
-//
-// return false;
- return SaveFile( Value() );
-}
-
-bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
-{
- // There was a really terrifying little bug here. The code:
- // value = filename
- // in the STL case, cause the assignment method of the std::string to
- // be called. What is strange, is that the std::string had the same
- // address as it's c_str() method, and so bad things happen. Looks
- // like a bug in the Microsoft STL implementation.
- // Add an extra string to avoid the crash.
- TIXML_STRING filename( _filename );
- value = filename;
-
- // reading in binary mode so that tinyxml can normalize the EOL
- FILE* file = TiXmlFOpen( value.c_str (), "rb" );
-
- if ( file )
- {
- bool result = LoadFile( file, encoding );
- fclose( file );
- return result;
- }
- else
- {
- SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
- return false;
- }
-}
-
-bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
-{
- if ( !file )
- {
- SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
- return false;
- }
-
- // Delete the existing data:
- Clear();
- location.Clear();
-
- // Get the file size, so we can pre-allocate the string. HUGE speed impact.
- long length = 0;
- fseek( file, 0, SEEK_END );
- length = ftell( file );
- fseek( file, 0, SEEK_SET );
-
- // Strange case, but good to handle up front.
- if ( length <= 0 )
- {
- SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
- return false;
- }
-
- // If we have a file, assume it is all one big XML file, and read it in.
- // The document parser may decide the document ends sooner than the entire file, however.
- TIXML_STRING data;
- data.reserve( length );
-
- // Subtle bug here. TinyXml did use fgets. But from the XML spec:
- // 2.11 End-of-Line Handling
- // <snip>
- // <quote>
- // ...the XML processor MUST behave as if it normalized all line breaks in external
- // parsed entities (including the document entity) on input, before parsing, by translating
- // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
- // a single #xA character.
- // </quote>
- //
- // It is not clear fgets does that, and certainly isn't clear it works cross platform.
- // Generally, you expect fgets to translate from the convention of the OS to the c/unix
- // convention, and not work generally.
-
- /*
- while( fgets( buf, sizeof(buf), file ) )
- {
- data += buf;
- }
- */
-
- char* buf = new char[ length+1 ];
- buf[0] = 0;
-
- if ( fread( buf, length, 1, file ) != 1 ) {
- delete [] buf;
- SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
- return false;
- }
-
- const char* lastPos = buf;
- const char* p = buf;
-
- buf[length] = 0;
- while( *p ) {
- assert( p < (buf+length) );
- if ( *p == 0xa ) {
- // Newline character. No special rules for this. Append all the characters
- // since the last string, and include the newline.
- data.append( lastPos, (p-lastPos+1) ); // append, include the newline
- ++p; // move past the newline
- lastPos = p; // and point to the new buffer (may be 0)
- assert( p <= (buf+length) );
- }
- else if ( *p == 0xd ) {
- // Carriage return. Append what we have so far, then
- // handle moving forward in the buffer.
- if ( (p-lastPos) > 0 ) {
- data.append( lastPos, p-lastPos ); // do not add the CR
- }
- data += (char)0xa; // a proper newline
-
- if ( *(p+1) == 0xa ) {
- // Carriage return - new line sequence
- p += 2;
- lastPos = p;
- assert( p <= (buf+length) );
- }
- else {
- // it was followed by something else...that is presumably characters again.
- ++p;
- lastPos = p;
- assert( p <= (buf+length) );
- }
- }
- else {
- ++p;
- }
- }
- // Handle any left over characters.
- if ( p-lastPos ) {
- data.append( lastPos, p-lastPos );
- }
- delete [] buf;
- buf = 0;
-
- Parse( data.c_str(), 0, encoding );
-
- if ( Error() )
- return false;
- else
- return true;
-}
-
-
-bool TiXmlDocument::SaveFile( const char * filename ) const
-{
- // The old c stuff lives on...
- FILE* fp = TiXmlFOpen( filename, "w" );
- if ( fp )
- {
- bool result = SaveFile( fp );
- fclose( fp );
- return result;
- }
- return false;
-}
-
-
-bool TiXmlDocument::SaveFile( FILE* fp ) const
-{
- if ( useMicrosoftBOM )
- {
- const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
- const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
- const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
-
- fputc( TIXML_UTF_LEAD_0, fp );
- fputc( TIXML_UTF_LEAD_1, fp );
- fputc( TIXML_UTF_LEAD_2, fp );
- }
- Print( fp, 0 );
- return (ferror(fp) == 0);
-}
-
-
-void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
-{
- TiXmlNode::CopyTo( target );
-
- target->error = error;
- target->errorId = errorId;
- target->errorDesc = errorDesc;
- target->tabsize = tabsize;
- target->errorLocation = errorLocation;
- target->useMicrosoftBOM = useMicrosoftBOM;
-
- TiXmlNode* node = 0;
- for ( node = firstChild; node; node = node->NextSibling() )
- {
- target->LinkEndChild( node->Clone() );
- }
-}
-
-
-TiXmlNode* TiXmlDocument::Clone() const
-{
- TiXmlDocument* clone = new TiXmlDocument();
- if ( !clone )
- return 0;
-
- CopyTo( clone );
- return clone;
-}
-
-
-void TiXmlDocument::Print( FILE* cfile, int depth ) const
-{
- assert( cfile );
- for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
- {
- node->Print( cfile, depth );
- fprintf( cfile, "\n" );
- }
-}
-
-
-bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
-{
- if ( visitor->VisitEnter( *this ) )
- {
- for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
- {
- if ( !node->Accept( visitor ) )
- break;
- }
- }
- return visitor->VisitExit( *this );
-}
-
-
-const TiXmlAttribute* TiXmlAttribute::Next() const
-{
- // We are using knowledge of the sentinel. The sentinel
- // have a value or name.
- if ( next->value.empty() && next->name.empty() )
- return 0;
- return next;
-}
-
-/*
-TiXmlAttribute* TiXmlAttribute::Next()
-{
- // We are using knowledge of the sentinel. The sentinel
- // have a value or name.
- if ( next->value.empty() && next->name.empty() )
- return 0;
- return next;
-}
-*/
-
-const TiXmlAttribute* TiXmlAttribute::Previous() const
-{
- // We are using knowledge of the sentinel. The sentinel
- // have a value or name.
- if ( prev->value.empty() && prev->name.empty() )
- return 0;
- return prev;
-}
-
-/*
-TiXmlAttribute* TiXmlAttribute::Previous()
-{
- // We are using knowledge of the sentinel. The sentinel
- // have a value or name.
- if ( prev->value.empty() && prev->name.empty() )
- return 0;
- return prev;
-}
-*/
-
-void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
-{
- TIXML_STRING n, v;
-
- EncodeString( name, &n );
- EncodeString( value, &v );
-
- if (value.find ('\"') == TIXML_STRING::npos) {
- if ( cfile ) {
- fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
- }
- if ( str ) {
- (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
- }
- }
- else {
- if ( cfile ) {
- fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
- }
- if ( str ) {
- (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
- }
- }
-}
-
-
-int TiXmlAttribute::QueryIntValue( int* ival ) const
-{
- if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
- return TIXML_SUCCESS;
- return TIXML_WRONG_TYPE;
-}
-
-int TiXmlAttribute::QueryDoubleValue( double* dval ) const
-{
- if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
- return TIXML_SUCCESS;
- return TIXML_WRONG_TYPE;
-}
-
-void TiXmlAttribute::SetIntValue( int _value )
-{
- char buf [64];
- #if defined(TIXML_SNPRINTF)
- TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
- #else
- sprintf (buf, "%d", _value);
- #endif
- SetValue (buf);
-}
-
-void TiXmlAttribute::SetDoubleValue( double _value )
-{
- char buf [256];
- #if defined(TIXML_SNPRINTF)
- TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
- #else
- sprintf (buf, "%lf", _value);
- #endif
- SetValue (buf);
-}
-
-int TiXmlAttribute::IntValue() const
-{
- return atoi (value.c_str ());
-}
-
-double TiXmlAttribute::DoubleValue() const
-{
- return atof (value.c_str ());
-}
-
-
-TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
-{
- copy.CopyTo( this );
-}
-
-
-void TiXmlComment::operator=( const TiXmlComment& base )
-{
- Clear();
- base.CopyTo( this );
-}
-
-
-void TiXmlComment::Print( FILE* cfile, int depth ) const
-{
- assert( cfile );
- for ( int i=0; i<depth; i++ )
- {
- fprintf( cfile, " " );
- }
- fprintf( cfile, "<!--%s-->", value.c_str() );
-}
-
-
-void TiXmlComment::CopyTo( TiXmlComment* target ) const
-{
- TiXmlNode::CopyTo( target );
-}
-
-
-bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
-{
- return visitor->Visit( *this );
-}
-
-
-TiXmlNode* TiXmlComment::Clone() const
-{
- TiXmlComment* clone = new TiXmlComment();
-
- if ( !clone )
- return 0;
-
- CopyTo( clone );
- return clone;
-}
-
-
-void TiXmlText::Print( FILE* cfile, int depth ) const
-{
- assert( cfile );
- if ( cdata )
- {
- int i;
- fprintf( cfile, "\n" );
- for ( i=0; i<depth; i++ ) {
- fprintf( cfile, " " );
- }
- fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
- }
- else
- {
- TIXML_STRING buffer;
- EncodeString( value, &buffer );
- fprintf( cfile, "%s", buffer.c_str() );
- }
-}
-
-
-void TiXmlText::CopyTo( TiXmlText* target ) const
-{
- TiXmlNode::CopyTo( target );
- target->cdata = cdata;
-}
-
-
-bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
-{
- return visitor->Visit( *this );
-}
-
-
-TiXmlNode* TiXmlText::Clone() const
-{
- TiXmlText* clone = 0;
- clone = new TiXmlText( "" );
-
- if ( !clone )
- return 0;
-
- CopyTo( clone );
- return clone;
-}
-
-
-TiXmlDeclaration::TiXmlDeclaration( const char * _version,
- const char * _encoding,
- const char * _standalone )
- : TiXmlNode( TiXmlNode::DECLARATION )
-{
- version = _version;
- encoding = _encoding;
- standalone = _standalone;
-}
-
-
-#ifdef TIXML_USE_STL
-TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
- const std::string& _encoding,
- const std::string& _standalone )
- : TiXmlNode( TiXmlNode::DECLARATION )
-{
- version = _version;
- encoding = _encoding;
- standalone = _standalone;
-}
-#endif
-
-
-TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
- : TiXmlNode( TiXmlNode::DECLARATION )
-{
- copy.CopyTo( this );
-}
-
-
-void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
-{
- Clear();
- copy.CopyTo( this );
-}
-
-
-void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
-{
- if ( cfile ) fprintf( cfile, "<?xml " );
- if ( str ) (*str) += "<?xml ";
-
- if ( !version.empty() ) {
- if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
- if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
- }
- if ( !encoding.empty() ) {
- if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
- if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
- }
- if ( !standalone.empty() ) {
- if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
- if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
- }
- if ( cfile ) fprintf( cfile, "?>" );
- if ( str ) (*str) += "?>";
-}
-
-
-void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
-{
- TiXmlNode::CopyTo( target );
-
- target->version = version;
- target->encoding = encoding;
- target->standalone = standalone;
-}
-
-
-bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
-{
- return visitor->Visit( *this );
-}
-
-
-TiXmlNode* TiXmlDeclaration::Clone() const
-{
- TiXmlDeclaration* clone = new TiXmlDeclaration();
-
- if ( !clone )
- return 0;
-
- CopyTo( clone );
- return clone;
-}
-
-
-void TiXmlUnknown::Print( FILE* cfile, int depth ) const
-{
- for ( int i=0; i<depth; i++ )
- fprintf( cfile, " " );
- fprintf( cfile, "<%s>", value.c_str() );
-}
-
-
-void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
-{
- TiXmlNode::CopyTo( target );
-}
-
-
-bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
-{
- return visitor->Visit( *this );
-}
-
-
-TiXmlNode* TiXmlUnknown::Clone() const
-{
- TiXmlUnknown* clone = new TiXmlUnknown();
-
- if ( !clone )
- return 0;
-
- CopyTo( clone );
- return clone;
-}
-
-
-TiXmlAttributeSet::TiXmlAttributeSet()
-{
- sentinel.next = &sentinel;
- sentinel.prev = &sentinel;
-}
-
-
-TiXmlAttributeSet::~TiXmlAttributeSet()
-{
- assert( sentinel.next == &sentinel );
- assert( sentinel.prev == &sentinel );
-}
-
-
-void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
-{
- #ifdef TIXML_USE_STL
- assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
- #else
- assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
- #endif
-
- addMe->next = &sentinel;
- addMe->prev = sentinel.prev;
-
- sentinel.prev->next = addMe;
- sentinel.prev = addMe;
-}
-
-void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
-{
- TiXmlAttribute* node;
-
- for( node = sentinel.next; node != &sentinel; node = node->next )
- {
- if ( node == removeMe )
- {
- node->prev->next = node->next;
- node->next->prev = node->prev;
- node->next = 0;
- node->prev = 0;
- return;
- }
- }
- assert( 0 ); // we tried to remove a non-linked attribute.
-}
-
-
-#ifdef TIXML_USE_STL
-const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
-{
- for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
- {
- if ( node->name == name )
- return node;
- }
- return 0;
-}
-
-/*
-TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
-{
- for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
- {
- if ( node->name == name )
- return node;
- }
- return 0;
-}
-*/
-#endif
-
-
-const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
-{
- for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
- {
- if ( strcmp( node->name.c_str(), name ) == 0 )
- return node;
- }
- return 0;
-}
-
-/*
-TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
-{
- for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
- {
- if ( strcmp( node->name.c_str(), name ) == 0 )
- return node;
- }
- return 0;
-}
-*/
-
-#ifdef TIXML_USE_STL
-std::istream& operator>> (std::istream & in, TiXmlNode & base)
-{
- TIXML_STRING tag;
- tag.reserve( 8 * 1000 );
- base.StreamIn( &in, &tag );
-
- base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
- return in;
-}
-#endif
-
-
-#ifdef TIXML_USE_STL
-std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
-{
- TiXmlPrinter printer;
- printer.SetStreamPrinting();
- base.Accept( &printer );
- out << printer.Str();
-
- return out;
-}
-
-
-std::string& operator<< (std::string& out, const TiXmlNode& base )
-{
- TiXmlPrinter printer;
- printer.SetStreamPrinting();
- base.Accept( &printer );
- out.append( printer.Str() );
-
- return out;
-}
-#endif
-
-
-TiXmlHandle TiXmlHandle::FirstChild() const
-{
- if ( node )
- {
- TiXmlNode* child = node->FirstChild();
- if ( child )
- return TiXmlHandle( child );
- }
- return TiXmlHandle( 0 );
-}
-
-
-TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
-{
- if ( node )
- {
- TiXmlNode* child = node->FirstChild( value );
- if ( child )
- return TiXmlHandle( child );
- }
- return TiXmlHandle( 0 );
-}
-
-
-TiXmlHandle TiXmlHandle::FirstChildElement() const
-{
- if ( node )
- {
- TiXmlElement* child = node->FirstChildElement();
- if ( child )
- return TiXmlHandle( child );
- }
- return TiXmlHandle( 0 );
-}
-
-
-TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
-{
- if ( node )
- {
- TiXmlElement* child = node->FirstChildElement( value );
- if ( child )
- return TiXmlHandle( child );
- }
- return TiXmlHandle( 0 );
-}
-
-
-TiXmlHandle TiXmlHandle::Child( int count ) const
-{
- if ( node )
- {
- int i;
- TiXmlNode* child = node->FirstChild();
- for ( i=0;
- child && i<count;
- child = child->NextSibling(), ++i )
- {
- // nothing
- }
- if ( child )
- return TiXmlHandle( child );
- }
- return TiXmlHandle( 0 );
-}
-
-
-TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
-{
- if ( node )
- {
- int i;
- TiXmlNode* child = node->FirstChild( value );
- for ( i=0;
- child && i<count;
- child = child->NextSibling( value ), ++i )
- {
- // nothing
- }
- if ( child )
- return TiXmlHandle( child );
- }
- return TiXmlHandle( 0 );
-}
-
-
-TiXmlHandle TiXmlHandle::ChildElement( int count ) const
-{
- if ( node )
- {
- int i;
- TiXmlElement* child = node->FirstChildElement();
- for ( i=0;
- child && i<count;
- child = child->NextSiblingElement(), ++i )
- {
- // nothing
- }
- if ( child )
- return TiXmlHandle( child );
- }
- return TiXmlHandle( 0 );
-}
-
-
-TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
-{
- if ( node )
- {
- int i;
- TiXmlElement* child = node->FirstChildElement( value );
- for ( i=0;
- child && i<count;
- child = child->NextSiblingElement( value ), ++i )
- {
- // nothing
- }
- if ( child )
- return TiXmlHandle( child );
- }
- return TiXmlHandle( 0 );
-}
-
-
-bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
-{
- return true;
-}
-
-bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
-{
- return true;
-}
-
-bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
-{
- DoIndent();
- buffer += "<";
- buffer += element.Value();
-
- for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
- {
- buffer += " ";
- attrib->Print( 0, 0, &buffer );
- }
-
- if ( !element.FirstChild() )
- {
- buffer += " />";
- DoLineBreak();
- }
- else
- {
- buffer += ">";
- if ( element.FirstChild()->ToText()
- && element.LastChild() == element.FirstChild()
- && element.FirstChild()->ToText()->CDATA() == false )
- {
- simpleTextPrint = true;
- // no DoLineBreak()!
- }
- else
- {
- DoLineBreak();
- }
- }
- ++depth;
- return true;
-}
-
-
-bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
-{
- --depth;
- if ( !element.FirstChild() )
- {
- // nothing.
- }
- else
- {
- if ( simpleTextPrint )
- {
- simpleTextPrint = false;
- }
- else
- {
- DoIndent();
- }
- buffer += "</";
- buffer += element.Value();
- buffer += ">";
- DoLineBreak();
- }
- return true;
-}
-
-
-bool TiXmlPrinter::Visit( const TiXmlText& text )
-{
- if ( text.CDATA() )
- {
- DoIndent();
- buffer += "<![CDATA[";
- buffer += text.Value();
- buffer += "]]>";
- DoLineBreak();
- }
- else if ( simpleTextPrint )
- {
- TIXML_STRING str;
- TiXmlBase::EncodeString( text.ValueTStr(), &str );
- buffer += str;
- }
- else
- {
- DoIndent();
- TIXML_STRING str;
- TiXmlBase::EncodeString( text.ValueTStr(), &str );
- buffer += str;
- DoLineBreak();
- }
- return true;
-}
-
-
-bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
-{
- DoIndent();
- declaration.Print( 0, 0, &buffer );
- DoLineBreak();
- return true;
-}
-
-
-bool TiXmlPrinter::Visit( const TiXmlComment& comment )
-{
- DoIndent();
- buffer += "<!--";
- buffer += comment.Value();
- buffer += "-->";
- DoLineBreak();
- return true;
-}
-
-
-bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
-{
- DoIndent();
- buffer += "<";
- buffer += unknown.Value();
- buffer += ">";
- DoLineBreak();
- return true;
-}
-
+++ /dev/null
-/*
-www.sourceforge.net/projects/tinyxml
-Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-
-#ifndef TINYXML_INCLUDED
-#define TINYXML_INCLUDED
-
-#ifdef _MSC_VER
-#pragma warning( push )
-#pragma warning( disable : 4530 )
-#pragma warning( disable : 4786 )
-#endif
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-// Help out windows:
-#if defined( _DEBUG ) && !defined( DEBUG )
-#define DEBUG
-#endif
-
-#ifdef TIXML_USE_STL
- #include <string>
- #include <iostream>
- #include <sstream>
- #define TIXML_STRING std::string
-#else
- #include "tinystr.h"
- #define TIXML_STRING TiXmlString
-#endif
-
-// Deprecated library function hell. Compilers want to use the
-// new safe versions. This probably doesn't fully address the problem,
-// but it gets closer. There are too many compilers for me to fully
-// test. If you get compilation troubles, undefine TIXML_SAFE
-#define TIXML_SAFE
-
-#ifdef TIXML_SAFE
- #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
- // Microsoft visual studio, version 2005 and higher.
- #define TIXML_SNPRINTF _snprintf_s
- #define TIXML_SNSCANF _snscanf_s
- #define TIXML_SSCANF sscanf_s
- #elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
- // Microsoft visual studio, version 6 and higher.
- //#pragma message( "Using _sn* functions." )
- #define TIXML_SNPRINTF _snprintf
- #define TIXML_SNSCANF _snscanf
- #define TIXML_SSCANF sscanf
- #elif defined(__GNUC__) && (__GNUC__ >= 3 )
- // GCC version 3 and higher.s
- //#warning( "Using sn* functions." )
- #define TIXML_SNPRINTF snprintf
- #define TIXML_SNSCANF snscanf
- #define TIXML_SSCANF sscanf
- #else
- #define TIXML_SSCANF sscanf
- #endif
-#endif
-
-class TiXmlDocument;
-class TiXmlElement;
-class TiXmlComment;
-class TiXmlUnknown;
-class TiXmlAttribute;
-class TiXmlText;
-class TiXmlDeclaration;
-class TiXmlParsingData;
-
-const int TIXML_MAJOR_VERSION = 2;
-const int TIXML_MINOR_VERSION = 5;
-const int TIXML_PATCH_VERSION = 3;
-
-/* Internal structure for tracking location of items
- in the XML file.
-*/
-struct TiXmlCursor
-{
- TiXmlCursor() { Clear(); }
- void Clear() { row = col = -1; }
-
- int row; // 0 based.
- int col; // 0 based.
-};
-
-
-/**
- If you call the Accept() method, it requires being passed a TiXmlVisitor
- class to handle callbacks. For nodes that contain other nodes (Document, Element)
- you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
- are simple called with Visit().
-
- If you return 'true' from a Visit method, recursive parsing will continue. If you return
- false, <b>no children of this node or its sibilings</b> will be Visited.
-
- All flavors of Visit methods have a default implementation that returns 'true' (continue
- visiting). You need to only override methods that are interesting to you.
-
- Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
-
- You should never change the document from a callback.
-
- @sa TiXmlNode::Accept()
-*/
-class TiXmlVisitor
-{
-public:
- virtual ~TiXmlVisitor() {}
-
- /// Visit a document.
- virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; }
- /// Visit a document.
- virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; }
-
- /// Visit an element.
- virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; }
- /// Visit an element.
- virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; }
-
- /// Visit a declaration
- virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; }
- /// Visit a text node
- virtual bool Visit( const TiXmlText& /*text*/ ) { return true; }
- /// Visit a comment node
- virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; }
- /// Visit an unknow node
- virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; }
-};
-
-// Only used by Attribute::Query functions
-enum
-{
- TIXML_SUCCESS,
- TIXML_NO_ATTRIBUTE,
- TIXML_WRONG_TYPE
-};
-
-
-// Used by the parsing routines.
-enum TiXmlEncoding
-{
- TIXML_ENCODING_UNKNOWN,
- TIXML_ENCODING_UTF8,
- TIXML_ENCODING_LEGACY
-};
-
-const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
-
-/** TiXmlBase is a base class for every class in TinyXml.
- It does little except to establish that TinyXml classes
- can be printed and provide some utility functions.
-
- In XML, the document and elements can contain
- other elements and other types of nodes.
-
- @verbatim
- A Document can contain: Element (container or leaf)
- Comment (leaf)
- Unknown (leaf)
- Declaration( leaf )
-
- An Element can contain: Element (container or leaf)
- Text (leaf)
- Attributes (not on tree)
- Comment (leaf)
- Unknown (leaf)
-
- A Decleration contains: Attributes (not on tree)
- @endverbatim
-*/
-class TiXmlBase
-{
- friend class TiXmlNode;
- friend class TiXmlElement;
- friend class TiXmlDocument;
-
-public:
- TiXmlBase() : userData(0) {}
- virtual ~TiXmlBase() {}
-
- /** All TinyXml classes can print themselves to a filestream
- or the string class (TiXmlString in non-STL mode, std::string
- in STL mode.) Either or both cfile and str can be null.
-
- This is a formatted print, and will insert
- tabs and newlines.
-
- (For an unformatted stream, use the << operator.)
- */
- virtual void Print( FILE* cfile, int depth ) const = 0;
-
- /** The world does not agree on whether white space should be kept or
- not. In order to make everyone happy, these global, static functions
- are provided to set whether or not TinyXml will condense all white space
- into a single space or not. The default is to condense. Note changing this
- value is not thread safe.
- */
- static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; }
-
- /// Return the current white space setting.
- static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; }
-
- /** Return the position, in the original source file, of this node or attribute.
- The row and column are 1-based. (That is the first row and first column is
- 1,1). If the returns values are 0 or less, then the parser does not have
- a row and column value.
-
- Generally, the row and column value will be set when the TiXmlDocument::Load(),
- TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
- when the DOM was created from operator>>.
-
- The values reflect the initial load. Once the DOM is modified programmatically
- (by adding or changing nodes and attributes) the new values will NOT update to
- reflect changes in the document.
-
- There is a minor performance cost to computing the row and column. Computation
- can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
-
- @sa TiXmlDocument::SetTabSize()
- */
- int Row() const { return location.row + 1; }
- int Column() const { return location.col + 1; } ///< See Row()
-
- void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data.
- void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data.
- const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data.
-
- // Table that returs, for a given lead byte, the total number of bytes
- // in the UTF-8 sequence.
- static const int utf8ByteTable[256];
-
- virtual const char* Parse( const char* p,
- TiXmlParsingData* data,
- TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
-
- /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc,
- or they will be transformed into entities!
- */
- static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out );
-
- enum
- {
- TIXML_NO_ERROR = 0,
- TIXML_ERROR,
- TIXML_ERROR_OPENING_FILE,
- TIXML_ERROR_OUT_OF_MEMORY,
- TIXML_ERROR_PARSING_ELEMENT,
- TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
- TIXML_ERROR_READING_ELEMENT_VALUE,
- TIXML_ERROR_READING_ATTRIBUTES,
- TIXML_ERROR_PARSING_EMPTY,
- TIXML_ERROR_READING_END_TAG,
- TIXML_ERROR_PARSING_UNKNOWN,
- TIXML_ERROR_PARSING_COMMENT,
- TIXML_ERROR_PARSING_DECLARATION,
- TIXML_ERROR_DOCUMENT_EMPTY,
- TIXML_ERROR_EMBEDDED_NULL,
- TIXML_ERROR_PARSING_CDATA,
- TIXML_ERROR_DOCUMENT_TOP_ONLY,
-
- TIXML_ERROR_STRING_COUNT
- };
-
-protected:
-
- static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding );
- inline static bool IsWhiteSpace( char c )
- {
- return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' );
- }
- inline static bool IsWhiteSpace( int c )
- {
- if ( c < 256 )
- return IsWhiteSpace( (char) c );
- return false; // Again, only truly correct for English/Latin...but usually works.
- }
-
- #ifdef TIXML_USE_STL
- static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag );
- static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag );
- #endif
-
- /* Reads an XML name into the string provided. Returns
- a pointer just past the last character of the name,
- or 0 if the function has an error.
- */
- static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
-
- /* Reads text. Returns a pointer past the given end tag.
- Wickedly complex options, but it keeps the (sensitive) code in one place.
- */
- static const char* ReadText( const char* in, // where to start
- TIXML_STRING* text, // the string read
- bool ignoreWhiteSpace, // whether to keep the white space
- const char* endTag, // what ends this text
- bool ignoreCase, // whether to ignore case in the end tag
- TiXmlEncoding encoding ); // the current encoding
-
- // If an entity has been found, transform it into a character.
- static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
-
- // Get a character, while interpreting entities.
- // The length can be from 0 to 4 bytes.
- inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
- {
- assert( p );
- if ( encoding == TIXML_ENCODING_UTF8 )
- {
- *length = utf8ByteTable[ *((const unsigned char*)p) ];
- assert( *length >= 0 && *length < 5 );
- }
- else
- {
- *length = 1;
- }
-
- if ( *length == 1 )
- {
- if ( *p == '&' )
- return GetEntity( p, _value, length, encoding );
- *_value = *p;
- return p+1;
- }
- else if ( *length )
- {
- //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe),
- // and the null terminator isn't needed
- for( int i=0; p[i] && i<*length; ++i ) {
- _value[i] = p[i];
- }
- return p + (*length);
- }
- else
- {
- // Not valid text.
- return 0;
- }
- }
-
- // Return true if the next characters in the stream are any of the endTag sequences.
- // Ignore case only works for english, and should only be relied on when comparing
- // to English words: StringEqual( p, "version", true ) is fine.
- static bool StringEqual( const char* p,
- const char* endTag,
- bool ignoreCase,
- TiXmlEncoding encoding );
-
- static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
-
- TiXmlCursor location;
-
- /// Field containing a generic user pointer
- void* userData;
-
- // None of these methods are reliable for any language except English.
- // Good for approximation, not great for accuracy.
- static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
- static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
- inline static int ToLower( int v, TiXmlEncoding encoding )
- {
- if ( encoding == TIXML_ENCODING_UTF8 )
- {
- if ( v < 128 ) return tolower( v );
- return v;
- }
- else
- {
- return tolower( v );
- }
- }
- static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
-
-private:
- TiXmlBase( const TiXmlBase& ); // not implemented.
- void operator=( const TiXmlBase& base ); // not allowed.
-
- struct Entity
- {
- const char* str;
- unsigned int strLength;
- char chr;
- };
- enum
- {
- NUM_ENTITY = 5,
- MAX_ENTITY_LENGTH = 6
-
- };
- static Entity entity[ NUM_ENTITY ];
- static bool condenseWhiteSpace;
-};
-
-
-/** The parent class for everything in the Document Object Model.
- (Except for attributes).
- Nodes have siblings, a parent, and children. A node can be
- in a document, or stand on its own. The type of a TiXmlNode
- can be queried, and it can be cast to its more defined type.
-*/
-class TiXmlNode : public TiXmlBase
-{
- friend class TiXmlDocument;
- friend class TiXmlElement;
-
-public:
- #ifdef TIXML_USE_STL
-
- /** An input stream operator, for every class. Tolerant of newlines and
- formatting, but doesn't expect them.
- */
- friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
-
- /** An output stream operator, for every class. Note that this outputs
- without any newlines or formatting, as opposed to Print(), which
- includes tabs and new lines.
-
- The operator<< and operator>> are not completely symmetric. Writing
- a node to a stream is very well defined. You'll get a nice stream
- of output, without any extra whitespace or newlines.
-
- But reading is not as well defined. (As it always is.) If you create
- a TiXmlElement (for example) and read that from an input stream,
- the text needs to define an element or junk will result. This is
- true of all input streams, but it's worth keeping in mind.
-
- A TiXmlDocument will read nodes until it reads a root element, and
- all the children of that root element.
- */
- friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
-
- /// Appends the XML node or attribute to a std::string.
- friend std::string& operator<< (std::string& out, const TiXmlNode& base );
-
- #endif
-
- /** The types of XML nodes supported by TinyXml. (All the
- unsupported types are picked up by UNKNOWN.)
- */
- enum NodeType
- {
- DOCUMENT,
- ELEMENT,
- COMMENT,
- UNKNOWN,
- TEXT,
- DECLARATION,
- TYPECOUNT
- };
-
- virtual ~TiXmlNode();
-
- /** The meaning of 'value' changes for the specific type of
- TiXmlNode.
- @verbatim
- Document: filename of the xml file
- Element: name of the element
- Comment: the comment text
- Unknown: the tag contents
- Text: the text string
- @endverbatim
-
- The subclasses will wrap this function.
- */
- const char *Value() const { return value.c_str (); }
-
- #ifdef TIXML_USE_STL
- /** Return Value() as a std::string. If you only use STL,
- this is more efficient than calling Value().
- Only available in STL mode.
- */
- const std::string& ValueStr() const { return value; }
- #endif
-
- const TIXML_STRING& ValueTStr() const { return value; }
-
- /** Changes the value of the node. Defined as:
- @verbatim
- Document: filename of the xml file
- Element: name of the element
- Comment: the comment text
- Unknown: the tag contents
- Text: the text string
- @endverbatim
- */
- void SetValue(const char * _value) { value = _value;}
-
- #ifdef TIXML_USE_STL
- /// STL std::string form.
- void SetValue( const std::string& _value ) { value = _value; }
- #endif
-
- /// Delete all the children of this node. Does not affect 'this'.
- void Clear();
-
- /// One step up the DOM.
- TiXmlNode* Parent() { return parent; }
- const TiXmlNode* Parent() const { return parent; }
-
- const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children.
- TiXmlNode* FirstChild() { return firstChild; }
- const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found.
- /// The first child of this node with the matching 'value'. Will be null if none found.
- TiXmlNode* FirstChild( const char * _value ) {
- // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe)
- // call the method, cast the return back to non-const.
- return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value ));
- }
- const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children.
- TiXmlNode* LastChild() { return lastChild; }
-
- const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children.
- TiXmlNode* LastChild( const char * _value ) {
- return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value ));
- }
-
- #ifdef TIXML_USE_STL
- const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form.
- TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form.
- const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form.
- TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form.
- #endif
-
- /** An alternate way to walk the children of a node.
- One way to iterate over nodes is:
- @verbatim
- for( child = parent->FirstChild(); child; child = child->NextSibling() )
- @endverbatim
-
- IterateChildren does the same thing with the syntax:
- @verbatim
- child = 0;
- while( child = parent->IterateChildren( child ) )
- @endverbatim
-
- IterateChildren takes the previous child as input and finds
- the next one. If the previous child is null, it returns the
- first. IterateChildren will return null when done.
- */
- const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const;
- TiXmlNode* IterateChildren( const TiXmlNode* previous ) {
- return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) );
- }
-
- /// This flavor of IterateChildren searches for children with a particular 'value'
- const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const;
- TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) {
- return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) );
- }
-
- #ifdef TIXML_USE_STL
- const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
- TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
- #endif
-
- /** Add a new node related to this. Adds a child past the LastChild.
- Returns a pointer to the new object or NULL if an error occured.
- */
- TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
-
-
- /** Add a new node related to this. Adds a child past the LastChild.
-
- NOTE: the node to be added is passed by pointer, and will be
- henceforth owned (and deleted) by tinyXml. This method is efficient
- and avoids an extra copy, but should be used with care as it
- uses a different memory model than the other insert functions.
-
- @sa InsertEndChild
- */
- TiXmlNode* LinkEndChild( TiXmlNode* addThis );
-
- /** Add a new node related to this. Adds a child before the specified child.
- Returns a pointer to the new object or NULL if an error occured.
- */
- TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
-
- /** Add a new node related to this. Adds a child after the specified child.
- Returns a pointer to the new object or NULL if an error occured.
- */
- TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis );
-
- /** Replace a child of this node.
- Returns a pointer to the new object or NULL if an error occured.
- */
- TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
-
- /// Delete a child of this node.
- bool RemoveChild( TiXmlNode* removeThis );
-
- /// Navigate to a sibling node.
- const TiXmlNode* PreviousSibling() const { return prev; }
- TiXmlNode* PreviousSibling() { return prev; }
-
- /// Navigate to a sibling node.
- const TiXmlNode* PreviousSibling( const char * ) const;
- TiXmlNode* PreviousSibling( const char *_prev ) {
- return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) );
- }
-
- #ifdef TIXML_USE_STL
- const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
- TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
- const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form.
- TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form.
- #endif
-
- /// Navigate to a sibling node.
- const TiXmlNode* NextSibling() const { return next; }
- TiXmlNode* NextSibling() { return next; }
-
- /// Navigate to a sibling node with the given 'value'.
- const TiXmlNode* NextSibling( const char * ) const;
- TiXmlNode* NextSibling( const char* _next ) {
- return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) );
- }
-
- /** Convenience function to get through elements.
- Calls NextSibling and ToElement. Will skip all non-Element
- nodes. Returns 0 if there is not another element.
- */
- const TiXmlElement* NextSiblingElement() const;
- TiXmlElement* NextSiblingElement() {
- return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() );
- }
-
- /** Convenience function to get through elements.
- Calls NextSibling and ToElement. Will skip all non-Element
- nodes. Returns 0 if there is not another element.
- */
- const TiXmlElement* NextSiblingElement( const char * ) const;
- TiXmlElement* NextSiblingElement( const char *_next ) {
- return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) );
- }
-
- #ifdef TIXML_USE_STL
- const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
- TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
- #endif
-
- /// Convenience function to get through elements.
- const TiXmlElement* FirstChildElement() const;
- TiXmlElement* FirstChildElement() {
- return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() );
- }
-
- /// Convenience function to get through elements.
- const TiXmlElement* FirstChildElement( const char * _value ) const;
- TiXmlElement* FirstChildElement( const char * _value ) {
- return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) );
- }
-
- #ifdef TIXML_USE_STL
- const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
- TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
- #endif
-
- /** Query the type (as an enumerated value, above) of this node.
- The possible types are: DOCUMENT, ELEMENT, COMMENT,
- UNKNOWN, TEXT, and DECLARATION.
- */
- int Type() const { return type; }
-
- /** Return a pointer to the Document this node lives in.
- Returns null if not in a document.
- */
- const TiXmlDocument* GetDocument() const;
- TiXmlDocument* GetDocument() {
- return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() );
- }
-
- /// Returns true if this node has no children.
- bool NoChildren() const { return !firstChild; }
-
- virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
-
- virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
- virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
-
- /** Create an exact duplicate of this node and return it. The memory must be deleted
- by the caller.
- */
- virtual TiXmlNode* Clone() const = 0;
-
- /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the
- XML tree will be conditionally visited and the host will be called back
- via the TiXmlVisitor interface.
-
- This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
- the XML for the callbacks, so the performance of TinyXML is unchanged by using this
- interface versus any other.)
-
- The interface has been based on ideas from:
-
- - http://www.saxproject.org/
- - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
-
- Which are both good references for "visiting".
-
- An example of using Accept():
- @verbatim
- TiXmlPrinter printer;
- tinyxmlDoc.Accept( &printer );
- const char* xmlcstr = printer.CStr();
- @endverbatim
- */
- virtual bool Accept( TiXmlVisitor* visitor ) const = 0;
-
-protected:
- TiXmlNode( NodeType _type );
-
- // Copy to the allocated object. Shared functionality between Clone, Copy constructor,
- // and the assignment operator.
- void CopyTo( TiXmlNode* target ) const;
-
- #ifdef TIXML_USE_STL
- // The real work of the input operator.
- virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0;
- #endif
-
- // Figure out what is at *p, and parse it. Returns null if it is not an xml node.
- TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
-
- TiXmlNode* parent;
- NodeType type;
-
- TiXmlNode* firstChild;
- TiXmlNode* lastChild;
-
- TIXML_STRING value;
-
- TiXmlNode* prev;
- TiXmlNode* next;
-
-private:
- TiXmlNode( const TiXmlNode& ); // not implemented.
- void operator=( const TiXmlNode& base ); // not allowed.
-};
-
-
-/** An attribute is a name-value pair. Elements have an arbitrary
- number of attributes, each with a unique name.
-
- @note The attributes are not TiXmlNodes, since they are not
- part of the tinyXML document object model. There are other
- suggested ways to look at this problem.
-*/
-class TiXmlAttribute : public TiXmlBase
-{
- friend class TiXmlAttributeSet;
-
-public:
- /// Construct an empty attribute.
- TiXmlAttribute() : TiXmlBase()
- {
- document = 0;
- prev = next = 0;
- }
-
- #ifdef TIXML_USE_STL
- /// std::string constructor.
- TiXmlAttribute( const std::string& _name, const std::string& _value )
- {
- name = _name;
- value = _value;
- document = 0;
- prev = next = 0;
- }
- #endif
-
- /// Construct an attribute with a name and value.
- TiXmlAttribute( const char * _name, const char * _value )
- {
- name = _name;
- value = _value;
- document = 0;
- prev = next = 0;
- }
-
- const char* Name() const { return name.c_str(); } ///< Return the name of this attribute.
- const char* Value() const { return value.c_str(); } ///< Return the value of this attribute.
- #ifdef TIXML_USE_STL
- const std::string& ValueStr() const { return value; } ///< Return the value of this attribute.
- #endif
- int IntValue() const; ///< Return the value of this attribute, converted to an integer.
- double DoubleValue() const; ///< Return the value of this attribute, converted to a double.
-
- // Get the tinyxml string representation
- const TIXML_STRING& NameTStr() const { return name; }
-
- /** QueryIntValue examines the value string. It is an alternative to the
- IntValue() method with richer error checking.
- If the value is an integer, it is stored in 'value' and
- the call returns TIXML_SUCCESS. If it is not
- an integer, it returns TIXML_WRONG_TYPE.
-
- A specialized but useful call. Note that for success it returns 0,
- which is the opposite of almost all other TinyXml calls.
- */
- int QueryIntValue( int* _value ) const;
- /// QueryDoubleValue examines the value string. See QueryIntValue().
- int QueryDoubleValue( double* _value ) const;
-
- void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute.
- void SetValue( const char* _value ) { value = _value; } ///< Set the value.
-
- void SetIntValue( int _value ); ///< Set the value from an integer.
- void SetDoubleValue( double _value ); ///< Set the value from a double.
-
- #ifdef TIXML_USE_STL
- /// STL std::string form.
- void SetName( const std::string& _name ) { name = _name; }
- /// STL std::string form.
- void SetValue( const std::string& _value ) { value = _value; }
- #endif
-
- /// Get the next sibling attribute in the DOM. Returns null at end.
- const TiXmlAttribute* Next() const;
- TiXmlAttribute* Next() {
- return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() );
- }
-
- /// Get the previous sibling attribute in the DOM. Returns null at beginning.
- const TiXmlAttribute* Previous() const;
- TiXmlAttribute* Previous() {
- return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() );
- }
-
- bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
- bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; }
- bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; }
-
- /* Attribute parsing starts: first letter of the name
- returns: the next char after the value end quote
- */
- virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
-
- // Prints this Attribute to a FILE stream.
- virtual void Print( FILE* cfile, int depth ) const {
- Print( cfile, depth, 0 );
- }
- void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
-
- // [internal use]
- // Set the document pointer so the attribute can report errors.
- void SetDocument( TiXmlDocument* doc ) { document = doc; }
-
-private:
- TiXmlAttribute( const TiXmlAttribute& ); // not implemented.
- void operator=( const TiXmlAttribute& base ); // not allowed.
-
- TiXmlDocument* document; // A pointer back to a document, for error reporting.
- TIXML_STRING name;
- TIXML_STRING value;
- TiXmlAttribute* prev;
- TiXmlAttribute* next;
-};
-
-
-/* A class used to manage a group of attributes.
- It is only used internally, both by the ELEMENT and the DECLARATION.
-
- The set can be changed transparent to the Element and Declaration
- classes that use it, but NOT transparent to the Attribute
- which has to implement a next() and previous() method. Which makes
- it a bit problematic and prevents the use of STL.
-
- This version is implemented with circular lists because:
- - I like circular lists
- - it demonstrates some independence from the (typical) doubly linked list.
-*/
-class TiXmlAttributeSet
-{
-public:
- TiXmlAttributeSet();
- ~TiXmlAttributeSet();
-
- void Add( TiXmlAttribute* attribute );
- void Remove( TiXmlAttribute* attribute );
-
- const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
- TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
- const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
- TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
-
- const TiXmlAttribute* Find( const char* _name ) const;
- TiXmlAttribute* Find( const char* _name ) {
- return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
- }
- #ifdef TIXML_USE_STL
- const TiXmlAttribute* Find( const std::string& _name ) const;
- TiXmlAttribute* Find( const std::string& _name ) {
- return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
- }
-
- #endif
-
-private:
- //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
- //*ME: this class must be also use a hidden/disabled copy-constructor !!!
- TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed
- void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute)
-
- TiXmlAttribute sentinel;
-};
-
-
-/** The element is a container class. It has a value, the element name,
- and can contain other elements, text, comments, and unknowns.
- Elements also contain an arbitrary number of attributes.
-*/
-class TiXmlElement : public TiXmlNode
-{
-public:
- /// Construct an element.
- TiXmlElement (const char * in_value);
-
- #ifdef TIXML_USE_STL
- /// std::string constructor.
- TiXmlElement( const std::string& _value );
- #endif
-
- TiXmlElement( const TiXmlElement& );
-
- void operator=( const TiXmlElement& base );
-
- virtual ~TiXmlElement();
-
- /** Given an attribute name, Attribute() returns the value
- for the attribute of that name, or null if none exists.
- */
- const char* Attribute( const char* name ) const;
-
- /** Given an attribute name, Attribute() returns the value
- for the attribute of that name, or null if none exists.
- If the attribute exists and can be converted to an integer,
- the integer value will be put in the return 'i', if 'i'
- is non-null.
- */
- const char* Attribute( const char* name, int* i ) const;
-
- /** Given an attribute name, Attribute() returns the value
- for the attribute of that name, or null if none exists.
- If the attribute exists and can be converted to an double,
- the double value will be put in the return 'd', if 'd'
- is non-null.
- */
- const char* Attribute( const char* name, double* d ) const;
-
- /** QueryIntAttribute examines the attribute - it is an alternative to the
- Attribute() method with richer error checking.
- If the attribute is an integer, it is stored in 'value' and
- the call returns TIXML_SUCCESS. If it is not
- an integer, it returns TIXML_WRONG_TYPE. If the attribute
- does not exist, then TIXML_NO_ATTRIBUTE is returned.
- */
- int QueryIntAttribute( const char* name, int* _value ) const;
- /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
- int QueryDoubleAttribute( const char* name, double* _value ) const;
- /// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
- int QueryFloatAttribute( const char* name, float* _value ) const {
- double d;
- int result = QueryDoubleAttribute( name, &d );
- if ( result == TIXML_SUCCESS ) {
- *_value = (float)d;
- }
- return result;
- }
-
- #ifdef TIXML_USE_STL
- /** Template form of the attribute query which will try to read the
- attribute into the specified type. Very easy, very powerful, but
- be careful to make sure to call this with the correct type.
-
- NOTE: This method doesn't work correctly for 'string' types.
-
- @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE
- */
- template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const
- {
- const TiXmlAttribute* node = attributeSet.Find( name );
- if ( !node )
- return TIXML_NO_ATTRIBUTE;
-
- std::stringstream sstream( node->ValueStr() );
- sstream >> *outValue;
- if ( !sstream.fail() )
- return TIXML_SUCCESS;
- return TIXML_WRONG_TYPE;
- }
- /*
- This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string"
- but template specialization is hard to get working cross-compiler. Leaving the bug for now.
-
- // The above will fail for std::string because the space character is used as a seperator.
- // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string
- template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const
- {
- const TiXmlAttribute* node = attributeSet.Find( name );
- if ( !node )
- return TIXML_NO_ATTRIBUTE;
- *outValue = node->ValueStr();
- return TIXML_SUCCESS;
- }
- */
- #endif
-
- /** Sets an attribute of name to a given value. The attribute
- will be created if it does not exist, or changed if it does.
- */
- void SetAttribute( const char* name, const char * _value );
-
- #ifdef TIXML_USE_STL
- const std::string* Attribute( const std::string& name ) const;
- const std::string* Attribute( const std::string& name, int* i ) const;
- const std::string* Attribute( const std::string& name, double* d ) const;
- int QueryIntAttribute( const std::string& name, int* _value ) const;
- int QueryDoubleAttribute( const std::string& name, double* _value ) const;
-
- /// STL std::string form.
- void SetAttribute( const std::string& name, const std::string& _value );
- ///< STL std::string form.
- void SetAttribute( const std::string& name, int _value );
- #endif
-
- /** Sets an attribute of name to a given value. The attribute
- will be created if it does not exist, or changed if it does.
- */
- void SetAttribute( const char * name, int value );
-
- /** Sets an attribute of name to a given value. The attribute
- will be created if it does not exist, or changed if it does.
- */
- void SetDoubleAttribute( const char * name, double value );
-
- /** Deletes an attribute with the given name.
- */
- void RemoveAttribute( const char * name );
- #ifdef TIXML_USE_STL
- void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form.
- #endif
-
- const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element.
- TiXmlAttribute* FirstAttribute() { return attributeSet.First(); }
- const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element.
- TiXmlAttribute* LastAttribute() { return attributeSet.Last(); }
-
- /** Convenience function for easy access to the text inside an element. Although easy
- and concise, GetText() is limited compared to getting the TiXmlText child
- and accessing it directly.
-
- If the first child of 'this' is a TiXmlText, the GetText()
- returns the character string of the Text node, else null is returned.
-
- This is a convenient method for getting the text of simple contained text:
- @verbatim
- <foo>This is text</foo>
- const char* str = fooElement->GetText();
- @endverbatim
-
- 'str' will be a pointer to "This is text".
-
- Note that this function can be misleading. If the element foo was created from
- this XML:
- @verbatim
- <foo><b>This is text</b></foo>
- @endverbatim
-
- then the value of str would be null. The first child node isn't a text node, it is
- another element. From this XML:
- @verbatim
- <foo>This is <b>text</b></foo>
- @endverbatim
- GetText() will return "This is ".
-
- WARNING: GetText() accesses a child node - don't become confused with the
- similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are
- safe type casts on the referenced node.
- */
- const char* GetText() const;
-
- /// Creates a new Element and returns it - the returned element is a copy.
- virtual TiXmlNode* Clone() const;
- // Print the Element to a FILE stream.
- virtual void Print( FILE* cfile, int depth ) const;
-
- /* Attribtue parsing starts: next char past '<'
- returns: next char past '>'
- */
- virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
-
- virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
- virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
-
- /** Walk the XML tree visiting this node and all of its children.
- */
- virtual bool Accept( TiXmlVisitor* visitor ) const;
-
-protected:
-
- void CopyTo( TiXmlElement* target ) const;
- void ClearThis(); // like clear, but initializes 'this' object as well
-
- // Used to be public [internal use]
- #ifdef TIXML_USE_STL
- virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
- #endif
- /* [internal use]
- Reads the "value" of the element -- another element, or text.
- This should terminate with the current end tag.
- */
- const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
-
-private:
-
- TiXmlAttributeSet attributeSet;
-};
-
-
-/** An XML comment.
-*/
-class TiXmlComment : public TiXmlNode
-{
-public:
- /// Constructs an empty comment.
- TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
- /// Construct a comment from text.
- TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) {
- SetValue( _value );
- }
- TiXmlComment( const TiXmlComment& );
- void operator=( const TiXmlComment& base );
-
- virtual ~TiXmlComment() {}
-
- /// Returns a copy of this Comment.
- virtual TiXmlNode* Clone() const;
- // Write this Comment to a FILE stream.
- virtual void Print( FILE* cfile, int depth ) const;
-
- /* Attribtue parsing starts: at the ! of the !--
- returns: next char past '>'
- */
- virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
-
- virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
- virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
-
- /** Walk the XML tree visiting this node and all of its children.
- */
- virtual bool Accept( TiXmlVisitor* visitor ) const;
-
-protected:
- void CopyTo( TiXmlComment* target ) const;
-
- // used to be public
- #ifdef TIXML_USE_STL
- virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
- #endif
-// virtual void StreamOut( TIXML_OSTREAM * out ) const;
-
-private:
-
-};
-
-
-/** XML text. A text node can have 2 ways to output the next. "normal" output
- and CDATA. It will default to the mode it was parsed from the XML file and
- you generally want to leave it alone, but you can change the output mode with
- SetCDATA() and query it with CDATA().
-*/
-class TiXmlText : public TiXmlNode
-{
- friend class TiXmlElement;
-public:
- /** Constructor for text element. By default, it is treated as
- normal, encoded text. If you want it be output as a CDATA text
- element, set the parameter _cdata to 'true'
- */
- TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT)
- {
- SetValue( initValue );
- cdata = false;
- }
- virtual ~TiXmlText() {}
-
- #ifdef TIXML_USE_STL
- /// Constructor.
- TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
- {
- SetValue( initValue );
- cdata = false;
- }
- #endif
-
- TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); }
- void operator=( const TiXmlText& base ) { base.CopyTo( this ); }
-
- // Write this text object to a FILE stream.
- virtual void Print( FILE* cfile, int depth ) const;
-
- /// Queries whether this represents text using a CDATA section.
- bool CDATA() const { return cdata; }
- /// Turns on or off a CDATA representation of text.
- void SetCDATA( bool _cdata ) { cdata = _cdata; }
-
- virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
-
- virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
- virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
-
- /** Walk the XML tree visiting this node and all of its children.
- */
- virtual bool Accept( TiXmlVisitor* content ) const;
-
-protected :
- /// [internal use] Creates a new Element and returns it.
- virtual TiXmlNode* Clone() const;
- void CopyTo( TiXmlText* target ) const;
-
- bool Blank() const; // returns true if all white space and new lines
- // [internal use]
- #ifdef TIXML_USE_STL
- virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
- #endif
-
-private:
- bool cdata; // true if this should be input and output as a CDATA style text element
-};
-
-
-/** In correct XML the declaration is the first entry in the file.
- @verbatim
- <?xml version="1.0" standalone="yes"?>
- @endverbatim
-
- TinyXml will happily read or write files without a declaration,
- however. There are 3 possible attributes to the declaration:
- version, encoding, and standalone.
-
- Note: In this version of the code, the attributes are
- handled as special cases, not generic attributes, simply
- because there can only be at most 3 and they are always the same.
-*/
-class TiXmlDeclaration : public TiXmlNode
-{
-public:
- /// Construct an empty declaration.
- TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {}
-
-#ifdef TIXML_USE_STL
- /// Constructor.
- TiXmlDeclaration( const std::string& _version,
- const std::string& _encoding,
- const std::string& _standalone );
-#endif
-
- /// Construct.
- TiXmlDeclaration( const char* _version,
- const char* _encoding,
- const char* _standalone );
-
- TiXmlDeclaration( const TiXmlDeclaration& copy );
- void operator=( const TiXmlDeclaration& copy );
-
- virtual ~TiXmlDeclaration() {}
-
- /// Version. Will return an empty string if none was found.
- const char *Version() const { return version.c_str (); }
- /// Encoding. Will return an empty string if none was found.
- const char *Encoding() const { return encoding.c_str (); }
- /// Is this a standalone document?
- const char *Standalone() const { return standalone.c_str (); }
-
- /// Creates a copy of this Declaration and returns it.
- virtual TiXmlNode* Clone() const;
- // Print this declaration to a FILE stream.
- virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
- virtual void Print( FILE* cfile, int depth ) const {
- Print( cfile, depth, 0 );
- }
-
- virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
-
- virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
- virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
-
- /** Walk the XML tree visiting this node and all of its children.
- */
- virtual bool Accept( TiXmlVisitor* visitor ) const;
-
-protected:
- void CopyTo( TiXmlDeclaration* target ) const;
- // used to be public
- #ifdef TIXML_USE_STL
- virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
- #endif
-
-private:
-
- TIXML_STRING version;
- TIXML_STRING encoding;
- TIXML_STRING standalone;
-};
-
-
-/** Any tag that tinyXml doesn't recognize is saved as an
- unknown. It is a tag of text, but should not be modified.
- It will be written back to the XML, unchanged, when the file
- is saved.
-
- DTD tags get thrown into TiXmlUnknowns.
-*/
-class TiXmlUnknown : public TiXmlNode
-{
-public:
- TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
- virtual ~TiXmlUnknown() {}
-
- TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); }
- void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); }
-
- /// Creates a copy of this Unknown and returns it.
- virtual TiXmlNode* Clone() const;
- // Print this Unknown to a FILE stream.
- virtual void Print( FILE* cfile, int depth ) const;
-
- virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
-
- virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
- virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
-
- /** Walk the XML tree visiting this node and all of its children.
- */
- virtual bool Accept( TiXmlVisitor* content ) const;
-
-protected:
- void CopyTo( TiXmlUnknown* target ) const;
-
- #ifdef TIXML_USE_STL
- virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
- #endif
-
-private:
-
-};
-
-
-/** Always the top level node. A document binds together all the
- XML pieces. It can be saved, loaded, and printed to the screen.
- The 'value' of a document node is the xml file name.
-*/
-class TiXmlDocument : public TiXmlNode
-{
-public:
- /// Create an empty document, that has no name.
- TiXmlDocument();
- /// Create a document with a name. The name of the document is also the filename of the xml.
- TiXmlDocument( const char * documentName );
-
- #ifdef TIXML_USE_STL
- /// Constructor.
- TiXmlDocument( const std::string& documentName );
- #endif
-
- TiXmlDocument( const TiXmlDocument& copy );
- void operator=( const TiXmlDocument& copy );
-
- virtual ~TiXmlDocument() {}
-
- /** Load a file using the current document value.
- Returns true if successful. Will delete any existing
- document data before loading.
- */
- bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
- /// Save a file using the current document value. Returns true if successful.
- bool SaveFile() const;
- /// Load a file using the given filename. Returns true if successful.
- bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
- /// Save a file using the given filename. Returns true if successful.
- bool SaveFile( const char * filename ) const;
- /** Load a file using the given FILE*. Returns true if successful. Note that this method
- doesn't stream - the entire object pointed at by the FILE*
- will be interpreted as an XML file. TinyXML doesn't stream in XML from the current
- file location. Streaming may be added in the future.
- */
- bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
- /// Save a file using the given FILE*. Returns true if successful.
- bool SaveFile( FILE* ) const;
-
- #ifdef TIXML_USE_STL
- bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version.
- {
-// StringToBuffer f( filename );
-// return ( f.buffer && LoadFile( f.buffer, encoding ));
- return LoadFile( filename.c_str(), encoding );
- }
- bool SaveFile( const std::string& filename ) const ///< STL std::string version.
- {
-// StringToBuffer f( filename );
-// return ( f.buffer && SaveFile( f.buffer ));
- return SaveFile( filename.c_str() );
- }
- #endif
-
- /** Parse the given null terminated block of xml data. Passing in an encoding to this
- method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
- to use that encoding, regardless of what TinyXml might otherwise try to detect.
- */
- virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
-
- /** Get the root element -- the only top level element -- of the document.
- In well formed XML, there should only be one. TinyXml is tolerant of
- multiple elements at the document level.
- */
- const TiXmlElement* RootElement() const { return FirstChildElement(); }
- TiXmlElement* RootElement() { return FirstChildElement(); }
-
- /** If an error occurs, Error will be set to true. Also,
- - The ErrorId() will contain the integer identifier of the error (not generally useful)
- - The ErrorDesc() method will return the name of the error. (very useful)
- - The ErrorRow() and ErrorCol() will return the location of the error (if known)
- */
- bool Error() const { return error; }
-
- /// Contains a textual (english) description of the error if one occurs.
- const char * ErrorDesc() const { return errorDesc.c_str (); }
-
- /** Generally, you probably want the error string ( ErrorDesc() ). But if you
- prefer the ErrorId, this function will fetch it.
- */
- int ErrorId() const { return errorId; }
-
- /** Returns the location (if known) of the error. The first column is column 1,
- and the first row is row 1. A value of 0 means the row and column wasn't applicable
- (memory errors, for example, have no row/column) or the parser lost the error. (An
- error in the error reporting, in that case.)
-
- @sa SetTabSize, Row, Column
- */
- int ErrorRow() const { return errorLocation.row+1; }
- int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow()
-
- /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol())
- to report the correct values for row and column. It does not change the output
- or input in any way.
-
- By calling this method, with a tab size
- greater than 0, the row and column of each node and attribute is stored
- when the file is loaded. Very useful for tracking the DOM back in to
- the source file.
-
- The tab size is required for calculating the location of nodes. If not
- set, the default of 4 is used. The tabsize is set per document. Setting
- the tabsize to 0 disables row/column tracking.
-
- Note that row and column tracking is not supported when using operator>>.
-
- The tab size needs to be enabled before the parse or load. Correct usage:
- @verbatim
- TiXmlDocument doc;
- doc.SetTabSize( 8 );
- doc.Load( "myfile.xml" );
- @endverbatim
-
- @sa Row, Column
- */
- void SetTabSize( int _tabsize ) { tabsize = _tabsize; }
-
- int TabSize() const { return tabsize; }
-
- /** If you have handled the error, it can be reset with this call. The error
- state is automatically cleared if you Parse a new XML block.
- */
- void ClearError() { error = false;
- errorId = 0;
- errorDesc = "";
- errorLocation.row = errorLocation.col = 0;
- //errorLocation.last = 0;
- }
-
- /** Write the document to standard out using formatted printing ("pretty print"). */
- void Print() const { Print( stdout, 0 ); }
-
- /* Write the document to a string using formatted printing ("pretty print"). This
- will allocate a character array (new char[]) and return it as a pointer. The
- calling code pust call delete[] on the return char* to avoid a memory leak.
- */
- //char* PrintToMemory() const;
-
- /// Print this Document to a FILE stream.
- virtual void Print( FILE* cfile, int depth = 0 ) const;
- // [internal use]
- void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
-
- virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
- virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
-
- /** Walk the XML tree visiting this node and all of its children.
- */
- virtual bool Accept( TiXmlVisitor* content ) const;
-
-protected :
- // [internal use]
- virtual TiXmlNode* Clone() const;
- #ifdef TIXML_USE_STL
- virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
- #endif
-
-private:
- void CopyTo( TiXmlDocument* target ) const;
-
- bool error;
- int errorId;
- TIXML_STRING errorDesc;
- int tabsize;
- TiXmlCursor errorLocation;
- bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write.
-};
-
-
-/**
- A TiXmlHandle is a class that wraps a node pointer with null checks; this is
- an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
- DOM structure. It is a separate utility class.
-
- Take an example:
- @verbatim
- <Document>
- <Element attributeA = "valueA">
- <Child attributeB = "value1" />
- <Child attributeB = "value2" />
- </Element>
- <Document>
- @endverbatim
-
- Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
- easy to write a *lot* of code that looks like:
-
- @verbatim
- TiXmlElement* root = document.FirstChildElement( "Document" );
- if ( root )
- {
- TiXmlElement* element = root->FirstChildElement( "Element" );
- if ( element )
- {
- TiXmlElement* child = element->FirstChildElement( "Child" );
- if ( child )
- {
- TiXmlElement* child2 = child->NextSiblingElement( "Child" );
- if ( child2 )
- {
- // Finally do something useful.
- @endverbatim
-
- And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
- of such code. A TiXmlHandle checks for null pointers so it is perfectly safe
- and correct to use:
-
- @verbatim
- TiXmlHandle docHandle( &document );
- TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement();
- if ( child2 )
- {
- // do something useful
- @endverbatim
-
- Which is MUCH more concise and useful.
-
- It is also safe to copy handles - internally they are nothing more than node pointers.
- @verbatim
- TiXmlHandle handleCopy = handle;
- @endverbatim
-
- What they should not be used for is iteration:
-
- @verbatim
- int i=0;
- while ( true )
- {
- TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement();
- if ( !child )
- break;
- // do something
- ++i;
- }
- @endverbatim
-
- It seems reasonable, but it is in fact two embedded while loops. The Child method is
- a linear walk to find the element, so this code would iterate much more than it needs
- to. Instead, prefer:
-
- @verbatim
- TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement();
-
- for( child; child; child=child->NextSiblingElement() )
- {
- // do something
- }
- @endverbatim
-*/
-class TiXmlHandle
-{
-public:
- /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
- TiXmlHandle( TiXmlNode* _node ) { this->node = _node; }
- /// Copy constructor
- TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; }
- TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; }
-
- /// Return a handle to the first child node.
- TiXmlHandle FirstChild() const;
- /// Return a handle to the first child node with the given name.
- TiXmlHandle FirstChild( const char * value ) const;
- /// Return a handle to the first child element.
- TiXmlHandle FirstChildElement() const;
- /// Return a handle to the first child element with the given name.
- TiXmlHandle FirstChildElement( const char * value ) const;
-
- /** Return a handle to the "index" child with the given name.
- The first child is 0, the second 1, etc.
- */
- TiXmlHandle Child( const char* value, int index ) const;
- /** Return a handle to the "index" child.
- The first child is 0, the second 1, etc.
- */
- TiXmlHandle Child( int index ) const;
- /** Return a handle to the "index" child element with the given name.
- The first child element is 0, the second 1, etc. Note that only TiXmlElements
- are indexed: other types are not counted.
- */
- TiXmlHandle ChildElement( const char* value, int index ) const;
- /** Return a handle to the "index" child element.
- The first child element is 0, the second 1, etc. Note that only TiXmlElements
- are indexed: other types are not counted.
- */
- TiXmlHandle ChildElement( int index ) const;
-
- #ifdef TIXML_USE_STL
- TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); }
- TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); }
-
- TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); }
- TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); }
- #endif
-
- /** Return the handle as a TiXmlNode. This may return null.
- */
- TiXmlNode* ToNode() const { return node; }
- /** Return the handle as a TiXmlElement. This may return null.
- */
- TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
- /** Return the handle as a TiXmlText. This may return null.
- */
- TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
- /** Return the handle as a TiXmlUnknown. This may return null.
- */
- TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
-
- /** @deprecated use ToNode.
- Return the handle as a TiXmlNode. This may return null.
- */
- TiXmlNode* Node() const { return ToNode(); }
- /** @deprecated use ToElement.
- Return the handle as a TiXmlElement. This may return null.
- */
- TiXmlElement* Element() const { return ToElement(); }
- /** @deprecated use ToText()
- Return the handle as a TiXmlText. This may return null.
- */
- TiXmlText* Text() const { return ToText(); }
- /** @deprecated use ToUnknown()
- Return the handle as a TiXmlUnknown. This may return null.
- */
- TiXmlUnknown* Unknown() const { return ToUnknown(); }
-
-private:
- TiXmlNode* node;
-};
-
-
-/** Print to memory functionality. The TiXmlPrinter is useful when you need to:
-
- -# Print to memory (especially in non-STL mode)
- -# Control formatting (line endings, etc.)
-
- When constructed, the TiXmlPrinter is in its default "pretty printing" mode.
- Before calling Accept() you can call methods to control the printing
- of the XML document. After TiXmlNode::Accept() is called, the printed document can
- be accessed via the CStr(), Str(), and Size() methods.
-
- TiXmlPrinter uses the Visitor API.
- @verbatim
- TiXmlPrinter printer;
- printer.SetIndent( "\t" );
-
- doc.Accept( &printer );
- fprintf( stdout, "%s", printer.CStr() );
- @endverbatim
-*/
-class TiXmlPrinter : public TiXmlVisitor
-{
-public:
- TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ),
- buffer(), indent( " " ), lineBreak( "\n" ) {}
-
- virtual bool VisitEnter( const TiXmlDocument& doc );
- virtual bool VisitExit( const TiXmlDocument& doc );
-
- virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute );
- virtual bool VisitExit( const TiXmlElement& element );
-
- virtual bool Visit( const TiXmlDeclaration& declaration );
- virtual bool Visit( const TiXmlText& text );
- virtual bool Visit( const TiXmlComment& comment );
- virtual bool Visit( const TiXmlUnknown& unknown );
-
- /** Set the indent characters for printing. By default 4 spaces
- but tab (\t) is also useful, or null/empty string for no indentation.
- */
- void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; }
- /// Query the indention string.
- const char* Indent() { return indent.c_str(); }
- /** Set the line breaking string. By default set to newline (\n).
- Some operating systems prefer other characters, or can be
- set to the null/empty string for no indenation.
- */
- void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; }
- /// Query the current line breaking string.
- const char* LineBreak() { return lineBreak.c_str(); }
-
- /** Switch over to "stream printing" which is the most dense formatting without
- linebreaks. Common when the XML is needed for network transmission.
- */
- void SetStreamPrinting() { indent = "";
- lineBreak = "";
- }
- /// Return the result.
- const char* CStr() { return buffer.c_str(); }
- /// Return the length of the result string.
- size_t Size() { return buffer.size(); }
-
- #ifdef TIXML_USE_STL
- /// Return the result.
- const std::string& Str() { return buffer; }
- #endif
-
-private:
- void DoIndent() {
- for( int i=0; i<depth; ++i )
- buffer += indent;
- }
- void DoLineBreak() {
- buffer += lineBreak;
- }
-
- int depth;
- bool simpleTextPrint;
- TIXML_STRING buffer;
- TIXML_STRING indent;
- TIXML_STRING lineBreak;
-};
-
-
-#ifdef _MSC_VER
-#pragma warning( pop )
-#endif
-
-#endif
-
+++ /dev/null
-/*
-www.sourceforge.net/projects/tinyxml
-Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-#include "tinyxml.h"
-
-// The goal of the seperate error file is to make the first
-// step towards localization. tinyxml (currently) only supports
-// english error messages, but the could now be translated.
-//
-// It also cleans up the code a bit.
-//
-
-const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
-{
- "No error",
- "Error",
- "Failed to open file",
- "Memory allocation failed.",
- "Error parsing Element.",
- "Failed to read Element name",
- "Error reading Element value.",
- "Error reading Attributes.",
- "Error: empty tag.",
- "Error reading end tag.",
- "Error parsing Unknown.",
- "Error parsing Comment.",
- "Error parsing Declaration.",
- "Error document empty.",
- "Error null (0) or unexpected EOF found in input stream.",
- "Error parsing CDATA.",
- "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
-};
+++ /dev/null
-/*
-www.sourceforge.net/projects/tinyxml
-Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-#include <ctype.h>
-#include <stddef.h>
-
-#include "tinyxml.h"
-
-//#define DEBUG_PARSER
-#if defined( DEBUG_PARSER )
-# if defined( DEBUG ) && defined( _MSC_VER )
-# include <windows.h>
-# define TIXML_LOG OutputDebugString
-# else
-# define TIXML_LOG printf
-# endif
-#endif
-
-// Note tha "PutString" hardcodes the same list. This
-// is less flexible than it appears. Changing the entries
-// or order will break putstring.
-TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
-{
- { "&", 5, '&' },
- { "<", 4, '<' },
- { ">", 4, '>' },
- { """, 6, '\"' },
- { "'", 6, '\'' }
-};
-
-// Bunch of unicode info at:
-// http://www.unicode.org/faq/utf_bom.html
-// Including the basic of this table, which determines the #bytes in the
-// sequence from the lead byte. 1 placed for invalid sequences --
-// although the result will be junk, pass it through as much as possible.
-// Beware of the non-characters in UTF-8:
-// ef bb bf (Microsoft "lead bytes")
-// ef bf be
-// ef bf bf
-
-const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
-const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
-const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
-
-const int TiXmlBase::utf8ByteTable[256] =
-{
- // 0 1 2 3 4 5 6 7 8 9 a b c d e f
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
- 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte
- 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
-};
-
-
-void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
-{
- const unsigned long BYTE_MASK = 0xBF;
- const unsigned long BYTE_MARK = 0x80;
- const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
- if (input < 0x80)
- *length = 1;
- else if ( input < 0x800 )
- *length = 2;
- else if ( input < 0x10000 )
- *length = 3;
- else if ( input < 0x200000 )
- *length = 4;
- else
- { *length = 0; return; } // This code won't covert this correctly anyway.
-
- output += *length;
-
- // Scary scary fall throughs.
- switch (*length)
- {
- case 4:
- --output;
- *output = (char)((input | BYTE_MARK) & BYTE_MASK);
- input >>= 6;
- case 3:
- --output;
- *output = (char)((input | BYTE_MARK) & BYTE_MASK);
- input >>= 6;
- case 2:
- --output;
- *output = (char)((input | BYTE_MARK) & BYTE_MASK);
- input >>= 6;
- case 1:
- --output;
- *output = (char)(input | FIRST_BYTE_MARK[*length]);
- }
-}
-
-
-/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
-{
- // This will only work for low-ascii, everything else is assumed to be a valid
- // letter. I'm not sure this is the best approach, but it is quite tricky trying
- // to figure out alhabetical vs. not across encoding. So take a very
- // conservative approach.
-
-// if ( encoding == TIXML_ENCODING_UTF8 )
-// {
- if ( anyByte < 127 )
- return isalpha( anyByte );
- else
- return 1; // What else to do? The unicode set is huge...get the english ones right.
-// }
-// else
-// {
-// return isalpha( anyByte );
-// }
-}
-
-
-/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
-{
- // This will only work for low-ascii, everything else is assumed to be a valid
- // letter. I'm not sure this is the best approach, but it is quite tricky trying
- // to figure out alhabetical vs. not across encoding. So take a very
- // conservative approach.
-
-// if ( encoding == TIXML_ENCODING_UTF8 )
-// {
- if ( anyByte < 127 )
- return isalnum( anyByte );
- else
- return 1; // What else to do? The unicode set is huge...get the english ones right.
-// }
-// else
-// {
-// return isalnum( anyByte );
-// }
-}
-
-
-class TiXmlParsingData
-{
- friend class TiXmlDocument;
- public:
- void Stamp( const char* now, TiXmlEncoding encoding );
-
- const TiXmlCursor& Cursor() { return cursor; }
-
- private:
- // Only used by the document!
- TiXmlParsingData( const char* start, int _tabsize, int row, int col )
- {
- assert( start );
- stamp = start;
- tabsize = _tabsize;
- cursor.row = row;
- cursor.col = col;
- }
-
- TiXmlCursor cursor;
- const char* stamp;
- int tabsize;
-};
-
-
-void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
-{
- assert( now );
-
- // Do nothing if the tabsize is 0.
- if ( tabsize < 1 )
- {
- return;
- }
-
- // Get the current row, column.
- int row = cursor.row;
- int col = cursor.col;
- const char* p = stamp;
- assert( p );
-
- while ( p < now )
- {
- // Treat p as unsigned, so we have a happy compiler.
- const unsigned char* pU = (const unsigned char*)p;
-
- // Code contributed by Fletcher Dunn: (modified by lee)
- switch (*pU) {
- case 0:
- // We *should* never get here, but in case we do, don't
- // advance past the terminating null character, ever
- return;
-
- case '\r':
- // bump down to the next line
- ++row;
- col = 0;
- // Eat the character
- ++p;
-
- // Check for \r\n sequence, and treat this as a single character
- if (*p == '\n') {
- ++p;
- }
- break;
-
- case '\n':
- // bump down to the next line
- ++row;
- col = 0;
-
- // Eat the character
- ++p;
-
- // Check for \n\r sequence, and treat this as a single
- // character. (Yes, this bizarre thing does occur still
- // on some arcane platforms...)
- if (*p == '\r') {
- ++p;
- }
- break;
-
- case '\t':
- // Eat the character
- ++p;
-
- // Skip to next tab stop
- col = (col / tabsize + 1) * tabsize;
- break;
-
- case TIXML_UTF_LEAD_0:
- if ( encoding == TIXML_ENCODING_UTF8 )
- {
- if ( *(p+1) && *(p+2) )
- {
- // In these cases, don't advance the column. These are
- // 0-width spaces.
- if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
- p += 3;
- else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
- p += 3;
- else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
- p += 3;
- else
- { p +=3; ++col; } // A normal character.
- }
- }
- else
- {
- ++p;
- ++col;
- }
- break;
-
- default:
- if ( encoding == TIXML_ENCODING_UTF8 )
- {
- // Eat the 1 to 4 byte utf8 character.
- int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)];
- if ( step == 0 )
- step = 1; // Error case from bad encoding, but handle gracefully.
- p += step;
-
- // Just advance one column, of course.
- ++col;
- }
- else
- {
- ++p;
- ++col;
- }
- break;
- }
- }
- cursor.row = row;
- cursor.col = col;
- assert( cursor.row >= -1 );
- assert( cursor.col >= -1 );
- stamp = p;
- assert( stamp );
-}
-
-
-const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
-{
- if ( !p || !*p )
- {
- return 0;
- }
- if ( encoding == TIXML_ENCODING_UTF8 )
- {
- while ( *p )
- {
- const unsigned char* pU = (const unsigned char*)p;
-
- // Skip the stupid Microsoft UTF-8 Byte order marks
- if ( *(pU+0)==TIXML_UTF_LEAD_0
- && *(pU+1)==TIXML_UTF_LEAD_1
- && *(pU+2)==TIXML_UTF_LEAD_2 )
- {
- p += 3;
- continue;
- }
- else if(*(pU+0)==TIXML_UTF_LEAD_0
- && *(pU+1)==0xbfU
- && *(pU+2)==0xbeU )
- {
- p += 3;
- continue;
- }
- else if(*(pU+0)==TIXML_UTF_LEAD_0
- && *(pU+1)==0xbfU
- && *(pU+2)==0xbfU )
- {
- p += 3;
- continue;
- }
-
- if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space.
- ++p;
- else
- break;
- }
- }
- else
- {
- while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' )
- ++p;
- }
-
- return p;
-}
-
-#ifdef TIXML_USE_STL
-/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag )
-{
- for( ;; )
- {
- if ( !in->good() ) return false;
-
- int c = in->peek();
- // At this scope, we can't get to a document. So fail silently.
- if ( !IsWhiteSpace( c ) || c <= 0 )
- return true;
-
- *tag += (char) in->get();
- }
-}
-
-/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag )
-{
- //assert( character > 0 && character < 128 ); // else it won't work in utf-8
- while ( in->good() )
- {
- int c = in->peek();
- if ( c == character )
- return true;
- if ( c <= 0 ) // Silent failure: can't get document at this scope
- return false;
-
- in->get();
- *tag += (char) c;
- }
- return false;
-}
-#endif
-
-// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The
-// "assign" optimization removes over 10% of the execution time.
-//
-const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
-{
- // Oddly, not supported on some comilers,
- //name->clear();
- // So use this:
- *name = "";
- assert( p );
-
- // Names start with letters or underscores.
- // Of course, in unicode, tinyxml has no idea what a letter *is*. The
- // algorithm is generous.
- //
- // After that, they can be letters, underscores, numbers,
- // hyphens, or colons. (Colons are valid ony for namespaces,
- // but tinyxml can't tell namespaces from names.)
- if ( p && *p
- && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
- {
- const char* start = p;
- while( p && *p
- && ( IsAlphaNum( (unsigned char ) *p, encoding )
- || *p == '_'
- || *p == '-'
- || *p == '.'
- || *p == ':' ) )
- {
- //(*name) += *p; // expensive
- ++p;
- }
- if ( p-start > 0 ) {
- name->assign( start, p-start );
- }
- return p;
- }
- return 0;
-}
-
-const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
-{
- // Presume an entity, and pull it out.
- TIXML_STRING ent;
- int i;
- *length = 0;
-
- if ( *(p+1) && *(p+1) == '#' && *(p+2) )
- {
- unsigned long ucs = 0;
- ptrdiff_t delta = 0;
- unsigned mult = 1;
-
- if ( *(p+2) == 'x' )
- {
- // Hexadecimal.
- if ( !*(p+3) ) return 0;
-
- const char* q = p+3;
- q = strchr( q, ';' );
-
- if ( !q || !*q ) return 0;
-
- delta = q-p;
- --q;
-
- while ( *q != 'x' )
- {
- if ( *q >= '0' && *q <= '9' )
- ucs += mult * (*q - '0');
- else if ( *q >= 'a' && *q <= 'f' )
- ucs += mult * (*q - 'a' + 10);
- else if ( *q >= 'A' && *q <= 'F' )
- ucs += mult * (*q - 'A' + 10 );
- else
- return 0;
- mult *= 16;
- --q;
- }
- }
- else
- {
- // Decimal.
- if ( !*(p+2) ) return 0;
-
- const char* q = p+2;
- q = strchr( q, ';' );
-
- if ( !q || !*q ) return 0;
-
- delta = q-p;
- --q;
-
- while ( *q != '#' )
- {
- if ( *q >= '0' && *q <= '9' )
- ucs += mult * (*q - '0');
- else
- return 0;
- mult *= 10;
- --q;
- }
- }
- if ( encoding == TIXML_ENCODING_UTF8 )
- {
- // convert the UCS to UTF-8
- ConvertUTF32ToUTF8( ucs, value, length );
- }
- else
- {
- *value = (char)ucs;
- *length = 1;
- }
- return p + delta + 1;
- }
-
- // Now try to match it.
- for( i=0; i<NUM_ENTITY; ++i )
- {
- if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
- {
- assert( strlen( entity[i].str ) == entity[i].strLength );
- *value = entity[i].chr;
- *length = 1;
- return ( p + entity[i].strLength );
- }
- }
-
- // So it wasn't an entity, its unrecognized, or something like that.
- *value = *p; // Don't put back the last one, since we return it!
- //*length = 1; // Leave unrecognized entities - this doesn't really work.
- // Just writes strange XML.
- return p+1;
-}
-
-
-bool TiXmlBase::StringEqual( const char* p,
- const char* tag,
- bool ignoreCase,
- TiXmlEncoding encoding )
-{
- assert( p );
- assert( tag );
- if ( !p || !*p )
- {
- assert( 0 );
- return false;
- }
-
- const char* q = p;
-
- if ( ignoreCase )
- {
- while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
- {
- ++q;
- ++tag;
- }
-
- if ( *tag == 0 )
- return true;
- }
- else
- {
- while ( *q && *tag && *q == *tag )
- {
- ++q;
- ++tag;
- }
-
- if ( *tag == 0 ) // Have we found the end of the tag, and everything equal?
- return true;
- }
- return false;
-}
-
-const char* TiXmlBase::ReadText( const char* p,
- TIXML_STRING * text,
- bool trimWhiteSpace,
- const char* endTag,
- bool caseInsensitive,
- TiXmlEncoding encoding )
-{
- *text = "";
- if ( !trimWhiteSpace // certain tags always keep whitespace
- || !condenseWhiteSpace ) // if true, whitespace is always kept
- {
- // Keep all the white space.
- while ( p && *p
- && !StringEqual( p, endTag, caseInsensitive, encoding )
- )
- {
- int len;
- char cArr[4] = { 0, 0, 0, 0 };
- p = GetChar( p, cArr, &len, encoding );
- text->append( cArr, len );
- }
- }
- else
- {
- bool whitespace = false;
-
- // Remove leading white space:
- p = SkipWhiteSpace( p, encoding );
- while ( p && *p
- && !StringEqual( p, endTag, caseInsensitive, encoding ) )
- {
- if ( *p == '\r' || *p == '\n' )
- {
- whitespace = true;
- ++p;
- }
- else if ( IsWhiteSpace( *p ) )
- {
- whitespace = true;
- ++p;
- }
- else
- {
- // If we've found whitespace, add it before the
- // new character. Any whitespace just becomes a space.
- if ( whitespace )
- {
- (*text) += ' ';
- whitespace = false;
- }
- int len;
- char cArr[4] = { 0, 0, 0, 0 };
- p = GetChar( p, cArr, &len, encoding );
- if ( len == 1 )
- (*text) += cArr[0]; // more efficient
- else
- text->append( cArr, len );
- }
- }
- }
- if ( p )
- p += strlen( endTag );
- return p;
-}
-
-#ifdef TIXML_USE_STL
-
-void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag )
-{
- // The basic issue with a document is that we don't know what we're
- // streaming. Read something presumed to be a tag (and hope), then
- // identify it, and call the appropriate stream method on the tag.
- //
- // This "pre-streaming" will never read the closing ">" so the
- // sub-tag can orient itself.
-
- if ( !StreamTo( in, '<', tag ) )
- {
- SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
- return;
- }
-
- while ( in->good() )
- {
- int tagIndex = (int) tag->length();
- while ( in->good() && in->peek() != '>' )
- {
- int c = in->get();
- if ( c <= 0 )
- {
- SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
- break;
- }
- (*tag) += (char) c;
- }
-
- if ( in->good() )
- {
- // We now have something we presume to be a node of
- // some sort. Identify it, and call the node to
- // continue streaming.
- TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
-
- if ( node )
- {
- node->StreamIn( in, tag );
- bool isElement = node->ToElement() != 0;
- delete node;
- node = 0;
-
- // If this is the root element, we're done. Parsing will be
- // done by the >> operator.
- if ( isElement )
- {
- return;
- }
- }
- else
- {
- SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
- return;
- }
- }
- }
- // We should have returned sooner.
- SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
-}
-
-#endif
-
-const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
-{
- ClearError();
-
- // Parse away, at the document level. Since a document
- // contains nothing but other tags, most of what happens
- // here is skipping white space.
- if ( !p || !*p )
- {
- SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
- return 0;
- }
-
- // Note that, for a document, this needs to come
- // before the while space skip, so that parsing
- // starts from the pointer we are given.
- location.Clear();
- if ( prevData )
- {
- location.row = prevData->cursor.row;
- location.col = prevData->cursor.col;
- }
- else
- {
- location.row = 0;
- location.col = 0;
- }
- TiXmlParsingData data( p, TabSize(), location.row, location.col );
- location = data.Cursor();
-
- if ( encoding == TIXML_ENCODING_UNKNOWN )
- {
- // Check for the Microsoft UTF-8 lead bytes.
- const unsigned char* pU = (const unsigned char*)p;
- if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
- && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
- && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
- {
- encoding = TIXML_ENCODING_UTF8;
- useMicrosoftBOM = true;
- }
- }
-
- p = SkipWhiteSpace( p, encoding );
- if ( !p )
- {
- SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
- return 0;
- }
-
- while ( p && *p )
- {
- TiXmlNode* node = Identify( p, encoding );
- if ( node )
- {
- p = node->Parse( p, &data, encoding );
- LinkEndChild( node );
- }
- else
- {
- break;
- }
-
- // Did we get encoding info?
- if ( encoding == TIXML_ENCODING_UNKNOWN
- && node->ToDeclaration() )
- {
- TiXmlDeclaration* dec = node->ToDeclaration();
- const char* enc = dec->Encoding();
- assert( enc );
-
- if ( *enc == 0 )
- encoding = TIXML_ENCODING_UTF8;
- else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
- encoding = TIXML_ENCODING_UTF8;
- else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
- encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
- else
- encoding = TIXML_ENCODING_LEGACY;
- }
-
- p = SkipWhiteSpace( p, encoding );
- }
-
- // Was this empty?
- if ( !firstChild ) {
- SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
- return 0;
- }
-
- // All is well.
- return p;
-}
-
-void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
-{
- // The first error in a chain is more accurate - don't set again!
- if ( error )
- return;
-
- assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
- error = true;
- errorId = err;
- errorDesc = errorString[ errorId ];
-
- errorLocation.Clear();
- if ( pError && data )
- {
- data->Stamp( pError, encoding );
- errorLocation = data->Cursor();
- }
-}
-
-
-TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
-{
- TiXmlNode* returnNode = 0;
-
- p = SkipWhiteSpace( p, encoding );
- if( !p || !*p || *p != '<' )
- {
- return 0;
- }
-
- TiXmlDocument* doc = GetDocument();
- p = SkipWhiteSpace( p, encoding );
-
- if ( !p || !*p )
- {
- return 0;
- }
-
- // What is this thing?
- // - Elements start with a letter or underscore, but xml is reserved.
- // - Comments: <!--
- // - Decleration: <?xml
- // - Everthing else is unknown to tinyxml.
- //
-
- const char* xmlHeader = { "<?xml" };
- const char* commentHeader = { "<!--" };
- const char* dtdHeader = { "<!" };
- const char* cdataHeader = { "<![CDATA[" };
-
- if ( StringEqual( p, xmlHeader, true, encoding ) )
- {
- #ifdef DEBUG_PARSER
- TIXML_LOG( "XML parsing Declaration\n" );
- #endif
- returnNode = new TiXmlDeclaration();
- }
- else if ( StringEqual( p, commentHeader, false, encoding ) )
- {
- #ifdef DEBUG_PARSER
- TIXML_LOG( "XML parsing Comment\n" );
- #endif
- returnNode = new TiXmlComment();
- }
- else if ( StringEqual( p, cdataHeader, false, encoding ) )
- {
- #ifdef DEBUG_PARSER
- TIXML_LOG( "XML parsing CDATA\n" );
- #endif
- TiXmlText* text = new TiXmlText( "" );
- text->SetCDATA( true );
- returnNode = text;
- }
- else if ( StringEqual( p, dtdHeader, false, encoding ) )
- {
- #ifdef DEBUG_PARSER
- TIXML_LOG( "XML parsing Unknown(1)\n" );
- #endif
- returnNode = new TiXmlUnknown();
- }
- else if ( IsAlpha( *(p+1), encoding )
- || *(p+1) == '_' )
- {
- #ifdef DEBUG_PARSER
- TIXML_LOG( "XML parsing Element\n" );
- #endif
- returnNode = new TiXmlElement( "" );
- }
- else
- {
- #ifdef DEBUG_PARSER
- TIXML_LOG( "XML parsing Unknown(2)\n" );
- #endif
- returnNode = new TiXmlUnknown();
- }
-
- if ( returnNode )
- {
- // Set the parent, so it can report errors
- returnNode->parent = this;
- }
- else
- {
- if ( doc )
- doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
- }
- return returnNode;
-}
-
-#ifdef TIXML_USE_STL
-
-void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag)
-{
- // We're called with some amount of pre-parsing. That is, some of "this"
- // element is in "tag". Go ahead and stream to the closing ">"
- while( in->good() )
- {
- int c = in->get();
- if ( c <= 0 )
- {
- TiXmlDocument* document = GetDocument();
- if ( document )
- document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
- return;
- }
- (*tag) += (char) c ;
-
- if ( c == '>' )
- break;
- }
-
- if ( tag->length() < 3 ) return;
-
- // Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
- // If not, identify and stream.
-
- if ( tag->at( tag->length() - 1 ) == '>'
- && tag->at( tag->length() - 2 ) == '/' )
- {
- // All good!
- return;
- }
- else if ( tag->at( tag->length() - 1 ) == '>' )
- {
- // There is more. Could be:
- // text
- // cdata text (which looks like another node)
- // closing tag
- // another node.
- for ( ;; )
- {
- StreamWhiteSpace( in, tag );
-
- // Do we have text?
- if ( in->good() && in->peek() != '<' )
- {
- // Yep, text.
- TiXmlText text( "" );
- text.StreamIn( in, tag );
-
- // What follows text is a closing tag or another node.
- // Go around again and figure it out.
- continue;
- }
-
- // We now have either a closing tag...or another node.
- // We should be at a "<", regardless.
- if ( !in->good() ) return;
- assert( in->peek() == '<' );
- int tagIndex = (int) tag->length();
-
- bool closingTag = false;
- bool firstCharFound = false;
-
- for( ;; )
- {
- if ( !in->good() )
- return;
-
- int c = in->peek();
- if ( c <= 0 )
- {
- TiXmlDocument* document = GetDocument();
- if ( document )
- document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
- return;
- }
-
- if ( c == '>' )
- break;
-
- *tag += (char) c;
- in->get();
-
- // Early out if we find the CDATA id.
- if ( c == '[' && tag->size() >= 9 )
- {
- size_t len = tag->size();
- const char* start = tag->c_str() + len - 9;
- if ( strcmp( start, "<![CDATA[" ) == 0 ) {
- assert( !closingTag );
- break;
- }
- }
-
- if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
- {
- firstCharFound = true;
- if ( c == '/' )
- closingTag = true;
- }
- }
- // If it was a closing tag, then read in the closing '>' to clean up the input stream.
- // If it was not, the streaming will be done by the tag.
- if ( closingTag )
- {
- if ( !in->good() )
- return;
-
- int c = in->get();
- if ( c <= 0 )
- {
- TiXmlDocument* document = GetDocument();
- if ( document )
- document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
- return;
- }
- assert( c == '>' );
- *tag += (char) c;
-
- // We are done, once we've found our closing tag.
- return;
- }
- else
- {
- // If not a closing tag, id it, and stream.
- const char* tagloc = tag->c_str() + tagIndex;
- TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
- if ( !node )
- return;
- node->StreamIn( in, tag );
- delete node;
- node = 0;
-
- // No return: go around from the beginning: text, closing tag, or node.
- }
- }
- }
-}
-#endif
-
-const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
-{
- p = SkipWhiteSpace( p, encoding );
- TiXmlDocument* document = GetDocument();
-
- if ( !p || !*p )
- {
- if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
- return 0;
- }
-
- if ( data )
- {
- data->Stamp( p, encoding );
- location = data->Cursor();
- }
-
- if ( *p != '<' )
- {
- if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
- return 0;
- }
-
- p = SkipWhiteSpace( p+1, encoding );
-
- // Read the name.
- const char* pErr = p;
-
- p = ReadName( p, &value, encoding );
- if ( !p || !*p )
- {
- if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
- return 0;
- }
-
- TIXML_STRING endTag ("</");
- endTag += value;
- endTag += ">";
-
- // Check for and read attributes. Also look for an empty
- // tag or an end tag.
- while ( p && *p )
- {
- pErr = p;
- p = SkipWhiteSpace( p, encoding );
- if ( !p || !*p )
- {
- if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
- return 0;
- }
- if ( *p == '/' )
- {
- ++p;
- // Empty tag.
- if ( *p != '>' )
- {
- if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
- return 0;
- }
- return (p+1);
- }
- else if ( *p == '>' )
- {
- // Done with attributes (if there were any.)
- // Read the value -- which can include other
- // elements -- read the end tag, and return.
- ++p;
- p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens.
- if ( !p || !*p ) {
- // We were looking for the end tag, but found nothing.
- // Fix for [ 1663758 ] Failure to report error on bad XML
- if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
- return 0;
- }
-
- // We should find the end tag now
- if ( StringEqual( p, endTag.c_str(), false, encoding ) )
- {
- p += endTag.length();
- return p;
- }
- else
- {
- if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
- return 0;
- }
- }
- else
- {
- // Try to read an attribute:
- TiXmlAttribute* attrib = new TiXmlAttribute();
- if ( !attrib )
- {
- if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
- return 0;
- }
-
- attrib->SetDocument( document );
- pErr = p;
- p = attrib->Parse( p, data, encoding );
-
- if ( !p || !*p )
- {
- if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
- delete attrib;
- return 0;
- }
-
- // Handle the strange case of double attributes:
- #ifdef TIXML_USE_STL
- TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
- #else
- TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
- #endif
- if ( node )
- {
- node->SetValue( attrib->Value() );
- delete attrib;
- return 0;
- }
-
- attributeSet.Add( attrib );
- }
- }
- return p;
-}
-
-
-const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
-{
- TiXmlDocument* document = GetDocument();
-
- // Read in text and elements in any order.
- const char* pWithWhiteSpace = p;
- p = SkipWhiteSpace( p, encoding );
-
- while ( p && *p )
- {
- if ( *p != '<' )
- {
- // Take what we have, make a text element.
- TiXmlText* textNode = new TiXmlText( "" );
-
- if ( !textNode )
- {
- if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
- return 0;
- }
-
- if ( TiXmlBase::IsWhiteSpaceCondensed() )
- {
- p = textNode->Parse( p, data, encoding );
- }
- else
- {
- // Special case: we want to keep the white space
- // so that leading spaces aren't removed.
- p = textNode->Parse( pWithWhiteSpace, data, encoding );
- }
-
- if ( !textNode->Blank() )
- LinkEndChild( textNode );
- else
- delete textNode;
- }
- else
- {
- // We hit a '<'
- // Have we hit a new element or an end tag? This could also be
- // a TiXmlText in the "CDATA" style.
- if ( StringEqual( p, "</", false, encoding ) )
- {
- return p;
- }
- else
- {
- TiXmlNode* node = Identify( p, encoding );
- if ( node )
- {
- p = node->Parse( p, data, encoding );
- LinkEndChild( node );
- }
- else
- {
- return 0;
- }
- }
- }
- pWithWhiteSpace = p;
- p = SkipWhiteSpace( p, encoding );
- }
-
- if ( !p )
- {
- if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
- }
- return p;
-}
-
-
-#ifdef TIXML_USE_STL
-void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag )
-{
- while ( in->good() )
- {
- int c = in->get();
- if ( c <= 0 )
- {
- TiXmlDocument* document = GetDocument();
- if ( document )
- document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
- return;
- }
- (*tag) += (char) c;
-
- if ( c == '>' )
- {
- // All is well.
- return;
- }
- }
-}
-#endif
-
-
-const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
-{
- TiXmlDocument* document = GetDocument();
- p = SkipWhiteSpace( p, encoding );
-
- if ( data )
- {
- data->Stamp( p, encoding );
- location = data->Cursor();
- }
- if ( !p || !*p || *p != '<' )
- {
- if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
- return 0;
- }
- ++p;
- value = "";
-
- while ( p && *p && *p != '>' )
- {
- value += *p;
- ++p;
- }
-
- if ( !p )
- {
- if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
- }
- if ( *p == '>' )
- return p+1;
- return p;
-}
-
-#ifdef TIXML_USE_STL
-void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag )
-{
- while ( in->good() )
- {
- int c = in->get();
- if ( c <= 0 )
- {
- TiXmlDocument* document = GetDocument();
- if ( document )
- document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
- return;
- }
-
- (*tag) += (char) c;
-
- if ( c == '>'
- && tag->at( tag->length() - 2 ) == '-'
- && tag->at( tag->length() - 3 ) == '-' )
- {
- // All is well.
- return;
- }
- }
-}
-#endif
-
-
-const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
-{
- TiXmlDocument* document = GetDocument();
- value = "";
-
- p = SkipWhiteSpace( p, encoding );
-
- if ( data )
- {
- data->Stamp( p, encoding );
- location = data->Cursor();
- }
- const char* startTag = "<!--";
- const char* endTag = "-->";
-
- if ( !StringEqual( p, startTag, false, encoding ) )
- {
- document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
- return 0;
- }
- p += strlen( startTag );
-
- // [ 1475201 ] TinyXML parses entities in comments
- // Oops - ReadText doesn't work, because we don't want to parse the entities.
- // p = ReadText( p, &value, false, endTag, false, encoding );
- //
- // from the XML spec:
- /*
- [Definition: Comments may appear anywhere in a document outside other markup; in addition,
- they may appear within the document type declaration at places allowed by the grammar.
- They are not part of the document's character data; an XML processor MAY, but need not,
- make it possible for an application to retrieve the text of comments. For compatibility,
- the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity
- references MUST NOT be recognized within comments.
-
- An example of a comment:
-
- <!-- declarations for <head> & <body> -->
- */
-
- value = "";
- // Keep all the white space.
- while ( p && *p && !StringEqual( p, endTag, false, encoding ) )
- {
- value.append( p, 1 );
- ++p;
- }
- if ( p )
- p += strlen( endTag );
-
- return p;
-}
-
-
-const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
-{
- p = SkipWhiteSpace( p, encoding );
- if ( !p || !*p ) return 0;
-
-// int tabsize = 4;
-// if ( document )
-// tabsize = document->TabSize();
-
- if ( data )
- {
- data->Stamp( p, encoding );
- location = data->Cursor();
- }
- // Read the name, the '=' and the value.
- const char* pErr = p;
- p = ReadName( p, &name, encoding );
- if ( !p || !*p )
- {
- if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
- return 0;
- }
- p = SkipWhiteSpace( p, encoding );
- if ( !p || !*p || *p != '=' )
- {
- if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
- return 0;
- }
-
- ++p; // skip '='
- p = SkipWhiteSpace( p, encoding );
- if ( !p || !*p )
- {
- if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
- return 0;
- }
-
- const char* end;
- const char SINGLE_QUOTE = '\'';
- const char DOUBLE_QUOTE = '\"';
-
- if ( *p == SINGLE_QUOTE )
- {
- ++p;
- end = "\'"; // single quote in string
- p = ReadText( p, &value, false, end, false, encoding );
- }
- else if ( *p == DOUBLE_QUOTE )
- {
- ++p;
- end = "\""; // double quote in string
- p = ReadText( p, &value, false, end, false, encoding );
- }
- else
- {
- // All attribute values should be in single or double quotes.
- // But this is such a common error that the parser will try
- // its best, even without them.
- value = "";
- while ( p && *p // existence
- && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace
- && *p != '/' && *p != '>' ) // tag end
- {
- if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
- // [ 1451649 ] Attribute values with trailing quotes not handled correctly
- // We did not have an opening quote but seem to have a
- // closing one. Give up and throw an error.
- if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
- return 0;
- }
- value += *p;
- ++p;
- }
- }
- return p;
-}
-
-#ifdef TIXML_USE_STL
-void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag )
-{
- while ( in->good() )
- {
- int c = in->peek();
- if ( !cdata && (c == '<' ) )
- {
- return;
- }
- if ( c <= 0 )
- {
- TiXmlDocument* document = GetDocument();
- if ( document )
- document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
- return;
- }
-
- (*tag) += (char) c;
- in->get(); // "commits" the peek made above
-
- if ( cdata && c == '>' && tag->size() >= 3 ) {
- size_t len = tag->size();
- if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) {
- // terminator of cdata.
- return;
- }
- }
- }
-}
-#endif
-
-const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
-{
- value = "";
- TiXmlDocument* document = GetDocument();
-
- if ( data )
- {
- data->Stamp( p, encoding );
- location = data->Cursor();
- }
-
- const char* const startTag = "<![CDATA[";
- const char* const endTag = "]]>";
-
- if ( cdata || StringEqual( p, startTag, false, encoding ) )
- {
- cdata = true;
-
- if ( !StringEqual( p, startTag, false, encoding ) )
- {
- document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
- return 0;
- }
- p += strlen( startTag );
-
- // Keep all the white space, ignore the encoding, etc.
- while ( p && *p
- && !StringEqual( p, endTag, false, encoding )
- )
- {
- value += *p;
- ++p;
- }
-
- TIXML_STRING dummy;
- p = ReadText( p, &dummy, false, endTag, false, encoding );
- return p;
- }
- else
- {
- bool ignoreWhite = true;
-
- const char* end = "<";
- p = ReadText( p, &value, ignoreWhite, end, false, encoding );
- if ( p )
- return p-1; // don't truncate the '<'
- return 0;
- }
-}
-
-#ifdef TIXML_USE_STL
-void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag )
-{
- while ( in->good() )
- {
- int c = in->get();
- if ( c <= 0 )
- {
- TiXmlDocument* document = GetDocument();
- if ( document )
- document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
- return;
- }
- (*tag) += (char) c;
-
- if ( c == '>' )
- {
- // All is well.
- return;
- }
- }
-}
-#endif
-
-const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
-{
- p = SkipWhiteSpace( p, _encoding );
- // Find the beginning, find the end, and look for
- // the stuff in-between.
- TiXmlDocument* document = GetDocument();
- if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
- {
- if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
- return 0;
- }
- if ( data )
- {
- data->Stamp( p, _encoding );
- location = data->Cursor();
- }
- p += 5;
-
- version = "";
- encoding = "";
- standalone = "";
-
- while ( p && *p )
- {
- if ( *p == '>' )
- {
- ++p;
- return p;
- }
-
- p = SkipWhiteSpace( p, _encoding );
- if ( StringEqual( p, "version", true, _encoding ) )
- {
- TiXmlAttribute attrib;
- p = attrib.Parse( p, data, _encoding );
- version = attrib.Value();
- }
- else if ( StringEqual( p, "encoding", true, _encoding ) )
- {
- TiXmlAttribute attrib;
- p = attrib.Parse( p, data, _encoding );
- encoding = attrib.Value();
- }
- else if ( StringEqual( p, "standalone", true, _encoding ) )
- {
- TiXmlAttribute attrib;
- p = attrib.Parse( p, data, _encoding );
- standalone = attrib.Value();
- }
- else
- {
- // Read over whatever it is.
- while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
- ++p;
- }
- }
- return 0;
-}
-
-bool TiXmlText::Blank() const
-{
- for ( unsigned i=0; i<value.length(); i++ )
- if ( !IsWhiteSpace( value[i] ) )
- return false;
- return true;
-}
-
COMPILING\r
---------\r
-Compiling FMS requires CMake, pthreads and iconv if you want to do charset\r
+Compiling FMS requires CMake, Poco and iconv if you want to do charset\r
conversion. Other required libraries are bundled with FMS.\r
\r
To compile, run these commands from the source directory:\r
RUNNING\r
-------\r
You may run FMS in console mode by running the binary directly. If you are\r
-running *nix and would like to run as a daemon, use the -d argument. On\r
-Windows, -i will install FMS as a service, and -u will uninstall the service.\r
+running *nix and would like to run as a daemon, use the --daemon argument. On\r
+Windows, /registerService will install FMS as a service, and /unregisterService\r
+will uninstall the service. Use the /displayName=name argument when installing\r
+the service to set the service name to whatever you want. You will need to\r
+manually start the service unless you change the startup type in the service\r
+properties.\r
\r
EXITING\r
-------\r
#include "../include/bitmapvalidator.h"\r
#include "../include/freenet/captcha/easybmp/EasyBMP.h"\r
\r
+#include <Poco/TemporaryFile.h>\r
+\r
#include <sstream>\r
+#include <cstdlib>\r
\r
const bool BitmapValidator::Validate(const std::vector<unsigned char> &data)\r
{\r
bool validated=false;\r
- std::ostringstream tempname;\r
- \r
- tempname << "validatebmp-" << rand() << ".tmp";\r
- FILE *outfile=fopen(tempname.str().c_str(),"w+b");\r
+ std::string tempname=Poco::TemporaryFile::tempName();\r
+\r
+ FILE *outfile=fopen(tempname.c_str(),"w+b");\r
if(outfile)\r
{\r
fwrite(&data[0],1,data.size(),outfile);\r
fclose(outfile);\r
\r
BMP temp;\r
- if(temp.ReadFromFile(tempname.str().c_str()))\r
+ if(temp.ReadFromFile(tempname.c_str()))\r
{\r
validated=true; \r
}\r
\r
- unlink(tempname.str().c_str());\r
+ unlink(tempname.c_str());\r
\r
}\r
\r
#include "../include/board.h"\r
#include "../include/stringfunctions.h"\r
\r
+#include <Poco/DateTimeParser.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
m_boardid=-1;\r
m_boardname="";\r
m_boarddescription="";\r
- m_datecreated.Set(1970,1,1);\r
+ m_datecreated.assign(1970,1,1);\r
m_lowmessageid=0;\r
m_highmessageid=0;\r
m_messagecount=0;\r
m_boardid=-1;\r
m_boardname="";\r
m_boarddescription="";\r
- m_datecreated.Set(1970,1,1);\r
+ m_datecreated.assign(1970,1,1);\r
m_lowmessageid=0;\r
m_highmessageid=0;\r
m_messagecount=0;\r
m_boardid=-1;\r
m_boardname="";\r
m_boarddescription="";\r
- m_datecreated.Set(1970,1,1);\r
+ m_datecreated.assign(1970,1,1);\r
m_lowmessageid=0;\r
m_highmessageid=0;\r
m_messagecount=0;\r
void Board::SetDateFromString(const std::string &datestring)\r
{\r
// break out date created - date should be in format yyyy-mm-dd HH:MM:SS, so we split on "-", " " (space), and ":"\r
- int tempint=0;\r
- std::vector<std::string> dateparts;\r
- StringFunctions::SplitMultiple(datestring,"- :",dateparts);\r
- if(dateparts.size()>0)\r
- {\r
- StringFunctions::Convert(dateparts[0],tempint);\r
- m_datecreated.SetYear(tempint);\r
- }\r
- if(dateparts.size()>1)\r
- {\r
- StringFunctions::Convert(dateparts[1],tempint);\r
- m_datecreated.SetMonth(tempint);\r
- }\r
- if(dateparts.size()>2)\r
- {\r
- StringFunctions::Convert(dateparts[2],tempint);\r
- m_datecreated.SetDay(tempint);\r
- }\r
- if(dateparts.size()>3)\r
- {\r
- StringFunctions::Convert(dateparts[3],tempint);\r
- m_datecreated.SetHour(tempint);\r
- }\r
- if(dateparts.size()>4)\r
- {\r
- StringFunctions::Convert(dateparts[4],tempint);\r
- m_datecreated.SetMinute(tempint);\r
- }\r
- if(dateparts.size()>5)\r
+ int tzdiff=0;\r
+ if(Poco::DateTimeParser::tryParse(datestring,m_datecreated,tzdiff)==false)\r
{\r
- StringFunctions::Convert(dateparts[5],tempint);\r
- m_datecreated.SetSecond(tempint);\r
+ m_log->error("Board::SetDateFromString could not parse date "+datestring);\r
}\r
}\r
{\r
std::vector<char> invec(input.begin(),input.end());\r
std::vector<char> outvec(invec.size()*4,0);\r
-#if defined(_WIN32) || defined(__APPLE__) || defined(__DARWIN__)\r
+#if defined(_WIN32) //|| defined(__APPLE__) || defined(__DARWIN__)\r
const char *inptr=&invec[0];\r
#else\r
char *inptr=&invec[0];\r
+++ /dev/null
-#include "../include/commandthread.h"\r
-#include "../include/stringfunctions.h"\r
-\r
-#include <iostream>\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-void CommandThread::HandleHelpCommand()\r
-{\r
- std::cout << "Available Commands:" << std::endl;\r
- std::cout << "QUIT End program" << std::endl;\r
-}\r
-\r
-void CommandThread::HandleInput(const std::string &input)\r
-{\r
- std::string command=input;\r
- std::string argument="";\r
- if(input.find(" ")!=std::string::npos)\r
- {\r
- command=input.substr(0,input.find(" "));\r
- argument=input.substr(command.size()+1);\r
- }\r
- StringFunctions::UpperCase(command,command);\r
- \r
- if(command=="HELP")\r
- {\r
- HandleHelpCommand();\r
- }\r
- else if(command=="QUIT")\r
- {\r
- HandleQuit();\r
- }\r
- else\r
- {\r
- std::cout << "Unknown command. Type HELP for a list of available commands." << std::endl;\r
- }\r
- \r
-}\r
-\r
-void CommandThread::HandleQuit()\r
-{\r
- m_running=false; \r
-}\r
-\r
-void CommandThread::Run()\r
-{\r
- std::string input;\r
- m_running=true;\r
-\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"CommandThread::run thread started.");\r
- \r
- do\r
- {\r
-\r
- std::cout << ">";\r
- std::cin >> input;\r
- \r
- HandleInput(input);\r
- \r
- }while(m_running && !IsCancelled());\r
- \r
-}\r
+++ /dev/null
-#include "../include/datetime.h"\r
-\r
-#include <vector>\r
-#include "../include/stringfunctions.h"\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-DateTime::DateTime()\r
-{\r
- Set();\r
-}\r
-\r
-DateTime::DateTime(const time_t &timet)\r
-{\r
- SetT(timet);\r
-}\r
-\r
-DateTime::DateTime(const struct tm *stm)\r
-{\r
- Set(stm);\r
-}\r
-\r
-void DateTime::Add(const int seconds, const int minutes, const int hours, const int days, const int months, const int years)\r
-{\r
- m_tm.tm_sec+=seconds;\r
- m_tm.tm_min+=minutes;\r
- m_tm.tm_hour+=hours;\r
- m_tm.tm_mday+=days;\r
- m_tm.tm_mon+=months;\r
- m_tm.tm_year+=years;\r
- \r
- Normalize();\r
-}\r
-\r
-std::string DateTime::Format(const std::string &formatstring) const\r
-{\r
- std::vector<char> str(256,0);\r
-\r
- size_t len=strftime(&str[0],str.size()-1,formatstring.c_str(),&m_tm);\r
-\r
- return std::string(str.begin(),str.begin()+len);\r
-}\r
-\r
-void DateTime::Normalize()\r
-{\r
- // check for tm_isdst in local time and take appropriate action when normalizing\r
- // thanks to http://www.erack.de/download/timetest.c for example\r
- int isdst;\r
- struct tm temptm;\r
- time_t temptimet;\r
- temptimet=time(NULL);\r
- temptm=*localtime(&temptimet);\r
- isdst=temptm.tm_isdst;\r
-\r
- temptm.tm_year=m_tm.tm_year;\r
- temptm.tm_mon=m_tm.tm_mon;\r
- temptm.tm_mday=m_tm.tm_mday;\r
- temptm.tm_hour=m_tm.tm_hour;\r
- temptm.tm_min=m_tm.tm_min;\r
- temptm.tm_sec=m_tm.tm_sec;\r
- temptm.tm_isdst=isdst;\r
- temptimet=mktime(&temptm);\r
-\r
- if(temptm.tm_isdst!=isdst)\r
- {\r
- // keep tm_isdst to whatever mktime returned and try again\r
- temptm.tm_year=m_tm.tm_year;\r
- temptm.tm_mon=m_tm.tm_mon;\r
- temptm.tm_mday=m_tm.tm_mday;\r
- temptm.tm_hour=m_tm.tm_hour;\r
- temptm.tm_min=m_tm.tm_min;\r
- temptm.tm_sec=m_tm.tm_sec;\r
- temptimet=mktime(&temptm);\r
- }\r
- else if(isdst && temptimet==-1)\r
- {\r
- // isdst set, but TZ has no offset (e.g. GMT), try with isdst=0\r
- temptm.tm_year=m_tm.tm_year;\r
- temptm.tm_mon=m_tm.tm_mon;\r
- temptm.tm_mday=m_tm.tm_mday;\r
- temptm.tm_hour=m_tm.tm_hour;\r
- temptm.tm_min=m_tm.tm_min;\r
- temptm.tm_sec=m_tm.tm_sec;\r
- temptm.tm_isdst=0;\r
- temptimet=mktime(&temptm);\r
- }\r
-\r
- m_tm=temptm;\r
- m_timet=temptimet;\r
-\r
- // date is erroneous - set to default date\r
- if(m_timet==-1 && (m_tm.tm_mon<0 || m_tm.tm_mon>11 || m_tm.tm_mday <1 || m_tm.tm_mday>31 || m_tm.tm_hour<0 || m_tm.tm_hour>23 || m_tm.tm_min<0 || m_tm.tm_min>59 || m_tm.tm_sec<0 || m_tm.tm_sec>59))\r
- {\r
- Set();\r
- }\r
-\r
-}\r
-\r
-DateTime DateTime::operator+(const double &rhs)\r
-{\r
- DateTime temp=*this;\r
-\r
- double val=rhs;\r
- int days=(int)val;\r
- val-=days;\r
- val*=24.0;\r
- int hours=(int)val;\r
- val-=hours;\r
- val*=60.0;\r
- int minutes=(int)val;\r
- val-=minutes;\r
- val*=60.0;\r
- int seconds=(int)val;\r
-\r
- temp.Add(seconds,minutes,hours,days);\r
- return temp;\r
-}\r
-\r
-DateTime DateTime::operator+(const DateTime &rhs)\r
-{\r
- DateTime temp=*this;\r
-\r
- temp.Add(rhs.m_tm.tm_sec,rhs.m_tm.tm_min,rhs.m_tm.tm_hour,rhs.m_tm.tm_mday,rhs.m_tm.tm_mon+1,rhs.m_tm.tm_year+1900);\r
- return temp;\r
-}\r
-\r
-DateTime &DateTime::operator+=(const double &rhs)\r
-{\r
- *this=*this+rhs;\r
-\r
- return *this;\r
-}\r
-\r
-DateTime &DateTime::operator+=(const DateTime &rhs)\r
-{\r
- *this=*this+rhs;\r
-\r
- return *this;\r
-}\r
-\r
-DateTime DateTime::operator-(const double &rhs)\r
-{\r
- DateTime temp=*this;\r
-\r
- double val=rhs;\r
- int days=(int)val;\r
- val-=days;\r
- val*=24.0;\r
- int hours=(int)val;\r
- val-=hours;\r
- val*=60.0;\r
- int minutes=(int)val;\r
- val-=minutes;\r
- val*=60.0;\r
- int seconds=(int)val;\r
-\r
- temp.Add(-seconds,-minutes,-hours,-days);\r
- return temp;\r
-}\r
-\r
-DateTime DateTime::operator-(const DateTime &rhs)\r
-{\r
- DateTime temp=*this;\r
-\r
- temp.Add(-rhs.m_tm.tm_sec,-rhs.m_tm.tm_min,-rhs.m_tm.tm_hour,-rhs.m_tm.tm_mday,-(rhs.m_tm.tm_mon+1),-(rhs.m_tm.tm_year+1900));\r
- return temp;\r
-}\r
-\r
-DateTime &DateTime::operator-=(const double &rhs)\r
-{\r
- *this=*this-rhs;\r
-\r
- return *this;\r
-}\r
-\r
-DateTime &DateTime::operator-=(const DateTime &rhs)\r
-{\r
- *this=*this-rhs;\r
-\r
- return *this;\r
-}\r
-\r
-const bool DateTime::operator==(const struct tm &rhs) const\r
-{\r
- return (m_tm.tm_year==rhs.tm_year && m_tm.tm_mon==rhs.tm_mon && m_tm.tm_mday==rhs.tm_mday && m_tm.tm_hour==rhs.tm_hour && m_tm.tm_min==rhs.tm_min && m_tm.tm_sec==rhs.tm_sec) ? true : false;\r
-}\r
-\r
-const bool DateTime::operator<(const struct tm &rhs) const\r
-{\r
- return (m_tm.tm_year<rhs.tm_year || (m_tm.tm_year==rhs.tm_year && m_tm.tm_mon<rhs.tm_mon) || (m_tm.tm_year==rhs.tm_year && m_tm.tm_mon==rhs.tm_mon && m_tm.tm_mday<rhs.tm_mday) || (m_tm.tm_year==rhs.tm_year && m_tm.tm_mon==rhs.tm_mon && m_tm.tm_mday==rhs.tm_mday && m_tm.tm_hour<rhs.tm_hour) || (m_tm.tm_year==rhs.tm_year && m_tm.tm_mon==rhs.tm_mon && m_tm.tm_mday==rhs.tm_mday && m_tm.tm_hour==rhs.tm_hour && m_tm.tm_min<rhs.tm_min) || (m_tm.tm_year==rhs.tm_year && m_tm.tm_mon==rhs.tm_mon && m_tm.tm_mday==rhs.tm_mday && m_tm.tm_hour==rhs.tm_hour && m_tm.tm_min==rhs.tm_min && m_tm.tm_sec==rhs.tm_sec));\r
-}\r
-\r
-void DateTime::Set(const int year, const int month, const int day, const int hour, const int minute, const int second)\r
-{\r
- m_tm.tm_year=year-1900;\r
- m_tm.tm_mon=month-1;\r
- m_tm.tm_mday=day;\r
- m_tm.tm_hour=hour;\r
- m_tm.tm_min=minute;\r
- m_tm.tm_sec=second;\r
-\r
- Normalize();\r
-}\r
-\r
-void DateTime::SetT(const time_t &timet)\r
-{\r
- m_timet=timet;\r
-\r
- m_tm=*gmtime(&m_timet);\r
- Normalize();\r
-}\r
-\r
-void DateTime::Set(const struct tm *stm)\r
-{\r
- m_tm=*stm;\r
- m_timet=mktime(&m_tm);\r
- Normalize();\r
-}\r
-\r
-void DateTime::Set(const std::string &datestring)\r
-{\r
- int year,month,day,hour,minute,second;\r
- std::vector<std::string> tokens;\r
- std::vector<std::string>::size_type vecpos;\r
- int tempint;\r
-\r
- year=month=day=hour=minute=second=-1;\r
-\r
- // reset to 1900-01-01 00:00:00\r
- Set();\r
-\r
- StringFunctions::SplitMultiple(datestring,"-/\\., :",tokens);\r
-\r
- // loop through 1st time to try to find 4 digit year and month (if it is a text month)\r
- vecpos=0;\r
- for(std::vector<std::string>::iterator i=tokens.begin(); i!=tokens.end(); i++,vecpos++)\r
- {\r
- StringFunctions::UpperCase((*i),(*i));\r
-\r
- if((*i).find("JAN")==0)\r
- {\r
- SetMonth(1);\r
- month=vecpos;\r
- }\r
- if((*i).find("FEB")==0)\r
- {\r
- SetMonth(2);\r
- month=vecpos;\r
- }\r
- if((*i).find("MAR")==0)\r
- {\r
- SetMonth(3);\r
- month=vecpos;\r
- }\r
- if((*i).find("APR")==0)\r
- {\r
- SetMonth(4);\r
- month=vecpos;\r
- }\r
- if((*i).find("MAY")==0)\r
- {\r
- SetMonth(5);\r
- month=vecpos;\r
- }\r
- if((*i).find("JUN")==0)\r
- {\r
- SetMonth(6);\r
- month=vecpos;\r
- }\r
- if((*i).find("JUL")==0)\r
- {\r
- SetMonth(7);\r
- month=vecpos;\r
- }\r
- if((*i).find("AUG")==0)\r
- {\r
- SetMonth(8);\r
- month=vecpos;\r
- }\r
- if((*i).find("SEP")==0)\r
- {\r
- SetMonth(9);\r
- month=vecpos;\r
- }\r
- if((*i).find("OCT")==0)\r
- {\r
- SetMonth(10);\r
- month=vecpos;\r
- }\r
- if((*i).find("NOV")==0)\r
- {\r
- SetMonth(11);\r
- month=vecpos;\r
- }\r
- if((*i).find("DEC")==0)\r
- {\r
- SetMonth(12);\r
- month=vecpos;\r
- }\r
-\r
- // if we just got month - day is probaby in the next position\r
- if(month==vecpos && vecpos+1<tokens.size() && tokens[vecpos+1].size()>0)\r
- {\r
- tempint=-1;\r
- StringFunctions::Convert(tokens[vecpos+1],tempint);\r
- if(tempint>0 && tempint<32)\r
- {\r
- SetDay(tempint);\r
- day=vecpos+1;\r
- }\r
- }\r
-\r
- // if this is not month or day, and the size is 4 then it is probably the year\r
- if(month!=vecpos && day!=vecpos && (*i).size()==4)\r
- {\r
- tempint=-1;\r
- StringFunctions::Convert((*i),tempint);\r
-\r
- SetYear(tempint);\r
- year=vecpos;\r
- }\r
- }\r
-\r
- // month is probably right after year\r
- if(year!=-1 && month==-1 && year+1<tokens.size())\r
- {\r
- tempint=-1;\r
- StringFunctions::Convert(tokens[year+1],tempint);\r
- if(tempint>=1 && tempint<=12)\r
- {\r
- SetMonth(tempint);\r
- month=year+1;\r
- }\r
- }\r
-\r
- // otherwise it is probably 2 steps back (m/d/y)\r
- if(year!=-1 && month==-1 && year-2>=0)\r
- {\r
- tempint=-1;\r
- StringFunctions::Convert(tokens[year-2],tempint);\r
- if(tempint>=1 && tempint<=12)\r
- {\r
- SetMonth(tempint);\r
- month=year-2;\r
- }\r
- }\r
-\r
- // day is probably right after month\r
- if(month!=-1 && month+1<tokens.size())\r
- {\r
- tempint=-1;\r
- StringFunctions::Convert(tokens[month+1],tempint);\r
- if(tempint>=1 && tempint<32)\r
- {\r
- SetDay(tempint);\r
- day=month+1;\r
- }\r
- }\r
-\r
- // loop through another time to find hour\r
- vecpos=0;\r
- for(std::vector<std::string>::iterator i=tokens.begin(); i!=tokens.end(); i++,vecpos++)\r
- {\r
- if(vecpos!=year && vecpos!=month && vecpos!=day && hour==-1)\r
- {\r
- tempint=-1;\r
- StringFunctions::Convert((*i),tempint);\r
- if(tempint>=0 && tempint<24)\r
- {\r
- SetHour(tempint);\r
- hour=vecpos;\r
- }\r
- }\r
- }\r
-\r
- // minute right after hour\r
- if(hour!=-1 && hour+1<tokens.size())\r
- {\r
- tempint=-1;\r
- StringFunctions::Convert(tokens[hour+1],tempint);\r
- if(tempint>=0 && tempint<60)\r
- {\r
- SetMinute(tempint);\r
- minute=hour+1;\r
- }\r
- }\r
-\r
- //second right after minute\r
- if(minute!=-1 && minute+1<tokens.size())\r
- {\r
- tempint=-1;\r
- StringFunctions::Convert(tokens[minute+1],tempint);\r
- if(tempint>=0 && tempint<60)\r
- {\r
- SetSecond(tempint);\r
- second=minute+1;\r
- }\r
- }\r
-\r
-}\r
-\r
-void DateTime::SetToGMTime()\r
-{\r
- m_timet=time(NULL);\r
-\r
- m_tm=*gmtime(&m_timet);\r
- Normalize();\r
-}\r
-\r
-void DateTime::SetToLocalTime()\r
-{\r
- m_timet=time(NULL);\r
- m_tm=*localtime(&m_timet);\r
- Normalize();\r
-}\r
-\r
-const time_t DateTime::TimeGM(struct tm *gmtimein)\r
-{\r
- //This looks good but I don't think will work when TZ isn't set (Windows)\r
- //http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/timegm.3.html\r
- \r
- //This should work\r
- //http://lists2.ais.fraunhofer.de/pipermail/emx/1999-September/000874.html\r
-\r
- struct tm ttm;\r
- time_t t, t2;\r
-\r
- ttm = *gmtimein; /* make a local copy to fiddle with */\r
- ttm.tm_isdst = 0; /* treat it as standard time */\r
-\r
- t2 = t = mktime(&ttm); /* calculate the time as a local time */\r
-\r
- ttm = *gmtime(&t2); /* now calculate the difference between */\r
- ttm.tm_isdst = 0; /* gm and local time */\r
- t2 = mktime(&ttm);\r
-\r
- t += t - t2; /* and adjust our answer by that difference */\r
- return t;\r
-}\r
{\r
if(IsOpen())\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(m_mutex);\r
- PThread::Guard g(m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
m_lastresult=sqlite3_close(m_db);\r
if(m_lastresult==SQLITE_OK)\r
{\r
{\r
if(IsOpen())\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(m_mutex);\r
- PThread::Guard g(m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
m_lastresult=sqlite3_exec(m_db,sql.c_str(),NULL,NULL,NULL);\r
if(m_lastresult==SQLITE_OK)\r
{\r
{\r
if(IsOpen())\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(m_mutex);\r
- PThread::Guard g(m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
m_lastresult=sqlite3_exec(m_db,sql.c_str(),NULL,NULL,NULL);\r
if(m_lastresult==SQLITE_OK)\r
{\r
{\r
if(IsOpen())\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(m_mutex);\r
- PThread::Guard g(m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
int errcode=sqlite3_errcode(m_db);\r
const char *errmsg=sqlite3_errmsg(m_db);\r
if(errmsg)\r
\r
const bool DB::IsOpen()\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(m_mutex);\r
- PThread::Guard g(m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
return m_db ? true : false; \r
}\r
\r
}\r
if(IsOpen()==false)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(m_mutex);\r
- PThread::Guard g(m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
m_lastresult=sqlite3_open(filename.c_str(),&m_db);\r
if(m_lastresult==SQLITE_OK)\r
{\r
{\r
if(IsOpen())\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(m_mutex);\r
- PThread::Guard g(m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
sqlite3_stmt *statement=NULL;\r
m_lastresult=sqlite3_prepare_v2(m_db,sql.c_str(),sql.size(),&statement,NULL);\r
if(m_lastresult==SQLITE_OK)\r
{\r
if(IsOpen())\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(m_mutex);\r
- PThread::Guard g(m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
char **rs=NULL;\r
int rows,cols;\r
m_lastresult=sqlite3_get_table(m_db,sql.c_str(),&rs,&rows,&cols,NULL);\r
{\r
if(IsOpen())\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(m_mutex);\r
- PThread::Guard g(m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(m_mutex);\r
m_lastresult=sqlite3_busy_timeout(m_db,ms);\r
return m_lastresult;\r
}\r
Free();\r
m_currentrow=0;\r
\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- PThread::Guard g(DB::Instance()->m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(DB::Instance()->m_mutex);\r
if(sqlite3_get_table(db->GetDB(),sql.c_str(),&m_rs,&m_rows,&m_cols,NULL)==SQLITE_OK)\r
{\r
}\r
{\r
if(m_statement)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- PThread::Guard g(DB::Instance()->m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(DB::Instance()->m_mutex);\r
m_statementcount[m_statement]--;\r
if(m_statementcount[m_statement]<=0)\r
{\r
\r
if(m_statement)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- PThread::Guard g(DB::Instance()->m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(DB::Instance()->m_mutex);\r
m_statementcount[m_statement]++;\r
}\r
}\r
{\r
if(Valid())\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- PThread::Guard g(DB::Instance()->m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(DB::Instance()->m_mutex);\r
if(sqlite3_reset(m_statement)==SQLITE_OK)\r
{\r
return true;\r
{\r
if(Valid() && column>=0 && column<m_resultcolumncount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
int bloblength=sqlite3_column_bytes(m_statement,column);\r
if(bloblength>length)\r
{\r
{\r
if(Valid() && column>=0 && column<m_resultcolumncount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
result=sqlite3_column_double(m_statement,column);\r
return true;\r
}\r
{\r
if(Valid() && column>=0 && column<m_resultcolumncount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
result=sqlite3_column_int(m_statement,column);\r
return true;\r
}\r
{\r
if(Valid() && column>=0 && column<m_resultcolumncount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
if(sqlite3_column_type(m_statement,column)==SQLITE_NULL)\r
{\r
return true;\r
{\r
if(Valid() && column>=0 && column<m_resultcolumncount)\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- //PThread::Guard g(DB::Instance()->m_mutex);\r
const unsigned char *cresult=sqlite3_column_text(m_statement,column);\r
if(cresult)\r
{\r
m_rowreturned=false;\r
if(Valid())\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- PThread::Guard g(DB::Instance()->m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(DB::Instance()->m_mutex);\r
int result=sqlite3_step(m_statement);\r
if(result==SQLITE_OK || result==SQLITE_ROW || result==SQLITE_DONE)\r
{\r
\r
const bool Statement::Valid()\r
{\r
- //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
- PThread::Guard g(DB::Instance()->m_mutex);\r
+ Poco::ScopedLock<Poco::FastMutex> g(DB::Instance()->m_mutex);\r
return m_statement ? true : false ;\r
}\r
\r
--- /dev/null
+#include "../include/dbconversions.h"\r
+#include "../include/db/sqlite3db.h"\r
+#include "../include/stringfunctions.h"\r
+\r
+#include <Poco/Timestamp.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+\r
+void ConvertDB0100To0101()\r
+{\r
+ // added unique constraint to public and private key\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");\r
+ db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
+ LocalIdentityID INTEGER PRIMARY KEY,\\r
+ Name TEXT,\\r
+ PublicKey TEXT UNIQUE,\\r
+ PrivateKey TEXT UNIQUE,\\r
+ SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
+ PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
+ PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
+ InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedIdentity DATETIME,\\r
+ InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedPuzzle DATETIME,\\r
+ InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedTrustList DATETIME,\\r
+ InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedBoardList DATETIME,\\r
+ InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedMessageList DATETIME\\r
+ );");\r
+ db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");\r
+ db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");\r
+}\r
+\r
+void ConvertDB0101To0103()\r
+{\r
+ // remove default 50 from trust fields and set default to NULL\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");\r
+ db->Execute("DROP TABLE IF EXISTS tblIdentity;");\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
+ IdentityID INTEGER PRIMARY KEY,\\r
+ PublicKey TEXT UNIQUE,\\r
+ Name TEXT,\\r
+ SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
+ PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
+ PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
+ DateAdded DATETIME,\\r
+ LastSeen DATETIME,\\r
+ LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\\r
+ );");\r
+ db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");\r
+ db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");\r
+\r
+ // add SaveReceivedMessages field to tblBoard\r
+ db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");\r
+\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");\r
+}\r
+\r
+void ConvertDB0103To0104()\r
+{\r
+ // add MessageIndex to tblMessage\r
+ Poco::Timestamp date;\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;");\r
+ db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");\r
+ db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");\r
+ db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");\r
+}\r
+\r
+void ConvertDB0104To0105()\r
+{\r
+ // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity\r
+ // add MessageTrustComment,TrustListTrustComment to tblPeerTrust\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;");\r
+ db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;");\r
+ db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;");\r
+ db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;");\r
+ db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;");\r
+}\r
+\r
+void ConvertDB0105To0106()\r
+{\r
+ // add Publish Freesite\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';");\r
+ db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");\r
+}\r
+\r
+void ConvertDB0106To0107()\r
+{\r
+ // add AddedMethod to tblBoard\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("ALTER TABLE tblBoard ADD COLUMN AddedMethod TEXT;");\r
+ db->Execute("ALTER TABLE tblIdentity ADD COLUMN Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false';");\r
+ db->Execute("UPDATE tblIdentity SET Hidden='false' WHERE Hidden IS NULL;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=7;");\r
+}\r
+\r
+void ConvertDB0107To0108()\r
+{\r
+ // add FreesiteEdition to tblLocalIdentity and tblIdentity\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN FreesiteEdition INTEGER;");\r
+ db->Execute("ALTER TABLE tblIdentity ADD COLUMN FreesiteEdition INTEGER;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=8;");\r
+}\r
+\r
+void ConvertDB0108To0109()\r
+{\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\\r
+ FileInsertID INTEGER PRIMARY KEY,\\r
+ MessageUUID TEXT,\\r
+ FileName TEXT,\\r
+ Key TEXT,\\r
+ Size INTEGER,\\r
+ Data BLOB\\r
+ );");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;");\r
+}\r
+\r
+void ConvertDB0109To0110()\r
+{\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ db->Execute("ALTER TABLE tblFileInserts ADD COLUMN MimeType TEXT;");\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=10;");\r
+}\r
+\r
+void ConvertDB0110To0111()\r
+{\r
+ /*\r
+ Drop MessageTrustComment, TrustListTrustComment FROM tblIdentity\r
+\r
+ Drop InsertingMessageList, InsertingBoardList FROM tblLocalIdentity\r
+ Add MinMessageDelay, MaxMessageDelay to tblLocalIdentity Default 0\r
+\r
+ Add SendDate to tblMessageInserts\r
+ */\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+\r
+ db->Execute("ALTER TABLE tblMessageInserts ADD COLUMN SendDate DATETIME;");\r
+\r
+ db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");\r
+ db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
+ LocalIdentityID INTEGER PRIMARY KEY,\\r
+ Name TEXT,\\r
+ PublicKey TEXT UNIQUE,\\r
+ PrivateKey TEXT UNIQUE,\\r
+ SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
+ PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
+ PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
+ PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\\r
+ FreesiteEdition INTEGER,\\r
+ InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedIdentity DATETIME,\\r
+ InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedPuzzle DATETIME,\\r
+ InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedTrustList DATETIME,\\r
+ LastInsertedBoardList DATETIME,\\r
+ LastInsertedMessageList DATETIME,\\r
+ LastInsertedFreesite DATETIME,\\r
+ DateCreated DATETIME,\\r
+ MinMessageDelay INTEGER DEFAULT 0,\\r
+ MaxMessageDelay INTEGER DEFAULT 0\\r
+ );");\r
+ db->Execute("INSERT INTO tblLocalIdentity SELECT LocalIdentityID,Name,PublicKey,PrivateKey,SingleUse,PublishTrustList,PublishBoardList,PublishFreesite,FreesiteEdition,InsertingIdentity,LastInsertedIdentity,InsertingPuzzle,LastInsertedPuzzle,InsertingTrustList,LastInsertedTrustList,LastInsertedBoardList,LastInsertedMessageList,LastInsertedFreesite,DateCreated,0,0 FROM tblLocalIdentityTemp;");\r
+ db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");\r
+\r
+ db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");\r
+ db->Execute("DROP TABLE IF EXISTS tblIdentity;");\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
+ IdentityID INTEGER PRIMARY KEY,\\r
+ PublicKey TEXT UNIQUE,\\r
+ Name TEXT,\\r
+ SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
+ PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
+ PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
+ FreesiteEdition INTEGER,\\r
+ DateAdded DATETIME,\\r
+ LastSeen DATETIME,\\r
+ LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ AddedMethod TEXT,\\r
+ Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+ db->Execute("INSERT INTO tblIdentity SELECT IdentityID,PublicKey,Name,SingleUse,PublishTrustList,PublishBoardList,FreesiteEdition,DateAdded,LastSeen,LocalMessageTrust,PeerMessageTrust,LocalTrustListTrust,PeerTrustListTrust,AddedMethod,Hidden FROM tblIdentityTemp;");\r
+ db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");\r
+\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=11;");\r
+}\r
+\r
+void ConvertDB0111To0112()\r
+{\r
+ /*\r
+ Add Section, SortOrder, ValidValues to tblOption\r
+ Add PurgeDate to tblIdentity\r
+ */\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+\r
+ db->Execute("ALTER TABLE tblOption ADD COLUMN Section TEXT;");\r
+ db->Execute("ALTER TABLE tblOption ADD COLUMN SortOrder INTEGER;");\r
+ db->Execute("ALTER TABLE tblOption ADD COLUMN ValidValues TEXT;");\r
+\r
+ db->Execute("ALTER TABLE tblIdentity ADD COLUMN PurgeDate DATETIME;");\r
+\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=12;");\r
+}\r
+\r
+void FixCapitalBoardNames()\r
+{\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+\r
+ SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);");\r
+ SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");\r
+ SQLite3DB::Statement del=db->Prepare("DELETE FROM tblBoard WHERE BoardID=?;");\r
+ SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;");\r
+ SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;");\r
+ SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;");\r
+\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ int boardid=0;\r
+ int newboardid=0;\r
+ std::string name="";\r
+ std::string lowername="";\r
+\r
+ st.ResultInt(0,boardid);\r
+ st.ResultText(1,name);\r
+\r
+ lowername=name;\r
+ StringFunctions::LowerCase(lowername,lowername);\r
+ \r
+ if(name!=lowername)\r
+ {\r
+ st2.Bind(0,lowername);\r
+ st2.Step();\r
+\r
+ if(st2.RowReturned())\r
+ {\r
+ st2.ResultInt(0,newboardid);\r
+\r
+ upd2.Bind(0,newboardid);\r
+ upd2.Bind(1,boardid);\r
+ upd2.Step();\r
+ upd2.Reset();\r
+\r
+ upd3.Bind(0,newboardid);\r
+ upd3.Bind(1,boardid);\r
+ upd3.Step();\r
+ upd3.Reset();\r
+\r
+ del.Bind(0,boardid);\r
+ del.Step();\r
+ del.Reset();\r
+ }\r
+ else\r
+ {\r
+ upd.Bind(0,lowername);\r
+ upd.Bind(1,boardid);\r
+ upd.Step();\r
+ upd.Reset();\r
+ }\r
+\r
+ st2.Reset();\r
+ }\r
+ \r
+ st.Step();\r
+ }\r
+\r
+}\r
--- /dev/null
+#include "../include/dbmaintenancethread.h"\r
+#include "../include/stringfunctions.h"\r
+#include "../include/option.h"\r
+\r
+#include <Poco/Timestamp.h>\r
+#include <Poco/Timespan.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/Thread.h>\r
+\r
+DBMaintenanceThread::DBMaintenanceThread()\r
+{\r
+ // move last maintenance times back so they will all run soon\r
+ m_last10minute=Poco::Timestamp();\r
+ m_last30minute=Poco::Timestamp();\r
+ m_last30minute-=Poco::Timespan(0,0,11,0,0);\r
+ m_last1hour=Poco::Timestamp();\r
+ m_last1hour-=Poco::Timespan(0,0,49,0,0);\r
+ m_last6hour=Poco::Timestamp();\r
+ m_last6hour-=Poco::Timespan(0,5,42,0,0);\r
+ m_last1day=Poco::Timestamp();\r
+ m_last1day-=Poco::Timespan(0,23,51,0,0);\r
+\r
+ std::string tempval="180";\r
+ Option::Instance()->Get("DeleteMessagesOlderThan",tempval);\r
+ StringFunctions::Convert(tempval,m_deletemessagesolderthan);\r
+\r
+}\r
+\r
+\r
+void DBMaintenanceThread::Do10MinuteMaintenance()\r
+{\r
+\r
+ m_log->debug("PeriodicDBMaintenance::Do10MinuteMaintenance");\r
+}\r
+\r
+void DBMaintenanceThread::Do30MinuteMaintenance()\r
+{\r
+\r
+ m_log->debug("PeriodicDBMaintenance::Do30MinuteMaintenance");\r
+}\r
+\r
+void DBMaintenanceThread::Do1HourMaintenance()\r
+{\r
+ // recalculate all trust levels - this is CPU instensive\r
+ // do 1 identity at a time as doing it with 1 UPDATE statement locks that database for the duration\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT TargetIdentityID,PeerMessageTrust,PeerTrustListTrust FROM vwCalculatedPeerTrust;");\r
+ SQLite3DB::Statement upd=m_db->Prepare("UPDATE tblIdentity SET PeerMessageTrust=?, PeerTrustListTrust=? WHERE IdentityID=?");\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ int identityid=0;\r
+ int trust=0;\r
+ \r
+ st.ResultInt(0,identityid);\r
+\r
+ upd.Bind(0,identityid);\r
+ if(st.ResultNull(1)==false)\r
+ {\r
+ trust=0;\r
+ st.ResultInt(1,trust);\r
+ upd.Bind(0,trust);\r
+ }\r
+ else\r
+ {\r
+ upd.Bind(0);\r
+ }\r
+ if(st.ResultNull(2)==false)\r
+ {\r
+ trust=0;\r
+ st.ResultInt(2,trust);\r
+ upd.Bind(1,trust);\r
+ }\r
+ else\r
+ {\r
+ upd.Bind(1);\r
+ }\r
+ upd.Bind(2,identityid);\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Step();\r
+ }\r
+\r
+ // set null peer trust for identities without a calculated trust\r
+ st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE IdentityID NOT IN (SELECT TargetIdentityID FROM vwCalculatedPeerTrust);");\r
+ upd=m_db->Prepare("UPDATE tblIdentity SET PeerMessageTrust=NULL, PeerTrustListTrust=NULL WHERE IdentityID=?;");\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ int identityid=0;\r
+ st.ResultInt(0,identityid);\r
+ upd.Bind(0,identityid);\r
+ upd.Step();\r
+ upd.Reset();\r
+ st.Step();\r
+ }\r
+\r
+ m_log->debug("PeriodicDBMaintenance::Do1HourMaintenance");\r
+}\r
+\r
+void DBMaintenanceThread::Do6HourMaintenance()\r
+{\r
+\r
+ // if we remove a board and the reply boardid is still set to it, we need to replace it with a boardid that does exist\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT MessageID FROM tblMessage WHERE ReplyBoardID NOT IN (SELECT BoardID FROM tblBoard);");\r
+ SQLite3DB::Statement st2=m_db->Prepare("SELECT BoardID FROM tblMessageBoard WHERE MessageID=?;");\r
+ SQLite3DB::Statement upd=m_db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE MessageID=?;");\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ // find a valid boardid for the message\r
+ int messageid=0;\r
+ int boardid=0;\r
+\r
+ st.ResultInt(0,messageid);\r
+\r
+ st2.Bind(0,messageid);\r
+ st2.Step();\r
+ if(st2.RowReturned())\r
+ {\r
+ st2.ResultInt(0,boardid);\r
+ upd.Bind(0,boardid);\r
+ upd.Bind(1,messageid);\r
+ upd.Step();\r
+ upd.Reset();\r
+ }\r
+ st2.Reset();\r
+ \r
+ st.Step();\r
+ }\r
+\r
+ m_log->debug("PeriodicDBMaintenance::Do6HourMaintenance");\r
+}\r
+\r
+void DBMaintenanceThread::Do1DayMaintenance()\r
+{\r
+ Poco::DateTime date;\r
+\r
+ // delete all puzzles 2 or more days old\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(2,0,0,0,0);\r
+ m_db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+ m_db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+\r
+ // delete all identities we've never seen and were added more than 20 days ago\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(20,0,0,0,0);\r
+ m_db->Execute("DELETE FROM tblIdentity WHERE LastSeen IS NULL AND DateAdded<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+\r
+ // delete old identity requests - we don't need them anymore\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(2,0,0,0,0);\r
+ m_db->Execute("DELETE FROM tblIdentityRequests WHERE Day<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+\r
+ // delete old board list inserts/requests - we don't need them anymore\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(2,0,0,0,0);\r
+ m_db->Execute("DELETE FROM tblBoardListInserts WHERE Day<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+ m_db->Execute("DELETE FROM tblBoardListRequests WHERE Day<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+\r
+ // delete old local identity inserts - we don't need them anymore\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(2,0,0,0,0);\r
+ m_db->Execute("DELETE FROM tblLocalIdentityInserts WHERE Day<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+\r
+ // delete old message list inserts/requests - we don't need them anymore\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(2,0,0,0,0);\r
+ m_db->Execute("DELETE FROM tblMessageListInserts WHERE Day<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+ m_db->Execute("DELETE FROM tblMessageListRequests WHERE Day<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+\r
+ // delete old trust list inserts/requests - we don't need them anymore\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(2,0,0,0,0);\r
+ m_db->Execute("DELETE FROM tblTrustListInserts WHERE Day<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+ m_db->Execute("DELETE FROM tblTrustListRequests WHERE Day<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+\r
+ // delete trust lists from identities we aren't trusting anymore\r
+ m_db->Execute("DELETE FROM tblPeerTrust WHERE IdentityID NOT IN (SELECT IdentityID FROM tblIdentity WHERE (LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust')) AND (PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust')));");\r
+\r
+ // remove identityid from messages where the identity has been deleted\r
+ m_db->Execute("UPDATE tblMessage SET IdentityID=NULL WHERE IdentityID NOT IN (SELECT IdentityID FROM tblIdentity);");\r
+\r
+ // try to re-attach messages from identities that were previously deleted, but have been since re-added\r
+ // first get the names from messages that have a NULL IdentityID\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT FromName FROM tblMessage WHERE IdentityID IS NULL GROUP BY FromName;");\r
+ st.Step();\r
+ while(st.RowReturned())\r
+ {\r
+ std::string name="";\r
+ std::string namepart="";\r
+ std::string publickey="";\r
+ int identityid=0;\r
+ st.ResultText(0,name);\r
+\r
+ std::vector<std::string> parts;\r
+ StringFunctions::Split(name,"@",parts);\r
+\r
+ // name can have a @ in it - so reattach all parts except the last which is the key\r
+ for(long i=0; i<parts.size()-1; i++)\r
+ {\r
+ if(i!=0)\r
+ {\r
+ namepart+="@";\r
+ }\r
+ namepart+=parts[i];\r
+ }\r
+\r
+ // find identities with this name\r
+ SQLite3DB::Statement st2=m_db->Prepare("SELECT IdentityID,PublicKey FROM tblIdentity WHERE Name=?;");\r
+ st2.Bind(0,namepart);\r
+ st2.Step();\r
+ while(st2.RowReturned())\r
+ {\r
+ publickey="";\r
+ identityid=0;\r
+ st2.ResultText(1,publickey);\r
+ // check if public key matches 2nd part\r
+ if(parts.size()>1 && publickey.find(parts[1])==4)\r
+ {\r
+ // we have the identity - so update the messages table with the identityid\r
+ st2.ResultInt(0,identityid);\r
+\r
+ SQLite3DB::Statement st3=m_db->Prepare("UPDATE tblMessage SET IdentityID=? WHERE FromName=? AND IdentityID IS NULL;");\r
+ st3.Bind(0,identityid);\r
+ st3.Bind(1,name);\r
+ st3.Step();\r
+ }\r
+ st2.Step();\r
+ }\r
+\r
+ st.Step();\r
+ }\r
+\r
+ // delete single use identities that are older than 7 days\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(7,0,0,0,0);\r
+ st=m_db->Prepare("DELETE FROM tblIdentity WHERE SingleUse='true' AND DateAdded<?;");\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
+ st.Step();\r
+\r
+ // delete local single use identities that are older than 7 days\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(7,0,0,0,0);\r
+ st=m_db->Prepare("DELETE FROM tblLocalIdentity WHERE SingleUse='true' AND DateCreated<?;");\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
+ st.Step();\r
+\r
+ // delete old messages\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(m_deletemessagesolderthan,0,0,0,0);\r
+ st=m_db->Prepare("DELETE FROM tblMessage WHERE MessageDate<?;");\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
+ st.Step();\r
+\r
+ // delete tblIdentityTrust for local identities and identities that have been deleted\r
+ m_db->Execute("DELETE FROM tblIdentityTrust WHERE LocalIdentityID NOT IN (SELECT LocalIdentityID FROM tblLocalIdentity);");\r
+ m_db->Execute("DELETE FROM tblIdentityTrust WHERE IdentityID NOT IN (SELECT IdentityID FROM tblIdentity);");\r
+\r
+ m_log->debug("PeriodicDBMaintenance::Do1DayMaintenance");\r
+\r
+}\r
+\r
+void DBMaintenanceThread::run()\r
+{\r
+ m_log->debug("DBMaintenanceThread::run thread started.");\r
+\r
+ Poco::DateTime now;\r
+\r
+ do\r
+ {\r
+ now=Poco::Timestamp();\r
+\r
+ if((m_last10minute+Poco::Timespan(0,0,10,0,0))<=now)\r
+ {\r
+ Do10MinuteMaintenance();\r
+ m_last10minute=Poco::Timestamp();\r
+ }\r
+ if((m_last30minute+Poco::Timespan(0,0,30,0,0))<=now)\r
+ {\r
+ Do30MinuteMaintenance();\r
+ m_last30minute=Poco::Timestamp();\r
+ }\r
+ if((m_last1hour+Poco::Timespan(0,1,0,0,0))<=now)\r
+ {\r
+ Do1HourMaintenance();\r
+ m_last1hour=Poco::Timestamp();\r
+ }\r
+ if((m_last6hour+Poco::Timespan(0,6,0,0,0))<=now)\r
+ {\r
+ Do6HourMaintenance();\r
+ m_last6hour=Poco::Timestamp();\r
+ }\r
+ if((m_last1day+Poco::Timespan(1,0,0,0,0))<=now)\r
+ {\r
+ Do1DayMaintenance();\r
+ m_last1day=Poco::Timestamp();\r
+ }\r
+\r
+ Poco::Thread::sleep(1000);\r
+ }while(!IsCancelled());\r
+\r
+ m_log->debug("DBMaintenanceThread::run thread exiting.");\r
+}\r
--- /dev/null
+#include "../include/dbsetup.h"\r
+#include "../include/dbconversions.h"\r
+#include "../include/option.h"\r
+#include "../include/db/sqlite3db.h"\r
+\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timespan.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+\r
+void SetupDB()\r
+{\r
+\r
+ Poco::DateTime date;\r
+ std::string tempval="";\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+\r
+ db->Open("fms.db3");\r
+ db->SetBusyTimeout(10000); // set timeout to 10 seconds\r
+\r
+ tempval="";\r
+ Option::Instance()->Get("VacuumOnStartup",tempval);\r
+ if(tempval=="true")\r
+ {\r
+ db->Execute("VACUUM;");\r
+ }\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblDBVersion(\\r
+ Major INTEGER,\\r
+ Minor INTEGER\\r
+ );");\r
+\r
+ SQLite3DB::Statement st=db->Prepare("SELECT Major,Minor FROM tblDBVersion;");\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ int major;\r
+ int minor;\r
+ st.ResultInt(0,major);\r
+ st.ResultInt(1,minor);\r
+ st.Finalize();\r
+ if(major==1 && minor==0)\r
+ {\r
+ ConvertDB0100To0101();\r
+ major=1;\r
+ minor=1;\r
+ }\r
+ if(major==1 && (minor==1 || minor==2))\r
+ {\r
+ ConvertDB0101To0103();\r
+ major=1;\r
+ minor=3;\r
+ }\r
+ if(major==1 && minor==3)\r
+ {\r
+ ConvertDB0103To0104();\r
+ major=1;\r
+ minor=4;\r
+ }\r
+ if(major==1 && minor==4)\r
+ {\r
+ ConvertDB0104To0105();\r
+ major=1;\r
+ minor=5;\r
+ }\r
+ if(major==1 && minor==5)\r
+ {\r
+ ConvertDB0105To0106();\r
+ major=1;\r
+ minor=6;\r
+ }\r
+ if(major==1 && minor==6)\r
+ {\r
+ ConvertDB0106To0107();\r
+ major=1;\r
+ minor=7;\r
+ }\r
+ if(major==1 && minor==7)\r
+ {\r
+ ConvertDB0107To0108();\r
+ major=1;\r
+ minor=8;\r
+ }\r
+ if(major==1 && minor==8)\r
+ {\r
+ ConvertDB0108To0109();\r
+ major=1;\r
+ minor=9;\r
+ }\r
+ if(major==1 && minor==9)\r
+ {\r
+ ConvertDB0109To0110();\r
+ major=1;\r
+ minor=10;\r
+ }\r
+ if(major==1 && minor==10)\r
+ {\r
+ ConvertDB0110To0111();\r
+ major=1;\r
+ minor=11;\r
+ }\r
+ if(major==1 && minor==11)\r
+ {\r
+ ConvertDB0111To0112();\r
+ major=1;\r
+ minor=12;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,12);");\r
+ }\r
+\r
+ db->Execute("UPDATE tblDBVersion SET Major=1, Minor=12;");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\\r
+ Option TEXT UNIQUE,\\r
+ OptionValue TEXT NOT NULL,\\r
+ OptionDescription TEXT,\\r
+ Section TEXT,\\r
+ SortOrder INTEGER,\\r
+ ValidValues TEXT\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
+ LocalIdentityID INTEGER PRIMARY KEY,\\r
+ Name TEXT,\\r
+ PublicKey TEXT UNIQUE,\\r
+ PrivateKey TEXT UNIQUE,\\r
+ SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
+ PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
+ PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
+ PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\\r
+ FreesiteEdition INTEGER,\\r
+ InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedIdentity DATETIME,\\r
+ InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedPuzzle DATETIME,\\r
+ InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\\r
+ LastInsertedTrustList DATETIME,\\r
+ LastInsertedBoardList DATETIME,\\r
+ LastInsertedMessageList DATETIME,\\r
+ LastInsertedFreesite DATETIME,\\r
+ DateCreated DATETIME,\\r
+ MinMessageDelay INTEGER DEFAULT 0,\\r
+ MaxMessageDelay INTEGER DEFAULT 0\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\\r
+ LocalIdentityID INTEGER,\\r
+ Day DATE,\\r
+ InsertIndex INTEGER\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\\r
+ LocalIdentityID INTEGER,\\r
+ Day DATE,\\r
+ InsertIndex INTEGER\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\\r
+ IdentityID INTEGER,\\r
+ Day DATE,\\r
+ RequestIndex INTEGER,\\r
+ Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\\r
+ UUID TEXT UNIQUE,\\r
+ LocalIdentityID INTEGER,\\r
+ Day DATE,\\r
+ InsertIndex INTEGER,\\r
+ Type TEXT,\\r
+ MimeType TEXT,\\r
+ PuzzleData TEXT,\\r
+ PuzzleSolution TEXT,\\r
+ FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
+ IdentityID INTEGER PRIMARY KEY,\\r
+ PublicKey TEXT UNIQUE,\\r
+ Name TEXT,\\r
+ SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
+ PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
+ PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
+ FreesiteEdition INTEGER,\\r
+ DateAdded DATETIME,\\r
+ LastSeen DATETIME,\\r
+ LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ AddedMethod TEXT,\\r
+ Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false',\\r
+ PurgeDate DATETIME\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\\r
+ IdentityID INTEGER,\\r
+ Day DATE,\\r
+ RequestIndex INTEGER,\\r
+ Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\\r
+ IdentityID INTEGER,\\r
+ Day DATE,\\r
+ RequestIndex INTEGER,\\r
+ Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\\r
+ UUID TEXT UNIQUE,\\r
+ Type TEXT,\\r
+ MimeType TEXT,\\r
+ PuzzleData TEXT\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\\r
+ LocalIdentityID INTEGER,\\r
+ Day DATE,\\r
+ UUID TEXT UNIQUE,\\r
+ Solution TEXT,\\r
+ Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityTrust(\\r
+ LocalIdentityID INTEGER,\\r
+ IdentityID INTEGER,\\r
+ LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ MessageTrustComment TEXT,\\r
+ LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
+ TrustListTrustComment TEXT\\r
+ );");\r
+\r
+ db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxIdentityTrust_IDs ON tblIdentityTrust(LocalIdentityID,IdentityID);");\r
+\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOnIdentityTrust AFTER INSERT ON tblIdentityTrust \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ UPDATE tblIdentity SET LocalMessageTrust=(SELECT MAX(LocalMessageTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID), LocalTrustListTrust=(SELECT MAX(LocalTrustListTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID) WHERE tblIdentity.IdentityID=new.IdentityID; \\r
+ END;");\r
+\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOnIdentityTrust AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentityTrust \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ UPDATE tblIdentity SET LocalMessageTrust=(SELECT MAX(LocalMessageTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID), LocalTrustListTrust=(SELECT MAX(LocalTrustListTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID) WHERE tblIdentity.IdentityID=new.IdentityID; \\r
+ END;");\r
+\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOnIdentityTrust AFTER DELETE ON tblIdentityTrust \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ UPDATE tblIdentity SET LocalMessageTrust=(SELECT MAX(LocalMessageTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=old.IdentityID GROUP BY tblIdentityTrust.IdentityID), LocalTrustListTrust=(SELECT MAX(LocalTrustListTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=old.IdentityID GROUP BY tblIdentityTrust.IdentityID) WHERE tblIdentity.IdentityID=old.IdentityID; \\r
+ END;");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\\r
+ IdentityID INTEGER,\\r
+ TargetIdentityID INTEGER,\\r
+ MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\\r
+ TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100),\\r
+ MessageTrustComment TEXT,\\r
+ TrustListTrustComment TEXT\\r
+ );");\r
+\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_IdentityID ON tblPeerTrust (IdentityID);");\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_TargetIdentityID ON tblPeerTrust (TargetIdentityID);");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\\r
+ BoardID INTEGER PRIMARY KEY,\\r
+ BoardName TEXT UNIQUE,\\r
+ BoardDescription TEXT,\\r
+ DateAdded DATETIME,\\r
+ SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true',\\r
+ AddedMethod TEXT\\r
+ );");\r
+\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('fms','Freenet Message System','2007-12-01 12:00:00','Initial Board');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00','Initial Board');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('public','Public discussion','2007-12-01 12:00:00','Initial Board');");\r
+ db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('test','Test board','2007-12-01 12:00:00','Initial Board');");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\\r
+ MessageID INTEGER PRIMARY KEY,\\r
+ IdentityID INTEGER,\\r
+ FromName TEXT,\\r
+ MessageDate DATE,\\r
+ MessageTime TIME,\\r
+ Subject TEXT,\\r
+ MessageUUID TEXT UNIQUE,\\r
+ ReplyBoardID INTEGER,\\r
+ Body TEXT,\\r
+ MessageIndex INTEGER\\r
+ );");\r
+\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxMessage_IdentityID ON tblMessage (IdentityID);");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\\r
+ MessageID INTEGER,\\r
+ ReplyToMessageUUID TEXT,\\r
+ ReplyOrder INTEGER\\r
+ );");\r
+\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxMessageReplyTo_MessageID ON tblMessageReplyTo (MessageID);");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\\r
+ MessageID INTEGER,\\r
+ BoardID INTEGER\\r
+ );");\r
+\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_MessageID ON tblMessageBoard (MessageID);");\r
+ db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_BoardID ON tblMessageBoard (BoardID);");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\\r
+ IdentityID INTEGER,\\r
+ Day DATE,\\r
+ RequestIndex INTEGER,\\r
+ Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\\r
+ IdentityID INTEGER,\\r
+ Day DATE,\\r
+ RequestIndex INTEGER,\\r
+ FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\\r
+ Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+\r
+ db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\\r
+ LocalIdentityID INTEGER,\\r
+ Day DATE,\\r
+ InsertIndex INTEGER,\\r
+ MessageUUID TEXT UNIQUE,\\r
+ MessageXML TEXT,\\r
+ Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false',\\r
+ SendDate DATETIME\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\\r
+ FileInsertID INTEGER PRIMARY KEY,\\r
+ MessageUUID TEXT,\\r
+ FileName TEXT,\\r
+ Key TEXT,\\r
+ Size INTEGER,\\r
+ MimeType TEXT,\\r
+ Data BLOB\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\\r
+ LocalIdentityID INTEGER,\\r
+ Day DATE,\\r
+ InsertIndex INTEGER,\\r
+ Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\\r
+ BoardID INTEGER UNIQUE,\\r
+ ModifyLocalMessageTrust INTEGER,\\r
+ ModifyLocalTrustListTrust INTEGER\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\\r
+ LocalIdentityID INTEGER,\\r
+ Day DATE,\\r
+ InsertIndex INTEGER,\\r
+ Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
+ );");\r
+\r
+ db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\\r
+ IdentityID INTEGER,\\r
+ Day DATE,\\r
+ RequestIndex INTEGER,\\r
+ Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
+ );"); \r
+\r
+ // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed\r
+ db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\\r
+ LocalIdentityID INTEGER,\\r
+ Date DATETIME\\r
+ );");\r
+\r
+ // A temporary table that will hold a local identity id of the last identity who was loaded in the trust list page\r
+ db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpLocalIdentityPeerTrustPage(\\r
+ LocalIdentityID INTEGER\\r
+ );");\r
+\r
+ // low / high / message count for each board\r
+ db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \\r
+ SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \\r
+ FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \\r
+ WHERE MessageID>=0 OR MessageID IS NULL \\r
+ GROUP BY tblBoard.BoardID;");\r
+\r
+ // calculates peer trust\r
+ // do the (MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1)/100.0 - so if MessageTrust or TrustListTrust is NULL, the calc will be NULL and it won't be included at all in the average\r
+ // need the +1 so that when the values are 0 the result is not 0\r
+ db->Execute("DROP VIEW IF EXISTS vwCalculatedPeerTrust;");\r
+ db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \\r
+ SELECT TargetIdentityID, \\r
+ ROUND(SUM(MessageTrust*(LocalTrustListTrust/100.0))/SUM(((MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1))/100.0),0) AS 'PeerMessageTrust', \\r
+ ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(((TrustListTrust+1)*LocalTrustListTrust/(TrustListTrust+1))/100.0),0) AS 'PeerTrustListTrust' \\r
+ FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \\r
+ WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \\r
+ AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \\r
+ GROUP BY TargetIdentityID;");\r
+\r
+ db->Execute("CREATE VIEW IF NOT EXISTS vwIdentityStats AS \\r
+ SELECT tblIdentity.IdentityID, COUNT(tblMessage.MessageID) AS MessageCount, MIN(tblMessage.MessageDate) AS FirstMessageDate, MAX(tblMessage.MessageDate) AS LastMessageDate \\r
+ FROM tblIdentity LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID \\r
+ GROUP BY tblIdentity.IdentityID;");\r
+\r
+ /*\r
+ These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed\r
+ All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class\r
+ */\r
+ // drop existing triggers\r
+ db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");\r
+ db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");\r
+ db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");\r
+ db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");\r
+/*\r
+ // update PeerTrustLevel when deleting a record from tblPeerTrust\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID) WHERE IdentityID=old.TargetIdentityID;\\r
+ END;");\r
+\r
+ // update PeerTrustLevel when inserting a record into tblPeerTrust\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID) WHERE IdentityID=new.TargetIdentityID;\\r
+ END;");\r
+\r
+ // update PeerTrustLevel when updating a record in tblPeerTrust\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID) WHERE IdentityID=old.TargetIdentityID;\\r
+ UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID) WHERE IdentityID=new.TargetIdentityID;\\r
+ END;");\r
+\r
+ // recalculate all Peer TrustLevels when updating Local TrustLevels on tblIdentity - doesn't really need to be all, but rather all identities the updated identity has a trust level for. It's easier to update everyone for now.\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\\r
+ END;");\r
+*/\r
+\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\\r
+ DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\\r
+ END;");\r
+\r
+ db->Execute("DROP TRIGGER IF EXISTS trgDeleteIdentity;");\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\\r
+ DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\\r
+ DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\\r
+ DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\\r
+ DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\\r
+ DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\\r
+ DELETE FROM tblIdentityTrust WHERE IdentityID=old.IdentityID;\\r
+ END;");\r
+\r
+ db->Execute("DROP TRIGGER IF EXISTS trgDeleteLocalIdentity;");\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
+ DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
+ DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
+ DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
+ DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
+ DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
+ DELETE FROM tblIdentityTrust WHERE LocalIdentityID=old.LocalIdentityID;\\r
+ END;");\r
+\r
+ db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \\r
+ FOR EACH ROW \\r
+ BEGIN \\r
+ DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\\r
+ END;");\r
+\r
+ // delete introduction puzzles that were half-way inserted\r
+ db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");\r
+\r
+ // delete stale introduction puzzles (2 or more days old)\r
+ date-=Poco::Timespan(2,0,0,0,0);\r
+ db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+ db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"';");\r
+\r
+ date=Poco::Timestamp();\r
+ // insert SomeDude's public key\r
+ db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,LocalTrustListTrust,AddedMethod) VALUES('SSK@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw,iXez4j3qCpd596TxXiJgZyTq9o-CElEuJxm~jNNZAuA,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"',50,'Initial Identity');");\r
+ // insert Shadow Panther's public key - haven't seen in a while - disabling for now\r
+ //db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+ // insert garfield's public key\r
+ db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+ // insert alek's public key\r
+ db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@lTjeI6V0lQsktXqaqJ6Iwk4TdsHduQI54rdUpHfhGbg,0oTYfrxxx8OmdU1~60gqpf3781qzEicM4Sz97mJsBM4,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+ // insert Luke771's public key\r
+ db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@mdXK~ZVlfTZhF1SLBrvZ--i0vOsOpa~w9wv~~psQ-04,gXonsXKc7aexKSO8Gt8Fwre4Qgmmbt2WueO7VzxNKkk,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+ // insert falafel's public key\r
+ db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@IxVqeqM0LyYdTmYAf5z49SJZUxr7NtQkOqVYG0hvITw,RM2wnMn5zAufCMt5upkkgq25B1elfBAxc7htapIWg1c,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+ // insert cptn_insano's public key\r
+ db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@bloE1LJ~qzSYUkU2nt7sB9kq060D4HTQC66pk5Q8NpA,DOOASUnp0kj6tOdhZJ-h5Tk7Ka50FSrUgsH7tCG1usU,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+ // insert Flink's public key\r
+ db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@q2TtkNBOuuniyJ56~8NSopCs3ttwe5KlB31ugZtWmXA,6~PzIupS8YK7L6oFNpXGKJmHT2kBMDfwTg73nHdNur8,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+ // insert Kane's public key\r
+ db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@Ofm~yZivDJ5Z2fSzZbMiLEUUQaIc0KHRdZMBTaPLO6I,WLm4s4hNbOOurJ6ijfOq4odz7-dN7uTUvYxJRwWnlMI,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+ // inserts boardstat's public key\r
+ db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@aYWBb6zo2AM13XCNhsmmRKMANEx6PG~C15CWjdZziKA,X1pAG4EIqR1gAiyGFVZ1iiw-uTlh460~rFACJ7ZHQXk,AQACAAE/','"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
+\r
+ // TODO remove sometime after 0.1.17\r
+ FixCapitalBoardNames();\r
+\r
+ // run analyze - may speed up some queries\r
+ db->Execute("ANALYZE;");\r
+\r
+}\r
--- /dev/null
+#include "../include/fmsapp.h"\r
+#include "../include/global.h"\r
+#include "../include/dbsetup.h"\r
+#include "../include/optionssetup.h"\r
+#include "../include/option.h"\r
+#include "../include/stringfunctions.h"\r
+#include "../include/http/httpthread.h"\r
+#include "../include/nntp/nntplistener.h"\r
+#include "../include/dbmaintenancethread.h"\r
+#include "../include/freenet/freenetmasterthread.h"\r
+#include "../include/threadwrapper/threadedexecutor.h"\r
+\r
+#include <Poco/Util/HelpFormatter.h>\r
+#include <Poco/FileChannel.h>\r
+#include <Poco/FormattingChannel.h>\r
+#include <Poco/PatternFormatter.h>\r
+#include <iostream>\r
+\r
+#ifdef _WIN32\r
+ #include <direct.h>\r
+#else\r
+ #include <unistd.h>\r
+#endif\r
+\r
+//debug\r
+#include <Poco/ScopedLock.h>\r
+#include <Poco/Runnable.h>\r
+#include <Poco/Thread.h>\r
+#include <Poco/ThreadPool.h>\r
+#include "../include/threadwrapper/cancelablerunnable.h"\r
+#include "../include/threadwrapper/cancelablethread.h"\r
+\r
+Poco::FastMutex m1;\r
+class TestRunner:public CancelableRunnable\r
+{\r
+public:\r
+ void run()\r
+ {\r
+ do\r
+ {\r
+\r
+ }while(!IsCancelled());\r
+ }\r
+};\r
+\r
+FMSApp::FMSApp():m_displayhelp(false)\r
+{\r
+\r
+}\r
+\r
+void FMSApp::defineOptions(Poco::Util::OptionSet &options)\r
+{\r
+ ServerApplication::defineOptions(options);\r
+\r
+ // add command line options here\r
+ options.addOption(Poco::Util::Option("help","?","display help for command line arguments",false).repeatable(false).callback(Poco::Util::OptionCallback<FMSApp>(this,&FMSApp::handleHelp)));\r
+}\r
+\r
+void FMSApp::displayHelp()\r
+{\r
+ Poco::Util::HelpFormatter helpFormatter(options());\r
+ helpFormatter.setCommand(commandName());\r
+ helpFormatter.setUsage("OPTIONS");\r
+ helpFormatter.setHeader("The Freenet Message System.");\r
+ helpFormatter.format(std::cout);\r
+}\r
+\r
+void FMSApp::handleHelp(const std::string &name, const std::string &value)\r
+{\r
+ m_displayhelp=true;\r
+ displayHelp();\r
+ stopOptionsProcessing();\r
+}\r
+\r
+void FMSApp::initialize(Poco::Util::Application &self)\r
+{\r
+ ServerApplication::initialize(self);\r
+\r
+ // set working directory to program directory\r
+ int rval=chdir(config().getString("application.dir").c_str());\r
+\r
+ SetupDB();\r
+ SetupDefaultOptions();\r
+ initializeLogger();\r
+ config().setString("application.logger","logfile");\r
+}\r
+\r
+void FMSApp::initializeLogger()\r
+{\r
+ int initiallevel=Poco::Message::PRIO_TRACE;\r
+\r
+ std::string tempval="";\r
+ if(Option::Instance()->Get("LogLevel",tempval))\r
+ {\r
+ StringFunctions::Convert(tempval,initiallevel);\r
+ }\r
+\r
+ Poco::AutoPtr<Poco::FormattingChannel> formatter=new Poco::FormattingChannel(new Poco::PatternFormatter("%Y-%m-%d %H:%M:%S | %p | %t"));\r
+ Poco::AutoPtr<Poco::FileChannel> fc=new Poco::FileChannel("fms.log");\r
+ fc->setProperty("rotation","daily"); // rotate log file daily\r
+ fc->setProperty("times","utc"); // utc date/times for log entries\r
+ fc->setProperty("archive","timestamp"); // add timestamp to old logs\r
+ fc->setProperty("purgeCount","30"); // purge old logs after 30 logs have accumulated\r
+ fc->setProperty("compress","true"); // gz compress old log files\r
+ formatter->setChannel(fc);\r
+ \r
+ setLogger(Poco::Logger::create("logfile",formatter,initiallevel));\r
+}\r
+\r
+int FMSApp::main(const std::vector<std::string> &args)\r
+{\r
+\r
+ if(m_displayhelp==false)\r
+ {\r
+ logger().information("FMS startup v"FMS_VERSION);\r
+\r
+ StartThreads();\r
+\r
+ waitForTerminationRequest();\r
+\r
+ m_threads.Cancel();\r
+ m_threads.Join();\r
+\r
+ logger().information("FMS shutdown");\r
+ }\r
+\r
+ return FMSApp::EXIT_OK;\r
+}\r
+\r
+void FMSApp::StartThreads()\r
+{\r
+ std::string tempval="";\r
+\r
+ // always start the DB maintenance thread\r
+ m_threads.Start(new DBMaintenanceThread());\r
+\r
+ Option::Instance()->Get("StartHTTP",tempval);\r
+ if(tempval=="true")\r
+ {\r
+ m_threads.Start(new HTTPThread());\r
+ }\r
+\r
+ tempval="";\r
+ Option::Instance()->Get("StartNNTP",tempval);\r
+ if(tempval=="true")\r
+ {\r
+ m_threads.Start(new NNTPListener());\r
+ }\r
+\r
+ tempval="";\r
+ Option::Instance()->Get("StartFreenetUpdater",tempval);\r
+ if(tempval=="true")\r
+ {\r
+ m_threads.Start(new FreenetMasterThread());\r
+ }\r
+\r
+}\r
+++ /dev/null
-#include "../include/fmsdaemon.h"\r
-\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <sys/types.h>\r
-#ifndef _WIN32\r
- #include <unistd.h>\r
- #include <sys/stat.h>\r
-#endif\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-/*\r
- modified from http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize\r
-*/\r
-void Daemonize()\r
-{\r
-#ifndef _WIN32\r
- pid_t pid, sid;\r
-\r
- /* already a daemon */\r
- if ( getppid() == 1 ) return;\r
-\r
- /* Fork off the parent process */\r
- pid = fork();\r
- if (pid < 0) {\r
- exit(EXIT_FAILURE);\r
- }\r
- /* If we got a good PID, then we can exit the parent process. */\r
- if (pid > 0) {\r
- exit(EXIT_SUCCESS);\r
- }\r
-\r
- /* At this point we are executing as the child process */\r
-\r
- /* Change the file mode mask */\r
- umask(0);\r
-\r
- /* Create a new SID for the child process */\r
- sid = setsid();\r
- if (sid < 0) {\r
- exit(EXIT_FAILURE);\r
- }\r
-\r
- /* Redirect standard files to /dev/null */\r
- freopen( "/dev/null", "r", stdin);\r
- freopen( "/dev/null", "w", stdout);\r
- freopen( "/dev/null", "w", stderr);\r
-#endif\r
-}\r
+++ /dev/null
-#include "../include/fmsservice.h"\r
-#include "../include/global.h"\r
-#include "../include/logfile.h"\r
-\r
-#include <string>\r
-\r
-#ifdef _WIN32\r
-\r
-#include <direct.h>\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-SERVICE_STATUS ServiceStatus; \r
-SERVICE_STATUS_HANDLE hStatus; \r
-\r
-void ControlHandler(DWORD request) \r
-{ \r
- switch(request) \r
- { \r
- case SERVICE_CONTROL_STOP: \r
- case SERVICE_CONTROL_SHUTDOWN: \r
- ServiceStatus.dwWin32ExitCode = 0; \r
- ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; \r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ControlHandler service got shutdown request");\r
- wantshutdown=true;\r
- break; \r
- \r
- default:\r
- break;\r
- } \r
- \r
- /* Report current status */\r
- SetServiceStatus (hStatus, &ServiceStatus);\r
- \r
- return; \r
-}\r
-\r
-BOOL ServiceInstall()\r
-{\r
- SC_HANDLE hSCM, hService;\r
- char szFilePath[FILENAME_MAX], szKey[256];\r
- HKEY hKey;\r
- DWORD dwData;\r
- \r
- hSCM = OpenSCManager(NULL, /* local machine */\r
- NULL, /* ServicesActive database */\r
- SC_MANAGER_ALL_ACCESS); /* full access */\r
-\r
- if (!hSCM) return FALSE;\r
-\r
- GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));\r
- std::string commandline(szFilePath);\r
- commandline+=" -s";\r
-\r
- hService = CreateService(hSCM,\r
- FMS_SERVICE_NAME,\r
- FMS_SERVICE_NAME,\r
- SERVICE_ALL_ACCESS,\r
- SERVICE_WIN32_OWN_PROCESS,\r
- SERVICE_AUTO_START, /* start condition */\r
- SERVICE_ERROR_NORMAL,\r
- commandline.c_str(),\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL);\r
-\r
- if (!hService) {\r
- CloseServiceHandle(hSCM);\r
- return FALSE;\r
- }\r
-\r
- hKey = NULL;\r
- strcpy(szKey, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");\r
- strcat(szKey, FMS_SERVICE_NAME);\r
- if (RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey) != ERROR_SUCCESS) {\r
- CloseServiceHandle(hService);\r
- CloseServiceHandle(hSCM);\r
- return FALSE;\r
- }\r
-\r
- RegSetValueEx(hKey,\r
- "EventMessageFile",\r
- 0,\r
- REG_EXPAND_SZ, \r
- (CONST BYTE*)szFilePath,\r
- (int) strlen(szFilePath) + 1); \r
-\r
- dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;\r
- RegSetValueEx(hKey,\r
- "TypesSupported",\r
- 0,\r
- REG_DWORD,\r
- (CONST BYTE*)&dwData,\r
- sizeof(DWORD));\r
- RegCloseKey(hKey);\r
-\r
- CloseServiceHandle(hService);\r
- CloseServiceHandle(hSCM);\r
-\r
- return TRUE;\r
-}\r
-\r
-BOOL ServiceIsInstalled()\r
-{\r
- BOOL bResult;\r
- SC_HANDLE hSCM, hService;\r
- \r
- hSCM = OpenSCManager(NULL, /* local machine */\r
- NULL, /* ServicesActive database */\r
- SC_MANAGER_ALL_ACCESS); /* full access */\r
-\r
- bResult = FALSE;\r
-\r
- if (hSCM) {\r
- hService = OpenService(hSCM,\r
- FMS_SERVICE_NAME,\r
- SERVICE_QUERY_CONFIG);\r
-\r
- if (hService) {\r
- bResult = TRUE;\r
- CloseServiceHandle(hService);\r
- }\r
- CloseServiceHandle(hSCM);\r
- }\r
-\r
- return bResult;\r
-}\r
-\r
-void ServiceMain(int argc, char** argv) \r
-{ \r
- char szDocumentRoot[MAX_PATH];\r
-\r
- ServiceStatus.dwServiceType = SERVICE_WIN32; \r
- ServiceStatus.dwCurrentState = SERVICE_START_PENDING; \r
- ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;\r
- ServiceStatus.dwWin32ExitCode = 0; \r
- ServiceStatus.dwServiceSpecificExitCode = 0; \r
- ServiceStatus.dwCheckPoint = 0; \r
- ServiceStatus.dwWaitHint = 0; \r
-\r
- hStatus = RegisterServiceCtrlHandler(FMS_SERVICE_NAME, (LPHANDLER_FUNCTION)ControlHandler);\r
-\r
- if (hStatus == (SERVICE_STATUS_HANDLE)0) { \r
- /* Registering Control Handler failed */\r
- return; \r
- }\r
-\r
- /* Initialize Service */\r
-\r
- /*\r
- Construct default paths & filenames and make sure we serve documents from the folder containing the executable.\r
- If left without a default value, we will be serving from C:\WINDOWS\SYSTEM32 (we start there as a service)!\r
- */\r
- GetModuleFileName(NULL, szDocumentRoot, MAX_PATH);\r
- std::string path(szDocumentRoot);\r
- std::string::size_type slashpos=path.rfind("\\");\r
- if(slashpos==std::string::npos)\r
- {\r
- slashpos=path.rfind("/");\r
- }\r
- if(slashpos!=std::string::npos)\r
- {\r
- path.erase(slashpos);\r
- }\r
- chdir(path.c_str());\r
-\r
- /* We report the running status to SCM. */\r
- ServiceStatus.dwCurrentState = SERVICE_RUNNING;\r
- SetServiceStatus (hStatus, &ServiceStatus);\r
-\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ServiceMain starting service");\r
-\r
- MainFunction();\r
-\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ServiceMain stopping service");\r
-\r
- ServiceStatus.dwCurrentState=SERVICE_STOPPED;\r
- SetServiceStatus(hStatus,&ServiceStatus);\r
-\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ServiceMain returning");\r
-\r
- return; \r
-}\r
-\r
-BOOL ServiceStart()\r
-{\r
- SERVICE_TABLE_ENTRY ServiceTable[2];\r
-\r
- ServiceTable[0].lpServiceName = FMS_SERVICE_NAME;\r
- ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;\r
-\r
- ServiceTable[1].lpServiceName = NULL;\r
- ServiceTable[1].lpServiceProc = NULL;\r
-\r
- /* Start the control dispatcher thread for our service */\r
- return StartServiceCtrlDispatcher(ServiceTable);\r
-}\r
-\r
-BOOL ServiceUninstall()\r
-{\r
- SC_HANDLE hSCM, hService;\r
- BOOL bResult;\r
- \r
- hSCM = OpenSCManager(NULL, /* local machine */\r
- NULL, /* ServicesActive database */\r
- SC_MANAGER_ALL_ACCESS); /* full access */\r
-\r
- if (!hSCM) return 0;\r
-\r
- bResult = FALSE;\r
-\r
- hService = OpenService(hSCM,\r
- FMS_SERVICE_NAME,\r
- DELETE);\r
-\r
- if (hService) {\r
- if (DeleteService(hService)) bResult = TRUE;\r
- CloseServiceHandle(hService);\r
- }\r
-\r
- CloseServiceHandle(hSCM);\r
-\r
- return bResult;\r
-}\r
-\r
-#endif // _WIN32\r
#include "../../include/freenet/boardlistinserter.h"\r
#include "../../include/freenet/boardlistxml.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timespan.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
// only do 1 insert at a time\r
if(m_inserting.size()==0)\r
{\r
- DateTime today;\r
- DateTime daysback;\r
- \r
- today.SetToGMTime();\r
- daysback.SetToGMTime();\r
+ Poco::DateTime today;\r
+ Poco::DateTime daysback;\r
\r
- // 20 days\r
- daysback.Add(0,0,0,-20);\r
+ // 20 days back\r
+ daysback-=Poco::Timespan(20,0,0,0,0);\r
\r
// get identities who posted messages to boards in the past 20 days\r
SQLite3DB::Statement st=m_db->Prepare("SELECT tblLocalIdentity.LocalIdentityID FROM tblLocalIdentity INNER JOIN tblMessageInserts ON tblLocalIdentity.LocalIdentityID=tblMessageInserts.LocalIdentityID WHERE tblLocalIdentity.PublishBoardList='true' AND (tblLocalIdentity.LastInsertedBoardList<? OR tblLocalIdentity.LastInsertedBoardList IS NULL) AND tblMessageInserts.Day>=? GROUP BY tblLocalIdentity.LocalIdentityID;");\r
- st.Bind(0,today.Format("%Y-%m-%d"));\r
- st.Bind(1,daysback.Format("%Y-%m-%d"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(today,"%Y-%m-%d"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(daysback,"%Y-%m-%d"));\r
st.Step();\r
\r
if(st.RowReturned())\r
\r
const bool BoardListInserter::HandlePutSuccessful(FCPMessage &message)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
std::vector<std::string> idparts;\r
long localidentityid;\r
long index;\r
st.Bind(2,index);\r
st.Step();\r
\r
- now.SetToGMTime();\r
st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedBoardList=? WHERE LocalIdentityID=?;");\r
- st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
st.Bind(1,localidentityid);\r
st.Step();\r
\r
RemoveFromInsertList(localidentityid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"BoardListInserter::HandlePutSuccessful successfully inserted BoardList.");\r
+ m_log->debug("BoardListInserter::HandlePutSuccessful successfully inserted BoardList.");\r
\r
return true;\r
}\r
\r
const bool BoardListInserter::StartInsert(const long &localidentityid)\r
{\r
- DateTime daysback;\r
- DateTime now;\r
+ Poco::DateTime daysback;\r
+ Poco::DateTime now;\r
BoardListXML xml;\r
FCPMessage message;\r
std::string data;\r
std::string indexstr="";\r
std::string localidentityidstr;\r
\r
- now.SetToGMTime();\r
- daysback.SetToGMTime();\r
- daysback.Add(0,0,0,-20);\r
+ // 20 days back\r
+ daysback-=Poco::Timespan(20,0,0,0,0);\r
\r
// get boards\r
SQLite3DB::Statement st=m_db->Prepare("SELECT BoardName,BoardDescription FROM tblBoard INNER JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID INNER JOIN tblMessage ON tblMessageBoard.MessageID=tblMessage.MessageID INNER JOIN tblMessageInserts ON tblMessage.MessageUUID=tblMessageInserts.MessageUUID WHERE tblMessageInserts.LocalIdentityID=? AND tblMessageInserts.Day>=? GROUP BY tblBoard.BoardID;");\r
st.Bind(0,localidentityid);\r
- st.Bind(1,daysback.Format("%Y-%m-%d"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(daysback,"%Y-%m-%d"));\r
st.Step();\r
\r
while(st.RowReturned())\r
index=0;\r
st=m_db->Prepare("SELECT MAX(InsertIndex) FROM tblBoardListInserts WHERE LocalIdentityID=? AND Day=?;");\r
st.Bind(0,localidentityid);\r
- st.Bind(1,now.Format("%Y-%m-%d"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
st.Step();\r
if(st.RowReturned())\r
{\r
StringFunctions::Convert(localidentityid,localidentityidstr);\r
\r
message.SetName("ClientPut");\r
- message["URI"]=privatekey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|BoardList|"+indexstr+".xml";\r
+ message["URI"]=privatekey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|BoardList|"+indexstr+".xml";\r
message["Identifier"]=m_fcpuniquename+"|"+localidentityidstr+"|"+indexstr+"|"+message["URI"];\r
message["UploadFrom"]="direct";\r
message["DataLength"]=datasizestr;\r
#include "../../include/freenet/boardlistrequester.h"\r
#include "../../include/freenet/boardlistxml.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
\r
const bool BoardListRequester::HandleAllData(FCPMessage &message)\r
{ \r
- DateTime now;\r
+ Poco::DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
long datalength;\r
long index;\r
std::string identityname="";\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(message["DataLength"],datalength);\r
StringFunctions::Convert(idparts[1],identityid);\r
{\r
ins.Bind(0,xml.GetName(i));\r
ins.Bind(1,xml.GetDescription(i));\r
- ins.Bind(2,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ ins.Bind(2,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
if(m_savemessagesfromnewboards)\r
{\r
ins.Bind(3,"true");\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"BoardListRequester::HandleAllData parsed BoardList XML file : "+message["Identifier"]);\r
+ m_log->debug("BoardListRequester::HandleAllData parsed BoardList XML file : "+message["Identifier"]);\r
}\r
else\r
{\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"BoardListRequester::HandleAllData error parsing BoardList XML file : "+message["Identifier"]);\r
+ m_log->error("BoardListRequester::HandleAllData error parsing BoardList XML file : "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
\r
const bool BoardListRequester::HandleGetFailed(FCPMessage &message)\r
{\r
- DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
long identityid;\r
long index;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(idparts[1],identityid);\r
StringFunctions::Convert(idparts[2],index); \r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"BoardListRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
+ m_log->error("BoardListRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
if(m_maxrequests<0)\r
{\r
m_maxrequests=0;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxBoardListRequests is currently set at "+tempval+". It must be 0 or greater.");\r
+ m_log->error("Option MaxBoardListRequests is currently set at "+tempval+". It must be 0 or greater.");\r
}\r
if(m_maxrequests>100)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxBoardListRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MaxBoardListRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
\r
Option::Instance()->Get("SaveMessagesFromNewBoards",tempval);\r
void BoardListRequester::PopulateIDList()\r
{\r
int id;\r
- DateTime today;\r
- today.SetToGMTime();\r
+ Poco::DateTime today;\r
\r
SQLite3DB::Statement st;\r
\r
if(m_localtrustoverrides==false)\r
{\r
- st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+today.Format("%Y-%m-%d")+"' AND (LocalMessageTrust IS NULL OR LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust')) AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')) AND PublishBoardList='true' ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
+ st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+Poco::DateTimeFormatter::format(today,"%Y-%m-%d")+"' AND (LocalMessageTrust IS NULL OR LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust')) AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')) AND PublishBoardList='true' ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
}\r
else\r
{\r
- st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+today.Format("%Y-%m-%d")+"' AND (LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust') OR (LocalMessageTrust IS NULL AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')))) AND PublishBoardList='true' ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
+ st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+Poco::DateTimeFormatter::format(today,"%Y-%m-%d")+"' AND (LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust') OR (LocalMessageTrust IS NULL AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')))) AND PublishBoardList='true' ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
}\r
st.Step();\r
\r
\r
void BoardListRequester::StartRequest(const long &identityid)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
FCPMessage message;\r
std::string publickey;\r
std::string indexstr;\r
{\r
st.ResultText(0,publickey);\r
\r
- now.SetToGMTime();\r
-\r
SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblBoardListRequests WHERE Day=? AND IdentityID=?;");\r
- st2.Bind(0,now.Format("%Y-%m-%d"));\r
+ st2.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
st2.Bind(1,identityid);\r
st2.Step();\r
\r
StringFunctions::Convert(identityid,identityidstr);\r
\r
message.SetName("ClientGet");\r
- message["URI"]=publickey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|BoardList|"+indexstr+".xml";\r
+ message["URI"]=publickey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|BoardList|"+indexstr+".xml";\r
message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|"+message["URI"];\r
message["ReturnType"]="direct";\r
message["MaxSize"]="100000"; // 100 KB\r
\r
std::string BoardListXML::GetXML()\r
{\r
- TiXmlDocument td;\r
- TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
- TiXmlElement *tid;\r
- TiXmlPrinter tp;\r
-\r
- td.LinkEndChild(tdec);\r
- tid=new TiXmlElement("BoardList");\r
- td.LinkEndChild(tid);\r
+ Poco::AutoPtr<Poco::XML::Document> doc=new Poco::XML::Document;\r
+ //TiXmlDocument td;\r
+ //TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
+ Poco::XML::Element *root=doc->createElement("BoardList");\r
+ //TiXmlElement *tid;\r
+ //TiXmlPrinter tp;\r
+\r
+ doc->appendChild(root);\r
+ //td.LinkEndChild(tdec);\r
+ //tid=new TiXmlElement("BoardList");\r
+ //td.LinkEndChild(tid);\r
\r
for(std::vector<board>::iterator i=m_boards.begin(); i!=m_boards.end(); i++)\r
{\r
std::string boardname=(*i).m_name;\r
StringFunctions::LowerCase(boardname,boardname);\r
- TiXmlElement *tr=new TiXmlElement("Board");\r
- tid->LinkEndChild(tr);\r
- tr->LinkEndChild(XMLCreateCDATAElement("Name",boardname));\r
- tr->LinkEndChild(XMLCreateCDATAElement("Description",(*i).m_description));\r
+ Poco::XML::Element *tr=doc->createElement("Board");\r
+ //TiXmlElement *tr=new TiXmlElement("Board");\r
+ root->appendChild(tr);\r
+ //tid->LinkEndChild(tr);\r
+ tr->appendChild(XMLCreateCDATAElement(doc,"Name",boardname));\r
+ //tr->LinkEndChild(XMLCreateCDATAElement("Name",boardname));\r
+ tr->appendChild(XMLCreateCDATAElement(doc,"Description",(*i).m_description));\r
+ //tr->LinkEndChild(XMLCreateCDATAElement("Description",(*i).m_description));\r
}\r
\r
- td.Accept(&tp);\r
- return std::string(tp.CStr());\r
+ //td.Accept(&tp);\r
+ //return std::string(tp.CStr());\r
+ return GenerateXML(doc);\r
}\r
\r
void BoardListXML::Initialize()\r
\r
const bool BoardListXML::ParseXML(const std::string &xml)\r
{\r
+ bool parsed=false;\r
+ Poco::XML::DOMParser dp;\r
+\r
+ Initialize();\r
+\r
+ try\r
+ {\r
+ Poco::AutoPtr<Poco::XML::Document> doc=dp.parseString(FixCDATA(xml));\r
+ Poco::XML::Element *root=XMLGetFirstChild(doc,"BoardList");\r
+ Poco::XML::Element *boardel=NULL;\r
+\r
+ boardel=XMLGetFirstChild(root,"Board");\r
+ while(boardel)\r
+ {\r
+ std::string name="";\r
+ std::string description="";\r
+\r
+ Poco::XML::Element *txt=XMLGetFirstChild(boardel,"Name");\r
+ if(txt && txt->firstChild())\r
+ {\r
+ name=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ StringFunctions::LowerCase(name,name);\r
+ if(name.size()>40)\r
+ {\r
+ name.erase(40);\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(boardel,"Description");\r
+ if(txt && txt->firstChild())\r
+ {\r
+ description=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+\r
+ if(name!="" && description!="")\r
+ {\r
+ m_boards.push_back(board(name,description));\r
+ }\r
+\r
+ boardel=XMLGetNextSibling(boardel,"Board");\r
+ }\r
+\r
+ parsed=true;\r
+\r
+ }\r
+ catch(...)\r
+ {\r
+ }\r
+\r
+ return parsed;\r
+\r
+ /*\r
std::string name;\r
std::string description;\r
TiXmlDocument td;\r
{\r
return false;\r
}\r
+ */\r
}\r
#include "../../../include/freenet/captcha/easybmp/EasyBMP_Font.h"\r
#include "../../../include/freenet/captcha/easybmp/EasyBMP_Geometry.h"\r
\r
+#include <Poco/TemporaryFile.h>\r
+\r
#include <cstdlib>\r
\r
#ifdef XMEM\r
int bmpheight=50;\r
RGBApixel lettercols[5];\r
std::string puzzlestring;\r
- std::string tempfilename=GenerateRandomString(10);\r
- tempfilename+=".bmp";\r
+ std::string tempfilename="";\r
+ \r
+ tempfilename=Poco::TemporaryFile::tempName();\r
\r
puzzlestring=GenerateRandomString(5);\r
m_solution.clear();\r
\r
RemoveFromInsertList(fileinsertid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"FileInserter::HandlePutFailed failed to insert "+message["Identifier"]);\r
+ m_log->error("FileInserter::HandlePutFailed failed to insert "+message["Identifier"]);\r
\r
return true;\r
\r
#include "../../include/freenet/freenetmasterthread.h"\r
#include "../../include/option.h"\r
-#include "../../include/uuidgenerator.h"\r
#include "../../include/stringfunctions.h"\r
#include "../../include/freenet/unkeyedidcreator.h"\r
#include "../../include/freenet/identityinserter.h"\r
#include "../../include/freenet/trustlistinserter.h"\r
#include "../../include/freenet/trustlistrequester.h"\r
#include "../../include/freenet/messagelistrequester.h"\r
+#include "../../include/freenet/messagelistinserter.h"\r
#include "../../include/freenet/messagerequester.h"\r
#include "../../include/freenet/messageinserter.h"\r
-#include "../../include/freenet/messagelistinserter.h"\r
-#include "../../include/freenet/periodicdbmaintenance.h"\r
#include "../../include/freenet/boardlistinserter.h"\r
#include "../../include/freenet/boardlistrequester.h"\r
#include "../../include/freenet/siteinserter.h"\r
#include "../../include/freenet/fileinserter.h"\r
-#include "../../include/pthreadwrapper/thread.h"\r
+\r
+#include <Poco/UUID.h>\r
+#include <Poco/UUIDGenerator.h>\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timespan.h>\r
+#include <Poco/Thread.h>\r
\r
#include <cstdlib>\r
\r
m_receivednodehello=false;\r
}\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"FreenetMasterThread::FCPConnect trying to connect to node "+m_fcphost);\r
+ m_log->information("FreenetMasterThread::FCPConnect trying to connect to node "+m_fcphost);\r
\r
if(m_fcp.Connect(m_fcphost.c_str(),m_fcpport)==true)\r
{\r
- UUIDGenerator uuid;\r
- std::string clientname="FMSClient-"+uuid.Generate();\r
+ Poco::UUIDGenerator uuidgen;\r
+ Poco::UUID uuid;\r
+\r
+ try\r
+ {\r
+ uuid=uuidgen.createRandom();\r
+ }\r
+ catch(...)\r
+ {\r
+ m_log->fatal("FreenetMasterThread::FCPConnect could not generate UUID");\r
+ }\r
+\r
+ std::string clientname="FMSClient-"+uuid.toString();\r
// send ClientHello message to node\r
m_fcp.SendMessage("ClientHello",2,"Name",clientname.c_str(),"ExpectedVersion","2.0");\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"FreenetMasterThread::FCPConnect connected to node");\r
+ m_log->information("FreenetMasterThread::FCPConnect connected to node");\r
\r
return true;\r
}\r
{\r
info+="\t\t\t\t"+(*mi).first+"="+(*mi).second+"\r\n";\r
}\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"FreenetMasterThread::HandleMessage received unhandled "+message.GetName()+" message. Message content :\r\n"+info);\r
+ m_log->debug("FreenetMasterThread::HandleMessage received unhandled "+message.GetName()+" message. Message content :\r\n"+info);\r
\r
// if unhandled message was alldata - we must retrieve the data\r
if(message.GetName()=="AllData")\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"FreenetMasterThread::HandleMessage received "+message.GetName()+" message before NodeHello");\r
+ m_log->error("FreenetMasterThread::HandleMessage received "+message.GetName()+" message before NodeHello");\r
}\r
\r
return false;\r
m_processors.push_back(obj);\r
}\r
\r
-void FreenetMasterThread::Run()\r
+void FreenetMasterThread::run()\r
{\r
\r
- DateTime lastreceivedmessage;\r
- DateTime lastconnected;\r
- DateTime now;\r
+ Poco::DateTime lastreceivedmessage;\r
+ Poco::DateTime lastconnected;\r
+ Poco::DateTime now;\r
FCPMessage message;\r
bool done=false;\r
\r
- lastconnected.SetToGMTime();\r
- lastconnected.Add(0,-1);\r
+ lastconnected-=Poco::Timespan(0,0,1,0,0);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"FreenetMasterThread::run thread started.");\r
+ m_log->debug("FreenetMasterThread::run thread started.");\r
\r
Setup();\r
\r
if(m_fcp.Connected()==false)\r
{\r
// wait at least 1 minute since last successful connect\r
- now.SetToGMTime();\r
- if(lastconnected<=(now-(1.0/1440.0)))\r
+ now=Poco::Timestamp();\r
+ if(lastconnected<=(now-Poco::Timespan(0,0,1,0,0)))\r
{\r
if(FCPConnect()==false)\r
{\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"FreenetMasterThread::run could not connect to node. Waiting 60 seconds.");\r
+ m_log->error("FreenetMasterThread::run could not connect to node. Waiting 60 seconds.");\r
\r
for(int i=0; i<60 && !IsCancelled(); i++)\r
{\r
- Sleep(1000);\r
+ Poco::Thread::sleep(1000);\r
}\r
}\r
else\r
{\r
- lastreceivedmessage.SetToGMTime();\r
- lastconnected.SetToGMTime();\r
+ lastreceivedmessage=Poco::Timestamp();\r
+ lastconnected=Poco::Timestamp();\r
}\r
}\r
else\r
{\r
- Sleep(1000);\r
+ Poco::Thread::sleep(1000);\r
}\r
}\r
// fcp is connected\r
if(message.GetName()!="")\r
{\r
HandleMessage(message);\r
- lastreceivedmessage.SetToGMTime();\r
+ lastreceivedmessage=Poco::Timestamp();\r
}\r
}\r
\r
}\r
\r
// if we haven't received any messages from the node in 10 minutes, something is wrong\r
- now.SetToGMTime();\r
- if(lastreceivedmessage<(now-(1.0/144.0)))\r
+ now=Poco::Timestamp();\r
+ if(lastreceivedmessage<(now-Poco::Timespan(0,0,10,0,0)))\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"FreenetMasterThread::Run The Freenet node has not responded in 10 minutes. Trying to reconnect.");\r
+ m_log->error("FreenetMasterThread::Run The Freenet node has not responded in 10 minutes. Trying to reconnect.");\r
m_fcp.Disconnect();\r
}\r
\r
if(m_fcp.Connected()==false)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"FreenetMasterThread::Run Disconnected from Freenet node.");\r
+ m_log->information("FreenetMasterThread::Run Disconnected from Freenet node.");\r
}\r
\r
}\r
\r
Shutdown();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"FreenetMasterThread::run thread exiting.");\r
+ m_log->debug("FreenetMasterThread::run thread exiting.");\r
\r
}\r
\r
m_registrables.push_back(new TrustListRequester(&m_fcp));\r
m_registrables.push_back(new MessageListInserter(&m_fcp));\r
m_registrables.push_back(new MessageListRequester(&m_fcp));\r
- m_registrables.push_back(new MessageRequester(&m_fcp));\r
m_registrables.push_back(new MessageInserter(&m_fcp));\r
+ m_registrables.push_back(new MessageRequester(&m_fcp));\r
m_registrables.push_back(new BoardListInserter(&m_fcp));\r
m_registrables.push_back(new BoardListRequester(&m_fcp));\r
m_registrables.push_back(new SiteInserter(&m_fcp));\r
m_registrables.push_back(new FileInserter(&m_fcp));\r
- m_registrables.push_back(new PeriodicDBMaintenance());\r
\r
for(std::vector<IFreenetRegistrable *>::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++)\r
{\r
#include "../../include/stringfunctions.h"\r
#include "../../include/option.h"\r
\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/DateTimeParser.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
\r
void IdentityInserter::CheckForNeededInsert()\r
{\r
- DateTime now;\r
- DateTime date;\r
- now.SetToGMTime();\r
- date.SetToGMTime();\r
+ Poco::DateTime now;\r
+ Poco::DateTime date;\r
+\r
// set date to 1 hour back\r
- date.Add(0,0,-1);\r
+ date-=Poco::Timespan(0,1,0,0,0);\r
\r
// Because of importance of Identity.xml, if we are now at the next day we immediately want to insert identities so change the date back to 12:00 AM so we find all identities not inserted yet today\r
- if(date.GetDay()!=now.GetDay())\r
+ if(date.day()!=now.day())\r
{\r
date=now;\r
- date.SetHour(0);\r
- date.SetMinute(0);\r
- date.SetSecond(0);\r
+ date.assign(date.year(),date.month(),date.day(),0,0,0);\r
}\r
\r
- SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID FROM tblLocalIdentity WHERE PrivateKey IS NOT NULL AND PrivateKey <> '' AND InsertingIdentity='false' AND (LastInsertedIdentity<'"+date.Format("%Y-%m-%d %H:%M:%S")+"' OR LastInsertedIdentity IS NULL) ORDER BY LastInsertedIdentity;");\r
+ SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID FROM tblLocalIdentity WHERE PrivateKey IS NOT NULL AND PrivateKey <> '' AND InsertingIdentity='false' AND (LastInsertedIdentity<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"' OR LastInsertedIdentity IS NULL) ORDER BY LastInsertedIdentity;");\r
\r
if(rs.Empty()==false)\r
{\r
\r
if(message["Identifier"].find("IdentityInserter")==0)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
std::vector<std::string> idparts;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
\r
// no action for URIGenerated\r
{\r
// a little hack here - if we just inserted index yesterday and it is now the next day - we would have inserted todays date not yesterdays as LastInsertedIdentity.\r
// If this is the case, we will skip updating LastInsertedIdentity so that we can insert this identity again for today\r
- DateTime lastdate;\r
- lastdate.Set(idparts[4]);\r
- if(lastdate.GetDay()==now.GetDay())\r
+ Poco::DateTime lastdate;\r
+ int tzdiff=0;\r
+ Poco::DateTimeParser::tryParse("%Y-%m-%d",idparts[4],lastdate,tzdiff);\r
+\r
+ if(lastdate.day()==now.day())\r
{\r
- m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='false', LastInsertedIdentity='"+now.Format("%Y-%m-%d %H:%M:%S")+"' WHERE LocalIdentityID="+idparts[1]+";");\r
+ m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='false', LastInsertedIdentity='"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S")+"' WHERE LocalIdentityID="+idparts[1]+";");\r
}\r
else\r
{\r
m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='false' WHERE LocalIdentityID="+idparts[1]+";");\r
}\r
m_db->Execute("INSERT INTO tblLocalIdentityInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IdentityInserter::HandleMessage inserted Identity xml");\r
+ m_log->debug("IdentityInserter::HandleMessage inserted Identity xml");\r
return true;\r
}\r
\r
if(message.GetName()=="PutFailed")\r
{\r
m_db->Execute("UPDATE tblLocalIdentity SET InsertingIdentity='false' WHERE LocalIdentityID="+idparts[1]+";");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IdentityInserter::HandleMessage failure inserting Identity xml. Code="+message["Code"]+" Description="+message["CodeDescription"]);\r
+ m_log->debug("IdentityInserter::HandleMessage failure inserting Identity xml. Code="+message["Code"]+" Description="+message["CodeDescription"]);\r
\r
// if code 9 (collision), then insert index into inserted table\r
if(message["Code"]=="9")\r
\r
void IdentityInserter::Initialize()\r
{\r
- m_lastchecked.SetToGMTime();\r
+ m_lastchecked=Poco::Timestamp();\r
}\r
\r
void IdentityInserter::Process()\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
\r
- if(m_lastchecked<(now-(1.0/1440.0)))\r
+ if(m_lastchecked<(now-Poco::Timespan(0,0,1,0,0)))\r
{\r
CheckForNeededInsert();\r
m_lastchecked=now;\r
\r
void IdentityInserter::StartInsert(const long localidentityid)\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
std::string idstring;\r
\r
StringFunctions::Convert(localidentityid,idstring);\r
- date.SetToGMTime();\r
\r
SQLite3DB::Recordset rs=m_db->Query("SELECT Name,PrivateKey,SingleUse,PublishTrustList,PublishBoardList,PublishFreesite,FreesiteEdition FROM tblLocalIdentity WHERE LocalIdentityID="+idstring+";");\r
\r
{\r
IdentityXML idxml;\r
FCPMessage mess;\r
- DateTime now;\r
+ Poco::DateTime now;\r
std::string messagebase;\r
std::string data;\r
std::string datasizestr;\r
std::string freesiteedition="";\r
int edition=-1;\r
\r
- now.SetToGMTime();\r
+ now=Poco::Timestamp();\r
\r
- SQLite3DB::Recordset rs2=m_db->Query("SELECT MAX(InsertIndex) FROM tblLocalIdentityInserts WHERE LocalIdentityID="+idstring+" AND Day='"+now.Format("%Y-%m-%d")+"';");\r
+ SQLite3DB::Recordset rs2=m_db->Query("SELECT MAX(InsertIndex) FROM tblLocalIdentityInserts WHERE LocalIdentityID="+idstring+" AND Day='"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"';");\r
if(rs2.Empty()==false)\r
{\r
if(rs2.GetField(0)==NULL)\r
StringFunctions::Convert(data.size(),datasizestr);\r
\r
mess.SetName("ClientPut");\r
- mess["URI"]=privatekey+messagebase+"|"+now.Format("%Y-%m-%d")+"|Identity|"+indexstr+".xml";\r
+ mess["URI"]=privatekey+messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|Identity|"+indexstr+".xml";\r
mess["Identifier"]="IdentityInserter|"+idstring+"|"+indexstr+"|"+mess["URI"];\r
mess["UploadFrom"]="direct";\r
mess["DataLength"]=datasizestr;\r
#include "../../include/freenet/identityintroductioninserter.h"\r
#include "../../include/freenet/identityintroductionxml.h"\r
-#include "../../include/xyssl/sha1.h"\r
#include "../../include/stringfunctions.h"\r
#include "../../include/hex.h"\r
#include "../../include/option.h"\r
\r
+#include <Poco/SHA1Engine.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
m_db->Execute("DELETE FROM tblIdentityIntroductionInserts WHERE UUID='"+idparts[3]+"';");\r
// update the puzzle from the request table (set to not found) because we don't need it anymore and don't want to user tyring to solve it again\r
m_db->Execute("UPDATE tblIntroductionPuzzleRequests SET Found='false' WHERE UUID='"+idparts[3]+"';");\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"IdentityIntroductionInserter::HandleMessage received fatal error trying to insert IdentityIntroduction "+idparts[3]);\r
+ m_log->warning("IdentityIntroductionInserter::HandleMessage received fatal error trying to insert IdentityIntroduction "+idparts[3]);\r
}\r
m_inserting=false;\r
return true;\r
{\r
m_db->Execute("UPDATE tblIdentityIntroductionInserts SET Inserted='true' WHERE UUID='"+idparts[3]+"';");\r
m_inserting=false;\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"IdentityIntroductionInserter::HandleMessage successfully inserted IdentityIntroduction "+idparts[3]);\r
+ m_log->information("IdentityIntroductionInserter::HandleMessage successfully inserted IdentityIntroduction "+idparts[3]);\r
return true;\r
}\r
\r
\r
void IdentityIntroductionInserter::Process()\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
\r
// only do 1 insert at a time\r
- if(!m_inserting && m_lastchecked<(now-(1.0/1440.0)))\r
+ if(!m_inserting && m_lastchecked<(now-Poco::Timespan(0,0,1,0,0)))\r
{\r
CheckForNewInserts();\r
m_lastchecked=now;\r
std::string publickey;\r
std::string data;\r
std::string datasizestr;\r
- std::vector<unsigned char> hash;\r
+// std::vector<unsigned char> hash;\r
std::string encodedhash;\r
\r
SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey FROM tblLocalIdentity WHERE PublicKey IS NOT NULL AND PublicKey<>'' AND LocalIdentityID=?;");\r
data=xml.GetXML();\r
StringFunctions::Convert(data.size(),datasizestr);\r
\r
- hash.resize(20);\r
- sha1((unsigned char *)solution.c_str(),solution.size(),&hash[0]);\r
- Hex::Encode(hash,encodedhash);\r
+ Poco::SHA1Engine sha1;\r
+ sha1.update(solution);\r
+ encodedhash=Poco::DigestEngine::digestToHex(sha1.digest());\r
+ StringFunctions::UpperCase(encodedhash,encodedhash);\r
+\r
+// hash.resize(20);\r
+// sha1((unsigned char *)solution.c_str(),solution.size(),&hash[0]);\r
+// Hex::Encode(hash,encodedhash);\r
\r
message.SetName("ClientPut");\r
message["URI"]="KSK@"+m_messagebase+"|"+day+"|"+UUID+"|"+encodedhash+".xml";\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IdentityIntroductionInserter::StartInsert could not find a public key for identity. It is probably a new identity that doesn't have a key yet.");\r
+ m_log->debug("IdentityIntroductionInserter::StartInsert could not find a public key for identity. It is probably a new identity that doesn't have a key yet.");\r
}\r
\r
}\r
#include "../../include/freenet/freenetssk.h"\r
#include "../../include/option.h"\r
#include "../../include/stringfunctions.h"\r
-#include "../../include/xyssl/sha1.h"\r
#include "../../include/hex.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timestamp.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/SHA1Engine.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
const bool IdentityIntroductionRequester::HandleAllData(FCPMessage &message)\r
{\r
FreenetSSK ssk;\r
- DateTime date;\r
+ Poco::DateTime date;\r
std::vector<std::string> idparts;\r
std::vector<char> data;\r
long datalength;\r
{\r
// we don't already know about this id - add it\r
st.Finalize();\r
- date.SetToGMTime();\r
+ date=Poco::Timestamp();\r
st=m_db->Prepare("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES(?,?,?);");\r
st.Bind(0,xml.GetIdentity());\r
- st.Bind(1,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Bind(2,"solved captcha");\r
st.Step();\r
}\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IdentityIntroductionRequester::HandleAddData parsed a valid identity.");\r
+ m_log->debug("IdentityIntroductionRequester::HandleAddData parsed a valid identity.");\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IdentityIntroductionRequester::HandleAllData parsed, public SSK key was not valid.");\r
+ m_log->error("IdentityIntroductionRequester::HandleAllData parsed, public SSK key was not valid.");\r
}\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IdentityIntroductionRequester::HandleAllData parsed IdentityIntroduction XML file : "+message["Identifier"]);\r
+ m_log->debug("IdentityIntroductionRequester::HandleAllData parsed IdentityIntroduction XML file : "+message["Identifier"]);\r
}\r
else\r
{\r
st.Step();\r
st.Finalize(); \r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IdentityIntroductionRequester::HandleAllData error parsing IdentityIntroduction XML file : "+message["Identifier"]);\r
+ m_log->error("IdentityIntroductionRequester::HandleAllData error parsing IdentityIntroduction XML file : "+message["Identifier"]);\r
}\r
\r
// remove UUID from request list\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IdentityIntroductionRequester::HandleAllData Fatal GetFailed for "+message["Identifier"]);\r
+ m_log->debug("IdentityIntroductionRequester::HandleAllData Fatal GetFailed for "+message["Identifier"]);\r
}\r
\r
// remove UUID from request list\r
if(m_maxrequests<1)\r
{\r
m_maxrequests=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxIdentityIntroductionRequests is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxIdentityIntroductionRequests is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxrequests>100)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxIdentityIntroductionRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MaxIdentityIntroductionRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
Option::Instance()->Get("MessageBase",m_messagebase);\r
- m_tempdate.SetToGMTime();\r
+ m_tempdate=Poco::Timestamp();\r
}\r
\r
void IdentityIntroductionRequester::PopulateIDList()\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
int id;\r
\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-1);\r
+ date-=Poco::Timespan(1,0,0,0,0);\r
\r
// get all identities that have unsolved puzzles from yesterday or today\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID FROM tblIntroductionPuzzleInserts WHERE Day>='"+date.Format("%Y-%m-%d")+"' AND FoundSolution='false' GROUP BY LocalIdentityID;");\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID FROM tblIntroductionPuzzleInserts WHERE Day>='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"' AND FoundSolution='false' GROUP BY LocalIdentityID;");\r
st.Step();\r
\r
m_ids.clear();\r
}\r
// special case - if there were 0 identities on the list when we started then we will never get a chance to repopulate the list\r
// this will recheck for ids every minute\r
- DateTime now;\r
- now.SetToGMTime();\r
- if(m_ids.size()==0 && m_tempdate<(now-(1.0/1440.0)))\r
+ Poco::DateTime now;\r
+ if(m_ids.size()==0 && m_tempdate<(now-Poco::Timespan(0,0,1,0,0)))\r
{\r
PopulateIDList();\r
m_tempdate=now;\r
{\r
std::string day;\r
std::string solution;\r
- std::vector<unsigned char> solutionhash;\r
+// std::vector<unsigned char> solutionhash;\r
std::string encodedhash;\r
FCPMessage message;\r
SQLite3DB::Statement st=m_db->Prepare("SELECT Day, PuzzleSolution FROM tblIntroductionPuzzleInserts WHERE FoundSolution='false' AND UUID=?;");\r
st.ResultText(0,day);\r
st.ResultText(1,solution);\r
\r
+ Poco::SHA1Engine sha1;\r
+ sha1.update(solution);\r
+ encodedhash=Poco::DigestEngine::digestToHex(sha1.digest());\r
+ StringFunctions::UpperCase(encodedhash,encodedhash);\r
+\r
// get the hash of the solution\r
- solutionhash.resize(20);\r
- sha1((unsigned char *)solution.c_str(),solution.size(),&solutionhash[0]);\r
- Hex::Encode(solutionhash,encodedhash);\r
+// solutionhash.resize(20);\r
+// sha1((unsigned char *)solution.c_str(),solution.size(),&solutionhash[0]);\r
+// Hex::Encode(solutionhash,encodedhash);\r
\r
//start request for the solution\r
message.SetName("ClientGet");\r
\r
void IdentityIntroductionRequester::StartRequests(const long localidentityid)\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
std::string localidentityidstr;\r
std::string uuid;\r
\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-1);\r
+ date-=Poco::Timespan(1,0,0,0,0);\r
StringFunctions::Convert(localidentityid,localidentityidstr);\r
\r
// get all non-solved puzzles from yesterday and today for this identity\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT UUID FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID="+localidentityidstr+" AND Day>='"+date.Format("%Y-%m-%d")+"' AND FoundSolution='false';");\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT UUID FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID="+localidentityidstr+" AND Day>='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"' AND FoundSolution='false';");\r
st.Step();\r
\r
// start requests for all non-solved puzzles\r
\r
std::string IdentityIntroductionXML::GetXML()\r
{\r
- TiXmlDocument td;\r
- TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
- TiXmlElement *tid;\r
- TiXmlPrinter tp;\r
+ Poco::AutoPtr<Poco::XML::Document> doc=new Poco::XML::Document;\r
+ //TiXmlDocument td;\r
+ //TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
+ Poco::XML::Element *root=doc->createElement("IdentityIntroduction");\r
+ //TiXmlElement *tid;\r
+ //TiXmlPrinter tp;\r
\r
- td.LinkEndChild(tdec);\r
- tid=new TiXmlElement("IdentityIntroduction");\r
- td.LinkEndChild(tid);\r
+ doc->appendChild(root);\r
+ //td.LinkEndChild(tdec);\r
+ //tid=new TiXmlElement("IdentityIntroduction");\r
+ //td.LinkEndChild(tid);\r
\r
- tid->LinkEndChild(XMLCreateCDATAElement("Identity",m_identity));\r
+ root->appendChild(XMLCreateCDATAElement(doc,"Identity",m_identity));\r
+ //tid->LinkEndChild(XMLCreateCDATAElement("Identity",m_identity));\r
\r
- td.Accept(&tp);\r
- return std::string(tp.CStr());\r
+ //td.Accept(&tp);\r
+ //return std::string(tp.CStr());\r
+ return GenerateXML(doc);\r
}\r
\r
void IdentityIntroductionXML::Initialize()\r
const bool IdentityIntroductionXML::ParseXML(const std::string &xml)\r
{\r
FreenetSSK ssk;\r
+ bool parsed=false;\r
+ Poco::XML::DOMParser dp;\r
+\r
+ Initialize();\r
+\r
+ try\r
+ {\r
+ Poco::AutoPtr<Poco::XML::Document> doc=dp.parseString(FixCDATA(xml));\r
+ Poco::XML::Element *root=XMLGetFirstChild(doc,"IdentityIntroduction");\r
+ Poco::XML::Element *txt=NULL;\r
+\r
+ txt=XMLGetFirstChild(root,"Identity");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_identity=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+\r
+ ssk.SetPublicKey(m_identity);\r
+ if(ssk.ValidPublicKey()==false)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ parsed=true;\r
+ }\r
+ catch(...)\r
+ {\r
+ }\r
+\r
+ return parsed;\r
+\r
+ /*\r
TiXmlDocument td;\r
td.Parse(xml.c_str());\r
\r
{\r
return false;\r
}\r
+ */\r
\r
}\r
#include "../../include/freenet/identityxml.h"\r
#include "../../include/stringfunctions.h"\r
#include "../../include/option.h"\r
-#include "../../include/datetime.h"\r
+\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timestamp.h>\r
+#include <Poco/Timespan.h>\r
+#include <Poco/DateTimeFormatter.h>\r
\r
#ifdef XMEM\r
#include <xmem.h>\r
\r
const bool IdentityRequester::HandleAllData(FCPMessage &message)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
long datalength;\r
long index;\r
std::string name="";\r
\r
- now.SetToGMTime();\r
+ now=Poco::Timestamp();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(message["DataLength"],datalength);\r
StringFunctions::Convert(idparts[1],identityid);\r
{\r
st.Bind(1,"false");\r
}\r
- st.Bind(2,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(2,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
if(xml.GetPublishTrustList()==true)\r
{\r
st.Bind(3,"true");\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IdentityRequester::HandleAllData parsed Identity XML file : "+message["Identifier"]);\r
+ m_log->debug("IdentityRequester::HandleAllData parsed Identity XML file : "+message["Identifier"]);\r
}\r
else\r
{\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IdentityRequester::HandleAllData error parsing Identity XML file : "+message["Identifier"]);\r
+ m_log->error("IdentityRequester::HandleAllData error parsing Identity XML file : "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
\r
const bool IdentityRequester::HandleGetFailed(FCPMessage &message)\r
{\r
- DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
long identityid;\r
long index;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(idparts[1],identityid);\r
StringFunctions::Convert(idparts[2],index); \r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IdentityRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
+ m_log->error("IdentityRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
if(m_maxrequests<1)\r
{\r
m_maxrequests=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxIdentityRequests is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxIdentityRequests is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxrequests>100)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxIdentityRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MaxIdentityRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
}\r
\r
void IdentityRequester::PopulateIDList()\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
int id;\r
\r
- date.SetToGMTime();\r
- date.SetHour(0);\r
- date.SetMinute(0);\r
- date.SetSecond(0);\r
+ date.assign(date.year(),date.month(),date.day(),0,0,0);\r
\r
// select identities we want to query (haven't seen yet today) - sort by their trust level (descending) with secondary sort on how long ago we saw them (ascending)\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND (LastSeen IS NULL OR LastSeen<'"+date.Format("%Y-%m-%d %H:%M:%S")+"') ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND (LastSeen IS NULL OR LastSeen<'"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"') ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
st.Step();\r
\r
m_ids.clear();\r
\r
void IdentityRequester::StartRequest(const long &identityid)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
FCPMessage message;\r
std::string publickey;\r
int index;\r
{\r
st.ResultText(0,publickey);\r
\r
- now.SetToGMTime();\r
+ now=Poco::Timestamp();\r
\r
SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblIdentityRequests WHERE Day=? AND IdentityID=?;");\r
- st2.Bind(0,now.Format("%Y-%m-%d"));\r
+ st2.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
st2.Bind(1,identityid);\r
st2.Step();\r
\r
StringFunctions::Convert(identityid,identityidstr);\r
\r
message.SetName("ClientGet");\r
- message["URI"]=publickey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|Identity|"+indexstr+".xml";\r
+ message["URI"]=publickey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|Identity|"+indexstr+".xml";\r
message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|"+message["URI"];\r
message["ReturnType"]="direct";\r
message["MaxSize"]="10000"; // 10 KB\r
\r
std::string IdentityXML::GetXML()\r
{\r
- TiXmlDocument td;\r
- TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
- TiXmlElement *tid;\r
- TiXmlPrinter tp;\r
+ Poco::AutoPtr<Poco::XML::Document> doc=new Poco::XML::Document;\r
+ //TiXmlDocument td;\r
+ //TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
+ Poco::XML::Element *root=doc->createElement("Identity");\r
+ //TiXmlElement *tid;\r
+ //TiXmlPrinter tp;\r
\r
- td.LinkEndChild(tdec);\r
- tid=new TiXmlElement("Identity");\r
- td.LinkEndChild(tid);\r
+ doc->appendChild(root);\r
+ //td.LinkEndChild(tdec);\r
+ //tid=new TiXmlElement("Identity");\r
+ //td.LinkEndChild(tid);\r
\r
- tid->LinkEndChild(XMLCreateCDATAElement("Name",m_name));\r
+ root->appendChild(XMLCreateCDATAElement(doc,"Name",m_name));\r
+ //tid->LinkEndChild(XMLCreateCDATAElement("Name",m_name));\r
\r
- tid->LinkEndChild(XMLCreateBooleanElement("SingleUse",m_singleuse));\r
+ root->appendChild(XMLCreateBooleanElement(doc,"SingleUse",m_singleuse));\r
+ //tid->LinkEndChild(XMLCreateBooleanElement("SingleUse",m_singleuse));\r
\r
- tid->LinkEndChild(XMLCreateBooleanElement("PublishTrustList",m_publishtrustlist));\r
+ root->appendChild(XMLCreateBooleanElement(doc,"PublishTrustList",m_publishtrustlist));\r
+ //tid->LinkEndChild(XMLCreateBooleanElement("PublishTrustList",m_publishtrustlist));\r
\r
- tid->LinkEndChild(XMLCreateBooleanElement("PublishBoardList",m_publishboardlist));\r
+ root->appendChild(XMLCreateBooleanElement(doc,"PublishBoardList",m_publishboardlist));\r
+ //tid->LinkEndChild(XMLCreateBooleanElement("PublishBoardList",m_publishboardlist));\r
\r
// freesite edition will be -1 if identity isn't publishing a freesite\r
if(m_freesiteedition>=0)\r
{\r
- tid->LinkEndChild(XMLCreateTextElement("FreesiteEdition",m_freesiteedition));\r
+ root->appendChild(XMLCreateTextElement(doc,"FreesiteEdition",m_freesiteedition));\r
+ //tid->LinkEndChild(XMLCreateTextElement("FreesiteEdition",m_freesiteedition));\r
}\r
\r
- td.Accept(&tp);\r
- return std::string(tp.CStr());\r
+ //td.Accept(&tp);\r
+ //return std::string(tp.CStr());\r
\r
+ return GenerateXML(doc);\r
}\r
\r
void IdentityXML::Initialize()\r
\r
const bool IdentityXML::ParseXML(const std::string &xml)\r
{\r
+\r
+ bool parsed=false;\r
+ Poco::XML::DOMParser dp;\r
+\r
+ Initialize();\r
+\r
+ try\r
+ {\r
+ Poco::AutoPtr<Poco::XML::Document> doc=dp.parseString(FixCDATA(xml));\r
+ Poco::XML::Element *root=XMLGetFirstChild(doc,"Identity");\r
+ Poco::XML::Element *txt=NULL;\r
+\r
+ txt=XMLGetFirstChild(root,"Name");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_name=txt->firstChild()->getNodeValue();\r
+ if(m_name.size()>40)\r
+ {\r
+ m_name.erase(40);\r
+ }\r
+ }\r
+ }\r
+ \r
+ m_singleuse=XMLGetBooleanElement(root,"SingleUse");\r
+ m_publishtrustlist=XMLGetBooleanElement(root,"PublishTrustList");\r
+ m_publishboardlist=XMLGetBooleanElement(root,"PublishBoardList");\r
+ \r
+ txt=XMLGetFirstChild(root,"FreesiteEdition");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ std::string editionstr=txt->firstChild()->getNodeValue();\r
+ StringFunctions::Convert(editionstr,m_freesiteedition);\r
+ }\r
+ }\r
+\r
+ parsed=true;\r
+\r
+ }\r
+ catch(...)\r
+ {\r
+ }\r
+\r
+ return parsed;\r
+\r
+ /*\r
TiXmlDocument td;\r
td.Parse(xml.c_str());\r
\r
{\r
return false;\r
}\r
-\r
+*/\r
}\r
#include "../../include/stringfunctions.h"\r
#include "../../include/option.h"\r
#include "../../include/freenet/captcha/simplecaptcha.h"\r
-#include "../../include/uuidgenerator.h"\r
#include "../../include/base64.h"\r
\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/UUIDGenerator.h>\r
+#include <Poco/UUID.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
while(!rs.AtEnd())\r
{\r
std::string localidentityidstr;\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
\r
if(rs.GetField(0))\r
{\r
}\r
\r
// if this identity has any non-solved puzzles for today, we don't need to insert a new puzzle\r
- SQLite3DB::Recordset rs2=m_db->Query("SELECT UUID FROM tblIntroductionPuzzleInserts WHERE Day='"+now.Format("%Y-%m-%d")+"' AND FoundSolution='false' AND LocalIdentityID="+localidentityidstr+";");\r
+ SQLite3DB::Recordset rs2=m_db->Query("SELECT UUID FROM tblIntroductionPuzzleInserts WHERE Day='"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"' AND FoundSolution='false' AND LocalIdentityID="+localidentityidstr+";");\r
\r
// identity doesn't have any non-solved puzzles for today - start a new insert\r
if(rs2.Empty()==true)\r
\r
RemoveFromInsertList(localidentityid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::HandlePutFailed failed to insert puzzle "+idparts[3]);\r
+ m_log->debug("IntroductionPuzzleInserter::HandlePutFailed failed to insert puzzle "+idparts[3]);\r
}\r
\r
return true;\r
\r
const bool IntroductionPuzzleInserter::HandlePutSuccessful(FCPMessage &message)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
long localidentityid;\r
long insertindex;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
\r
// non USK\r
st.Finalize();\r
\r
st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedPuzzle=? WHERE LocalIdentityID=?;");\r
- st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
st.Bind(1,localidentityid);\r
st.Step();\r
st.Finalize();\r
\r
RemoveFromInsertList(localidentityid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::HandlePutSuccessful inserted puzzle "+idparts[3]);\r
+ m_log->debug("IntroductionPuzzleInserter::HandlePutSuccessful inserted puzzle "+idparts[3]);\r
}\r
\r
return true;\r
\r
const bool IntroductionPuzzleInserter::StartInsert(const long &localidentityid)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
std::string idstring;\r
long index=0;\r
std::string indexstr;\r
- UUIDGenerator uuid;\r
+ Poco::UUIDGenerator uuidgen;\r
+ Poco::UUID uuid;\r
std::string messagebase;\r
IntroductionPuzzleXML xml;\r
std::string encodedpuzzle;\r
std::string keypart="";\r
\r
StringFunctions::Convert(localidentityid,idstring);\r
- now.SetToGMTime();\r
- SQLite3DB::Recordset rs=m_db->Query("SELECT MAX(InsertIndex) FROM tblIntroductionPuzzleInserts WHERE Day='"+now.Format("%Y-%m-%d")+"' AND LocalIdentityID="+idstring+";");\r
+ SQLite3DB::Recordset rs=m_db->Query("SELECT MAX(InsertIndex) FROM tblIntroductionPuzzleInserts WHERE Day='"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"' AND LocalIdentityID="+idstring+";");\r
\r
if(rs.Empty() || rs.GetField(0)==NULL)\r
{\r
\r
GenerateCaptcha(encodedpuzzle,solutionstring);\r
\r
+ try\r
+ {\r
+ uuid=uuidgen.createRandom();\r
+ }\r
+ catch(...)\r
+ {\r
+ m_log->fatal("IntroductionPuzzleInserter::StartInsert could not create UUID");\r
+ }\r
+\r
xml.SetType("captcha");\r
- xml.SetUUID(uuid.Generate()+"@"+keypart);\r
+ xml.SetUUID(uuid.toString()+"@"+keypart);\r
xml.SetPuzzleData(encodedpuzzle);\r
xml.SetMimeType("image/bmp");\r
\r
StringFunctions::Convert(xmldata.size(),xmldatasizestr);\r
\r
message.SetName("ClientPut");\r
- message["URI"]=privatekey+messagebase+"|"+now.Format("%Y-%m-%d")+"|IntroductionPuzzle|"+indexstr+".xml";\r
+ message["URI"]=privatekey+messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|IntroductionPuzzle|"+indexstr+".xml";\r
message["Identifier"]=m_fcpuniquename+"|"+idstring+"|"+indexstr+"|"+xml.GetUUID()+"|"+message["URI"];\r
message["UploadFrom"]="direct";\r
message["DataLength"]=xmldatasizestr;\r
// insert to USK\r
message.Reset();\r
message.SetName("ClientPutComplexDir");\r
- message["URI"]="USK"+privatekey.substr(3)+messagebase+"|"+now.Format("%Y.%m.%d")+"|IntroductionPuzzle/0/";\r
+ message["URI"]="USK"+privatekey.substr(3)+messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y.%m.%d")+"|IntroductionPuzzle/0/";\r
message["Identifier"]=m_fcpuniquename+"USK|"+message["URI"];\r
message["DefaultName"]="IntroductionPuzzle.xml";\r
message["Files.0.Name"]="IntroductionPuzzle.xml";\r
\r
m_inserting.push_back(localidentityid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::StartInsert started insert for id "+idstring);\r
+ m_log->debug("IntroductionPuzzleInserter::StartInsert started insert for id "+idstring);\r
\r
return true;\r
\r
#include "../../include/bitmapvalidator.h"\r
#include "../../include/base64.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timespan.h>\r
+#include <Poco/Timestamp.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
\r
const bool IntroductionPuzzleRequester::HandleAllData(FCPMessage &message)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
long datalength;\r
long index;\r
bool validmessage=true;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(message["DataLength"],datalength);\r
StringFunctions::Convert(idparts[1],identityid);\r
keypart=StringFunctions::Replace(StringFunctions::Replace(keyparts[1],"-",""),"~","");\r
if(keypart!=uuidparts[1])\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IntroductionPuzzleRequester::HandleAllData UUID in IntroductionPuzzle doesn't match public key of identity : "+message["Identifier"]);\r
+ m_log->error("IntroductionPuzzleRequester::HandleAllData UUID in IntroductionPuzzle doesn't match public key of identity : "+message["Identifier"]);\r
validmessage=false;\r
}\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IntroductionPuzzleRequester::HandleAllData Error with identity's public key or UUID : "+message["Identifier"]);\r
+ m_log->error("IntroductionPuzzleRequester::HandleAllData Error with identity's public key or UUID : "+message["Identifier"]);\r
validmessage=false;\r
}\r
\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IntroductionPuzzleRequester::HandleAllData Error couldn't find identity : "+message["Identifier"]);\r
+ m_log->error("IntroductionPuzzleRequester::HandleAllData Error couldn't find identity : "+message["Identifier"]);\r
validmessage=false;\r
}\r
\r
Base64::Decode(xml.GetPuzzleData(),puzzledata);\r
if(xml.GetMimeType()!="image/bmp" || val.Validate(puzzledata)==false)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IntroductionPuzzleRequester::HandleAllData received bad mime type and/or data for "+message["Identifier"]);\r
+ m_log->error("IntroductionPuzzleRequester::HandleAllData received bad mime type and/or data for "+message["Identifier"]);\r
validmessage=false;\r
}\r
\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleRequester::HandleAllData parsed IntroductionPuzzle XML file : "+message["Identifier"]);\r
+ m_log->debug("IntroductionPuzzleRequester::HandleAllData parsed IntroductionPuzzle XML file : "+message["Identifier"]);\r
}\r
else\r
{\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IntroductionPuzzleRequester::HandleAllData error parsing IntroductionPuzzle XML file : "+message["Identifier"]);\r
+ m_log->error("IntroductionPuzzleRequester::HandleAllData error parsing IntroductionPuzzle XML file : "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
\r
const bool IntroductionPuzzleRequester::HandleGetFailed(FCPMessage &message)\r
{\r
- DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
long identityid;\r
long index;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(idparts[1],identityid);\r
StringFunctions::Convert(idparts[2],index); \r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"IntroductionPuzzleRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
+ m_log->error("IntroductionPuzzleRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
if(m_maxrequests<1)\r
{\r
m_maxrequests=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxIntroductionPuzzleRequests is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxIntroductionPuzzleRequests is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxrequests>100)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxIntroductionPuzzleRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MaxIntroductionPuzzleRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
Option::Instance()->Get("MessageBase",m_messagebase);\r
- m_tempdate.SetToGMTime();\r
+ m_tempdate=Poco::Timestamp();\r
}\r
\r
void IntroductionPuzzleRequester::PopulateIDList()\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
int id;\r
std::string limitnum="30";\r
\r
}\r
st.Finalize();\r
\r
- now.SetToGMTime();\r
-\r
// select identities that aren't single use, are publishing a trust list, and have been seen today ( order by trust DESC and limit to limitnum )\r
- st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublishTrustList='true' AND PublicKey IS NOT NULL AND PublicKey <> '' AND SingleUse='false' AND LastSeen>='"+now.Format("%Y-%m-%d")+"' ORDER BY LocalMessageTrust DESC LIMIT 0,"+limitnum+";");\r
+ st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublishTrustList='true' AND PublicKey IS NOT NULL AND PublicKey <> '' AND SingleUse='false' AND LastSeen>='"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"' ORDER BY LocalMessageTrust DESC LIMIT 0,"+limitnum+";");\r
st.Step();\r
\r
m_ids.clear();\r
}\r
// special case - if there were 0 identities on the list when we started then we will never get a chance to repopulate the list\r
// this will recheck for ids every minute\r
- DateTime now;\r
- now.SetToGMTime();\r
- if(m_ids.size()==0 && m_tempdate<(now-(1.0/1440.0)))\r
+ Poco::DateTime now;\r
+ if(m_ids.size()==0 && m_tempdate<(now-Poco::Timespan(0,0,1,0,0)))\r
{\r
PopulateIDList();\r
m_tempdate=now;\r
\r
void IntroductionPuzzleRequester::StartRequest(const long identityid)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
FCPMessage message;\r
std::string publickey;\r
int index;\r
{\r
st.ResultText(0,publickey);\r
\r
- now.SetToGMTime();\r
+ now=Poco::Timestamp();\r
\r
SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblIntroductionPuzzleRequests WHERE Day=? AND IdentityID=?;");\r
- st2.Bind(0,now.Format("%Y-%m-%d"));\r
+ st2.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
st2.Bind(1,identityid);\r
st2.Step();\r
\r
StringFunctions::Convert(identityid,identityidstr);\r
\r
message.SetName("ClientGet");\r
- message["URI"]=publickey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|IntroductionPuzzle|"+indexstr+".xml";\r
+ message["URI"]=publickey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|IntroductionPuzzle|"+indexstr+".xml";\r
message["Identifier"]="IntroductionPuzzleRequester|"+identityidstr+"|"+indexstr+"|"+message["URI"];\r
message["ReturnType"]="direct";\r
message["MaxSize"]="1000000"; // 1 MB\r
\r
std::string IntroductionPuzzleXML::GetXML()\r
{\r
- TiXmlDocument td;\r
- TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
- TiXmlElement *tid;\r
- TiXmlPrinter tp;\r
+ Poco::AutoPtr<Poco::XML::Document> doc=new Poco::XML::Document;\r
+ //TiXmlDocument td;\r
+ //TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
+ Poco::XML::Element *root=doc->createElement("IntroductionPuzzle");\r
+ //TiXmlElement *tid;\r
+ //TiXmlPrinter tp;\r
\r
- td.LinkEndChild(tdec);\r
- tid=new TiXmlElement("IntroductionPuzzle");\r
- td.LinkEndChild(tid);\r
+ doc->appendChild(root);\r
+ //td.LinkEndChild(tdec);\r
+ //tid=new TiXmlElement("IntroductionPuzzle");\r
+ //td.LinkEndChild(tid);\r
\r
- tid->LinkEndChild(XMLCreateTextElement("Type",m_type));\r
+ root->appendChild(XMLCreateTextElement(doc,"Type",m_type));\r
+ //tid->LinkEndChild(XMLCreateTextElement("Type",m_type));\r
\r
- tid->LinkEndChild(XMLCreateCDATAElement("UUID",m_uuid));\r
+ root->appendChild(XMLCreateCDATAElement(doc,"UUID",m_uuid));\r
+ //tid->LinkEndChild(XMLCreateCDATAElement("UUID",m_uuid));\r
\r
- tid->LinkEndChild(XMLCreateTextElement("MimeType",m_mimetype));\r
+ root->appendChild(XMLCreateTextElement(doc,"MimeType",m_mimetype));\r
+ //tid->LinkEndChild(XMLCreateTextElement("MimeType",m_mimetype));\r
\r
- tid->LinkEndChild(XMLCreateTextElement("PuzzleData",m_puzzledata));\r
+ root->appendChild(XMLCreateTextElement(doc,"PuzzleData",m_puzzledata));\r
+ //tid->LinkEndChild(XMLCreateTextElement("PuzzleData",m_puzzledata));\r
\r
- td.Accept(&tp);\r
- return std::string(tp.CStr());\r
+ //td.Accept(&tp);\r
+ //return std::string(tp.CStr());\r
+ return GenerateXML(doc);\r
}\r
\r
void IntroductionPuzzleXML::Initialize()\r
\r
const bool IntroductionPuzzleXML::ParseXML(const std::string &xml)\r
{\r
+ bool parsed=false;\r
+ Poco::XML::DOMParser dp;\r
+\r
+ Initialize();\r
+\r
+ try\r
+ {\r
+ Poco::AutoPtr<Poco::XML::Document> doc=dp.parseString(FixCDATA(xml));\r
+ Poco::XML::Element *root=XMLGetFirstChild(doc,"IntroductionPuzzle");\r
+ Poco::XML::Element *txt=NULL;\r
+\r
+ txt=XMLGetFirstChild(root,"Type");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_type=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(root,"UUID");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_uuid=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(root,"MimeType");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_mimetype=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(root,"PuzzleData");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_puzzledata=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+\r
+ parsed=true;\r
+ }\r
+ catch(...)\r
+ {\r
+ }\r
+\r
+ return parsed;\r
+\r
+ /*\r
TiXmlDocument td;\r
td.Parse(xml.c_str());\r
\r
{\r
return false;\r
}\r
+ */\r
}\r
#include "../../include/freenet/messageinserter.h"\r
#include "../../include/freenet/messagexml.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/Timestamp.h>\r
+\r
MessageInserter::MessageInserter()\r
{\r
Initialize();\r
\r
void MessageInserter::CheckForNeededInsert()\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
bool didinsert=false;\r
// only do 1 insert at a time\r
if(m_inserting.size()==0)\r
{\r
SQLite3DB::Statement st=m_db->Prepare("SELECT MessageUUID FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE tblLocalIdentity.PrivateKey IS NOT NULL AND tblLocalIdentity.PrivateKey <> '' AND tblMessageInserts.Inserted='false' AND tblMessageInserts.SendDate<=?;");\r
- st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
\r
while(st.RowReturned() && m_inserting.size()==0)\r
const bool MessageInserter::HandlePutSuccessful(FCPMessage &message)\r
{\r
MessageXML xml;\r
- DateTime date;\r
+ Poco::DateTime date;\r
int localidentityid;\r
int index;\r
std::vector<std::string> idparts;\r
st.Step();\r
\r
// insert record into temp table so MessageList will be inserted ASAP\r
- date.SetToGMTime();\r
+ date=Poco::Timestamp();\r
st=m_db->Prepare("INSERT INTO tmpMessageListInsert(LocalIdentityID,Date) VALUES(?,?);");\r
st.Bind(0,localidentityid);\r
- st.Bind(1,date.Format("%Y-%m-%d"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
st.Step();\r
\r
// update the messageuuid to the real messageuuid\r
\r
RemoveFromInsertList(idparts[1]);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageInserter::HandlePutSuccessful successfully inserted message "+message["Identifier"]);\r
+ m_log->debug("MessageInserter::HandlePutSuccessful successfully inserted message "+message["Identifier"]);\r
\r
return true;\r
}\r
const bool MessageInserter::StartInsert(const std::string &messageuuid)\r
{\r
MessageXML xmlfile;\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
SQLite3DB::Statement st=m_db->Prepare("SELECT MessageXML,PrivateKey,tblLocalIdentity.LocalIdentityID,PublicKey FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE MessageUUID=?;");\r
st.Bind(0,messageuuid);\r
st.Step();\r
StringFunctions::Convert(localidentityid,idstr);\r
\r
st=m_db->Prepare("SELECT MAX(InsertIndex) FROM tblMessageInserts WHERE Day=? AND LocalIdentityID=?;");\r
- st.Bind(0,now.Format("%Y-%m-%d"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
st.Bind(1,localidentityid);\r
st.Step();\r
\r
StringFunctions::Convert(xml.size(),xmlsizestr);\r
\r
message.SetName("ClientPut");\r
- message["URI"]=privatekey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|Message|"+indexstr+".xml";\r
+ message["URI"]=privatekey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|Message|"+indexstr+".xml";\r
message["Identifier"]=m_fcpuniquename+"|"+messageuuid+"|"+idstr+"|"+indexstr+"|"+xmlfile.GetMessageID()+"|"+message["URI"];\r
message["UploadFrom"]="direct";\r
message["DataLength"]=xmlsizestr;\r
\r
m_inserting.push_back(messageuuid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageInserter::StartInsert started message insert "+message["URI"]);\r
+ m_log->debug("MessageInserter::StartInsert started message insert "+message["URI"]);\r
\r
return true;\r
}\r
#include "../../include/freenet/messagexml.h"\r
#include "../../include/freenet/messagelistxml.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timespan.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
if(m_inserting.size()==0)\r
{\r
std::string sql;\r
- DateTime now;\r
- DateTime previous;\r
+ Poco::DateTime now;\r
+ Poco::DateTime previous;\r
bool startedinsert=false;\r
\r
- now.SetToGMTime();\r
- previous.SetToGMTime();\r
-\r
// reset the last inserted xml doc to nothing if the day has changed\r
- if(m_lastchecked.GetDay()!=now.GetDay())\r
+ if(m_lastchecked.day()!=now.day())\r
{\r
m_lastinsertedxml.clear();\r
}\r
\r
- previous.Add(0,0,0,-m_daysbackward);\r
+ previous-=Poco::Timespan(m_daysbackward,0,0,0,0);\r
\r
// query for identities that have messages in the past X days and (we haven't inserted lists for in the past 30 minutes OR identity has a record in tmpMessageListInsert)\r
sql="SELECT tblLocalIdentity.LocalIdentityID ";\r
sql+="GROUP BY tblLocalIdentity.LocalIdentityID;";\r
\r
SQLite3DB::Statement st=m_db->Prepare(sql);\r
- st.Bind(0,previous.Format("%Y-%m-%d"));\r
- st.Bind(1,(now-(1.0/48.0)).Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(previous,"%Y-%m-%d"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format((now-Poco::Timespan(0,0,30,0,0)),"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
\r
while(st.RowReturned() && startedinsert==false)\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageListInserter::HandlePutFailed "+message["Identifier"]);\r
+ m_log->debug("MessageListInserter::HandlePutFailed "+message["Identifier"]);\r
}\r
\r
return true;\r
\r
const bool MessageListInserter::HandlePutSuccessful(FCPMessage &message)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
std::vector<std::string> idparts;\r
long localidentityid;\r
long index;\r
st.Bind(2,index);\r
st.Step();\r
\r
- now.SetToGMTime();\r
+ now=Poco::Timestamp();\r
st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedMessageList=? WHERE LocalIdentityID=?;");\r
- st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
st.Bind(1,localidentityid);\r
st.Step();\r
\r
\r
RemoveFromInsertList(localidentityid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageListInserter::HandlePutSuccessful successfully inserted MessageList.");\r
+ m_log->debug("MessageListInserter::HandlePutSuccessful successfully inserted MessageList.");\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageListInserter::HandlePutSuccessful inserted USK MessageList "+message["Identifier"]);\r
+ m_log->debug("MessageListInserter::HandlePutSuccessful inserted USK MessageList "+message["Identifier"]);\r
}\r
\r
return true;\r
const bool MessageListInserter::StartInsert(const long &localidentityid)\r
{\r
FCPMessage message;\r
- DateTime date;\r
- DateTime now;\r
+ Poco::DateTime date;\r
+ Poco::DateTime now;\r
std::string privatekey;\r
std::string localidentityidstr;\r
MessageListXML mlxml;\r
int index;\r
std::string indexstr;\r
\r
- now.SetToGMTime();\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-m_daysbackward);\r
+ date-=Poco::Timespan(m_daysbackward,0,0,0,0);\r
StringFunctions::Convert(localidentityid,localidentityidstr);\r
\r
SQLite3DB::Statement st=m_db->Prepare("SELECT Day, InsertIndex, MessageXML, PrivateKey FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE tblLocalIdentity.LocalIdentityID=? AND Day>=?;");\r
st.Bind(0,localidentityid);\r
- st.Bind(1,date.Format("%Y-%m-%d"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
st.Step();\r
\r
while(st.RowReturned())\r
index=0;\r
st=m_db->Prepare("SELECT MAX(InsertIndex) FROM tblMessageListInserts WHERE LocalIdentityID=? AND Day=?;");\r
st.Bind(0,localidentityid);\r
- st.Bind(1,now.Format("%Y-%m-%d"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
st.Step();\r
if(st.ResultNull(0)==false)\r
{\r
StringFunctions::Convert(xmlstr.size(),xmlsizestr);\r
\r
message.SetName("ClientPut");\r
- message["URI"]=privatekey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|MessageList|"+indexstr+".xml";\r
+ message["URI"]=privatekey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|MessageList|"+indexstr+".xml";\r
message["Identifier"]=m_fcpuniquename+"|"+localidentityidstr+"|"+indexstr+"|"+message["URI"];\r
message["UploadFrom"]="direct";\r
message["DataLength"]=xmlsizestr;\r
\r
message.Reset();\r
message.SetName("ClientPutComplexDir");\r
- message["URI"]="USK"+privatekey.substr(3)+m_messagebase+"|"+now.Format("%Y.%m.%d")+"|MessageList/0/";\r
+ message["URI"]="USK"+privatekey.substr(3)+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y.%m.%d")+"|MessageList/0/";\r
message["Identifier"]=m_fcpuniquename+"USK|"+message["URI"];\r
message["DefaultName"]="MessageList.xml";\r
message["Files.0.Name"]="MessageList.xml";\r
#include "../../include/freenet/messagelistrequester.h"\r
#include "../../include/freenet/messagelistxml.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/Timestamp.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
\r
const bool MessageListRequester::HandleAllData(FCPMessage &message)\r
{ \r
- DateTime now;\r
SQLite3DB::Statement st;\r
SQLite3DB::Statement trustst;\r
std::vector<std::string> idparts;\r
long identityid;\r
long index;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(message["DataLength"],datalength);\r
StringFunctions::Convert(idparts[1],identityid);\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageListRequester::HandleAllData parsed MessageList XML file : "+message["Identifier"]);\r
+ m_log->debug("MessageListRequester::HandleAllData parsed MessageList XML file : "+message["Identifier"]);\r
}\r
else\r
{\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageListRequester::HandleAllData error parsing MessageList XML file : "+message["Identifier"]);\r
+ m_log->error("MessageListRequester::HandleAllData error parsing MessageList XML file : "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
\r
const bool MessageListRequester::HandleGetFailed(FCPMessage &message)\r
{\r
- DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
long identityid;\r
long index;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(idparts[1],identityid);\r
StringFunctions::Convert(idparts[2],index); \r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageListRequester::HandleGetFailed fatal error code="+message["Code"]+" requesting "+message["Identifier"]);\r
+ m_log->error("MessageListRequester::HandleGetFailed fatal error code="+message["Code"]+" requesting "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
if(m_maxrequests<1)\r
{\r
m_maxrequests=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxMessageListRequests is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxMessageListRequests is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxrequests>100)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxMessageListRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MaxMessageListRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
\r
Option::Instance()->Get("LocalTrustOverridesPeerTrust",tempval);\r
\r
void MessageListRequester::PopulateIDList()\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
int id;\r
\r
- date.SetToGMTime();\r
-\r
SQLite3DB::Statement st;\r
\r
// select identities we want to query (we've seen them today) - sort by their trust level (descending) with secondary sort on how long ago we saw them (ascending)\r
if(m_localtrustoverrides==false)\r
{\r
- st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+date.Format("%Y-%m-%d")+"' AND (LocalMessageTrust IS NULL OR LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust')) AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')) ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
+ st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"' AND (LocalMessageTrust IS NULL OR LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust')) AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')) ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
}\r
else\r
{\r
- st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+date.Format("%Y-%m-%d")+"' AND (LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust') OR (LocalMessageTrust IS NULL AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')))) ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
+ st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"' AND (LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust') OR (LocalMessageTrust IS NULL AND (PeerMessageTrust IS NULL OR PeerMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerMessageTrust')))) ORDER BY LocalMessageTrust+LocalTrustListTrust DESC, LastSeen;");\r
}\r
st.Step();\r
\r
\r
void MessageListRequester::StartRequest(const long &id)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
FCPMessage message;\r
std::string publickey;\r
int index=0;\r
{\r
st.ResultText(0,publickey);\r
\r
- now.SetToGMTime();\r
+ now=Poco::Timestamp();\r
\r
SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblMessageListRequests WHERE Day=? AND IdentityID=?;");\r
- st2.Bind(0,now.Format("%Y-%m-%d"));\r
+ st2.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
st2.Bind(1,id);\r
st2.Step();\r
\r
StringFunctions::Convert(id,identityidstr);\r
\r
message.SetName("ClientGet");\r
- message["URI"]="USK"+publickey.substr(3)+m_messagebase+"|"+now.Format("%Y.%m.%d")+"|MessageList/"+indexstr+"/MessageList.xml";\r
- message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|_|"+now.Format("%Y-%m-%d")+"|"+message["URI"];\r
+ message["URI"]="USK"+publickey.substr(3)+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y.%m.%d")+"|MessageList/"+indexstr+"/MessageList.xml";\r
+ message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|_|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|"+message["URI"];\r
message["ReturnType"]="direct";\r
message["MaxSize"]="1000000";\r
\r
\r
std::string MessageListXML::GetXML()\r
{\r
- TiXmlDocument td;\r
- TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
- TiXmlElement *tid;\r
- TiXmlPrinter tp;\r
-\r
- td.LinkEndChild(tdec);\r
- tid=new TiXmlElement("MessageList");\r
- td.LinkEndChild(tid);\r
+ Poco::AutoPtr<Poco::XML::Document> doc=new Poco::XML::Document;\r
+ //TiXmlDocument td;\r
+ //TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
+ Poco::XML::Element *root=doc->createElement("MessageList");\r
+ //TiXmlElement *tid;\r
+ //TiXmlPrinter tp;\r
+\r
+ doc->appendChild(root);\r
+ //td.LinkEndChild(tdec);\r
+ //tid=new TiXmlElement("MessageList");\r
+ //td.LinkEndChild(tid);\r
\r
for(std::vector<message>::iterator i=m_messages.begin(); i!=m_messages.end(); i++)\r
{\r
- TiXmlElement *tr=new TiXmlElement("Message");\r
- tid->LinkEndChild(tr);\r
- tr->LinkEndChild(XMLCreateTextElement("Date",(*i).m_date));\r
- tr->LinkEndChild(XMLCreateTextElement("Index",(*i).m_index));\r
- TiXmlElement *brds=new TiXmlElement("Boards");\r
- tr->LinkEndChild(brds);\r
+ Poco::XML::Element *tr=doc->createElement("Message");\r
+ //TiXmlElement *tr=new TiXmlElement("Message");\r
+ root->appendChild(tr);\r
+ //tid->LinkEndChild(tr);\r
+ tr->appendChild(XMLCreateTextElement(doc,"Date",(*i).m_date));\r
+ //tr->LinkEndChild(XMLCreateTextElement("Date",(*i).m_date));\r
+ tr->appendChild(XMLCreateTextElement(doc,"Index",(*i).m_index));\r
+ //tr->LinkEndChild(XMLCreateTextElement("Index",(*i).m_index));\r
+ Poco::XML::Element *boards=doc->createElement("Boards");\r
+ //TiXmlElement *brds=new TiXmlElement("Boards");\r
+ tr->appendChild(boards);\r
+ //tr->LinkEndChild(brds);\r
for(std::vector<std::string>::iterator j=(*i).m_boards.begin(); j!=(*i).m_boards.end(); j++)\r
{\r
- brds->LinkEndChild(XMLCreateCDATAElement("Board",(*j)));\r
+ boards->appendChild(XMLCreateCDATAElement(doc,"Board",(*j)));\r
+ //brds->LinkEndChild(XMLCreateCDATAElement("Board",(*j)));\r
}\r
}\r
\r
for(std::vector<externalmessage>::iterator i=m_externalmessages.begin(); i!=m_externalmessages.end(); i++)\r
{\r
- TiXmlElement *tr=new TiXmlElement("ExternalMessage");\r
- tid->LinkEndChild(tr);\r
- tr->LinkEndChild(XMLCreateTextElement("Type",(*i).m_type));\r
+ Poco::XML::Element *tr=doc->createElement("ExternalMessage");\r
+ //TiXmlElement *tr=new TiXmlElement("ExternalMessage");\r
+ root->appendChild(tr);\r
+ //tid->LinkEndChild(tr);\r
+ tr->appendChild(XMLCreateTextElement(doc,"Type",(*i).m_type));\r
+ //tr->LinkEndChild(XMLCreateTextElement("Type",(*i).m_type));\r
if((*i).m_type=="Keyed")\r
{\r
- tr->LinkEndChild(XMLCreateCDATAElement("Identity",(*i).m_identity));\r
- tr->LinkEndChild(XMLCreateTextElement("Index",(*i).m_index));\r
+ tr->appendChild(XMLCreateCDATAElement(doc,"Identity",(*i).m_identity));\r
+ //tr->LinkEndChild(XMLCreateCDATAElement("Identity",(*i).m_identity));\r
+ tr->appendChild(XMLCreateTextElement(doc,"Index",(*i).m_index));\r
+ //tr->LinkEndChild(XMLCreateTextElement("Index",(*i).m_index));\r
}\r
else\r
{\r
- tr->LinkEndChild(XMLCreateCDATAElement("MessageKey",(*i).m_messagekey));\r
+ tr->appendChild(XMLCreateCDATAElement(doc,"MessageKey",(*i).m_messagekey));\r
+ //tr->LinkEndChild(XMLCreateCDATAElement("MessageKey",(*i).m_messagekey));\r
}\r
- tr->LinkEndChild(XMLCreateTextElement("Date",(*i).m_date));\r
- TiXmlElement *brds=new TiXmlElement("Boards");\r
- tr->LinkEndChild(brds);\r
+ tr->appendChild(XMLCreateTextElement(doc,"Date",(*i).m_date));\r
+ //tr->LinkEndChild(XMLCreateTextElement("Date",(*i).m_date));\r
+ Poco::XML::Element *boards=doc->createElement("Boards");\r
+ //TiXmlElement *brds=new TiXmlElement("Boards");\r
+ tr->appendChild(boards);\r
+ //tr->LinkEndChild(brds);\r
for(std::vector<std::string>::iterator j=(*i).m_boards.begin(); j!=(*i).m_boards.end(); j++)\r
{\r
- brds->LinkEndChild(XMLCreateCDATAElement("Board",(*j)));\r
+ boards->appendChild(XMLCreateCDATAElement(doc,"Board",(*j)));\r
+ //brds->LinkEndChild(XMLCreateCDATAElement("Board",(*j)));\r
}\r
}\r
\r
- td.Accept(&tp);\r
- return std::string(tp.CStr());\r
+ //td.Accept(&tp);\r
+ //return std::string(tp.CStr());\r
+ return GenerateXML(doc);\r
}\r
\r
void MessageListXML::Initialize()\r
\r
const bool MessageListXML::ParseXML(const std::string &xml)\r
{\r
+\r
+ bool parsed=false;\r
+ Poco::XML::DOMParser dp;\r
+\r
+ Initialize();\r
+\r
+ try\r
+ {\r
+ Poco::AutoPtr<Poco::XML::Document> doc=dp.parseString(FixCDATA(xml));\r
+ Poco::XML::Element *root=XMLGetFirstChild(doc,"MessageList");\r
+\r
+ Poco::XML::Element *node=XMLGetFirstChild(root,"Message");\r
+ while(node)\r
+ {\r
+ std::string date="";\r
+ int index=-1;\r
+ std::vector<std::string> boards;\r
+\r
+ Poco::XML::Element *node2=XMLGetFirstChild(node,"Date");\r
+ if(node2 && node2->firstChild())\r
+ {\r
+ date=SanitizeSingleString(node2->firstChild()->getNodeValue());\r
+ }\r
+ node2=XMLGetFirstChild(node,"Index");\r
+ if(node2 && node2->firstChild())\r
+ {\r
+ std::string indexstr=SanitizeSingleString(node2->firstChild()->getNodeValue());\r
+ StringFunctions::Convert(indexstr,index);\r
+ }\r
+ node2=XMLGetFirstChild(node,"Boards");\r
+ if(node2)\r
+ {\r
+ Poco::XML::Element *node3=XMLGetFirstChild(node2,"Board");\r
+ while(node3)\r
+ {\r
+ if(node3 && node3->firstChild())\r
+ {\r
+ std::string boardname=SanitizeSingleString(node3->firstChild()->getNodeValue());\r
+ StringFunctions::LowerCase(boardname,boardname);\r
+ if(boardname.size()>40)\r
+ {\r
+ boardname.erase(40);\r
+ }\r
+ boards.push_back(boardname);\r
+ }\r
+ node3=XMLGetNextSibling(node3,"Board");\r
+ }\r
+ }\r
+\r
+ m_messages.push_back(message(date,index,boards));\r
+\r
+ node=XMLGetNextSibling(node,"Message");\r
+ }\r
+\r
+ node=XMLGetFirstChild(root,"ExternalMessage");\r
+ while(node)\r
+ {\r
+ std::string type="";\r
+ std::string identity="";\r
+ std::string date="";\r
+ int index=-1;\r
+ std::vector<std::string> boards;\r
+\r
+ Poco::XML::Element *node2=XMLGetFirstChild(node,"Type");\r
+ if(node2 && node2->firstChild())\r
+ {\r
+ type=SanitizeSingleString(node2->firstChild()->getNodeValue());\r
+ }\r
+\r
+ if(type=="Keyed")\r
+ {\r
+ node2=XMLGetFirstChild(node,"Identity");\r
+ if(node2 && node2->firstChild())\r
+ {\r
+ identity=SanitizeSingleString(node2->firstChild()->getNodeValue());\r
+ }\r
+ node2=XMLGetFirstChild(node,"Date");\r
+ if(node2 && node2->firstChild())\r
+ {\r
+ date=SanitizeSingleString(node2->firstChild()->getNodeValue());\r
+ }\r
+ node2=XMLGetFirstChild(node,"Index");\r
+ if(node2 && node2->firstChild())\r
+ {\r
+ std::string indexstr=SanitizeSingleString(node2->firstChild()->getNodeValue());\r
+ StringFunctions::Convert(indexstr,index);\r
+ }\r
+ node2=XMLGetFirstChild(node,"Boards");\r
+ if(node2)\r
+ {\r
+ Poco::XML::Element *node3=XMLGetFirstChild(node2,"Board");\r
+ while(node3)\r
+ {\r
+ if(node3 && node3->firstChild())\r
+ {\r
+ std::string boardname=SanitizeSingleString(node3->firstChild()->getNodeValue());\r
+ StringFunctions::LowerCase(boardname,boardname);\r
+ if(boardname.size()>40)\r
+ {\r
+ boardname.erase(40);\r
+ }\r
+ boards.push_back(boardname);\r
+ }\r
+ node3=XMLGetNextSibling(node3,"Board");\r
+ }\r
+ }\r
+ m_externalmessages.push_back(externalmessage("Keyed",identity,date,index,boards));\r
+ }\r
+\r
+ node=XMLGetNextSibling(node,"ExternalMessage");\r
+ }\r
+ parsed=true;\r
+ }\r
+ catch(...)\r
+ {\r
+ }\r
+\r
+ return parsed;\r
+\r
+ /*\r
TiXmlDocument td;\r
td.Parse(xml.c_str());\r
\r
{\r
return false;\r
}\r
+ */\r
}\r
\r
#include <algorithm>\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/Timespan.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
}\r
else\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
st=m_db->Prepare("INSERT INTO tblBoard(BoardName,DateAdded,SaveReceivedMessages,AddedMethod) VALUES(?,?,?,?);");\r
st.Bind(0,boardname);\r
- st.Bind(1,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
if(m_savemessagesfromnewboards)\r
{\r
st.Bind(2,"true");\r
\r
if(boards.size()<=0)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData Message XML did not contain any boards! "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleAllData Message XML did not contain any boards! "+message["Identifier"]);\r
// remove this identityid from request list\r
RemoveFromRequestList(idparts[1]); \r
return true;\r
}\r
if(xml.GetReplyBoard()=="")\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData Message XML did not contain a reply board! "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleAllData Message XML did not contain a reply board! "+message["Identifier"]);\r
// remove this identityid from request list\r
RemoveFromRequestList(idparts[1]); \r
return true;\r
keypart=StringFunctions::Replace(StringFunctions::Replace(keyparts[1],"-",""),"~","");\r
if(keypart!=uuidparts[1])\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData MessageID in Message doesn't match public key of identity : "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleAllData MessageID in Message doesn't match public key of identity : "+message["Identifier"]);\r
validmessage=false;\r
}\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData Error with identity's public key or Message ID : "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleAllData Error with identity's public key or Message ID : "+message["Identifier"]);\r
validmessage=false;\r
}\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData Error couldn't find identity : "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleAllData Error couldn't find identity : "+message["Identifier"]);\r
validmessage=false;\r
}\r
\r
}\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageRequester::HandleAllData parsed Message XML file : "+message["Identifier"]);\r
+ m_log->debug("MessageRequester::HandleAllData parsed Message XML file : "+message["Identifier"]);\r
\r
}\r
else // couldn't insert - was already in database\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAllData error parsing Message XML file : "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleAllData error parsing Message XML file : "+message["Identifier"]);\r
}\r
\r
RemoveFromRequestList(idparts[1]);\r
\r
const bool MessageRequester::HandleGetFailed(FCPMessage &message)\r
{\r
- DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
std::string requestid;\r
long index;\r
long identityid;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
requestid=idparts[1];\r
StringFunctions::Convert(idparts[2],identityid);\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
+ m_log->error("MessageRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
if(m_maxrequests<1)\r
{\r
m_maxrequests=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxMessageRequests is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxMessageRequests is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxrequests>100)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxMessageRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MaxMessageRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
Option::Instance()->Get("MessageDownloadMaxDaysBackward",tempval);\r
StringFunctions::Convert(tempval,m_maxdaysbackward);\r
if(m_maxdaysbackward<0)\r
{\r
m_maxdaysbackward=0;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MessageDownloadMaxDaysBackward is currently set at "+tempval+". It must be 0 or greater.");\r
+ m_log->error("Option MessageDownloadMaxDaysBackward is currently set at "+tempval+". It must be 0 or greater.");\r
}\r
if(m_maxdaysbackward>30)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MessageDownloadMaxDaysBackward is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MessageDownloadMaxDaysBackward is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
Option::Instance()->Get("MaxPeerMessagesPerDay",tempval);\r
StringFunctions::Convert(tempval,m_maxpeermessages);\r
if(m_maxpeermessages<1)\r
{\r
m_maxpeermessages=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxPeerMessagesPerDay is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxPeerMessagesPerDay is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxpeermessages<20 || m_maxpeermessages>1000)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxPeerMessagesPerDay is currently set at "+tempval+". This value might be incorrectly configured. The suggested value is 200.");\r
+ m_log->warning("Option MaxPeerMessagesPerDay is currently set at "+tempval+". This value might be incorrectly configured. The suggested value is 200.");\r
}\r
Option::Instance()->Get("MaxBoardsPerMessage",tempval);\r
StringFunctions::Convert(tempval,m_maxboardspermessage);\r
if(m_maxboardspermessage<1)\r
{\r
m_maxboardspermessage=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxBoardsPerMessage is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxBoardsPerMessage is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxboardspermessage>20)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxBoardsPerMessage is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MaxBoardsPerMessage is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
\r
Option::Instance()->Get("SaveMessagesFromNewBoards",tempval);\r
\r
void MessageRequester::PopulateIDList()\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
std::string val1;\r
std::string val2;\r
std::string val3;\r
std::string sql;\r
long requestindex;\r
\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-m_maxdaysbackward);\r
+ date-=Poco::Timespan(m_maxdaysbackward,0,0,0,0);\r
\r
sql="SELECT tblIdentity.IdentityID,Day,RequestIndex ";\r
sql+="FROM tblMessageRequests INNER JOIN tblIdentity ON tblMessageRequests.IdentityID=tblIdentity.IdentityID ";\r
- sql+="WHERE FromMessageList='true' AND Found='false' AND Day>='"+date.Format("%Y-%m-%d")+"' ";\r
+ sql+="WHERE FromMessageList='true' AND Found='false' AND Day>='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"' ";\r
if(m_localtrustoverrides==false)\r
{\r
sql+="AND (tblIdentity.LocalMessageTrust IS NULL OR tblIdentity.LocalMessageTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalMessageTrust')) ";\r
\r
m_requesting.push_back(requestid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageRequester::StartRequest requesting "+message["Identifier"]);\r
+ m_log->debug("MessageRequester::StartRequest requesting "+message["Identifier"]);\r
}\r
\r
m_ids[requestid]=true;\r
\r
std::string MessageXML::GetXML()\r
{\r
- TiXmlDocument td;\r
- TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
- TiXmlElement *tid;\r
- TiXmlPrinter tp;\r
+ Poco::AutoPtr<Poco::XML::Document> doc=new Poco::XML::Document;\r
+ //TiXmlDocument td;\r
+ //TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
+ Poco::XML::Element *root=doc->createElement("Message");\r
+ //TiXmlElement *tid;\r
+ //TiXmlPrinter tp;\r
\r
- td.LinkEndChild(tdec);\r
- tid=new TiXmlElement("Message");\r
- td.LinkEndChild(tid);\r
+ doc->appendChild(root);\r
+ //td.LinkEndChild(tdec);\r
+ //tid=new TiXmlElement("Message");\r
+ //td.LinkEndChild(tid);\r
\r
+ root->appendChild(XMLCreateTextElement(doc,"Date",m_date));\r
+ root->appendChild(XMLCreateTextElement(doc,"Time",m_time));\r
+ root->appendChild(XMLCreateCDATAElement(doc,"Subject",m_subject));\r
+ root->appendChild(XMLCreateCDATAElement(doc,"MessageID",m_messageid));\r
+ root->appendChild(XMLCreateCDATAElement(doc,"ReplyBoard",m_replyboard));\r
+ /*\r
tid->LinkEndChild(XMLCreateTextElement("Date",m_date));\r
tid->LinkEndChild(XMLCreateTextElement("Time",m_time));\r
tid->LinkEndChild(XMLCreateCDATAElement("Subject",m_subject));\r
tid->LinkEndChild(XMLCreateCDATAElement("MessageID",m_messageid));\r
tid->LinkEndChild(XMLCreateCDATAElement("ReplyBoard",m_replyboard));\r
+ */\r
+ \r
+ root->appendChild(XMLCreateCDATAElement(doc,"Body",m_body));\r
// a little hack because TinyXML doesn't handle ]]> inside a CDATA section - manually separate into multiple CDATA sections\r
// TinyXML still won't be able to parse past the 1st CDATA section, but other implementations might\r
- tid->LinkEndChild(XMLCreateCDATAElement("Body",StringFunctions::Replace(m_body,"]]>","]]]]><![CDATA[>")));\r
+ //tid->LinkEndChild(XMLCreateCDATAElement("Body",StringFunctions::Replace(m_body,"]]>","]]]]><![CDATA[>")));\r
\r
- TiXmlElement *brds=new TiXmlElement("Boards");\r
- tid->LinkEndChild(brds);\r
+ Poco::XML::Element *brds=doc->createElement("Boards");\r
+ //TiXmlElement *brds=new TiXmlElement("Boards");\r
+ root->appendChild(brds);\r
+ //tid->LinkEndChild(brds);\r
for(std::vector<std::string>::iterator i=m_boards.begin(); i!=m_boards.end(); i++)\r
{\r
std::string boardname=(*i);\r
StringFunctions::Convert(boardname,boardname);\r
- brds->LinkEndChild(XMLCreateCDATAElement("Board",boardname));\r
+ brds->appendChild(XMLCreateCDATAElement(doc,"Board",boardname));\r
+ //brds->LinkEndChild(XMLCreateCDATAElement("Board",boardname));\r
}\r
\r
if(m_inreplyto.size()>0)\r
{\r
- TiXmlElement *rply=new TiXmlElement("InReplyTo");\r
- tid->LinkEndChild(rply);\r
+ Poco::XML::Element *rply=doc->createElement("InReplyTo");\r
+ //TiXmlElement *rply=new TiXmlElement("InReplyTo");\r
+ root->appendChild(rply);\r
+ //tid->LinkEndChild(rply);\r
for(std::map<long,std::string>::iterator j=m_inreplyto.begin(); j!=m_inreplyto.end(); j++)\r
{\r
- TiXmlElement *mess=new TiXmlElement("Message");\r
- rply->LinkEndChild(mess);\r
- mess->LinkEndChild(XMLCreateTextElement("Order",(*j).first));\r
- mess->LinkEndChild(XMLCreateCDATAElement("MessageID",(*j).second));\r
+ Poco::XML::Element *mess=doc->createElement("Message");\r
+ //TiXmlElement *mess=new TiXmlElement("Message");\r
+ rply->appendChild(mess);\r
+ mess->appendChild(XMLCreateTextElement(doc,"Order",(*j).first));\r
+ mess->appendChild(XMLCreateCDATAElement(doc,"MessageID",(*j).second));\r
+ //mess->LinkEndChild(XMLCreateTextElement("Order",(*j).first));\r
+ //mess->LinkEndChild(XMLCreateCDATAElement("MessageID",(*j).second));\r
}\r
}\r
\r
// add attachemnt node if we have attachments\r
if(m_fileattachments.size()>0)\r
{\r
- TiXmlElement *attachments=new TiXmlElement("Attachments");\r
- tid->LinkEndChild(attachments);\r
+ Poco::XML::Element *attachments=doc->createElement("Attachments");\r
+ //TiXmlElement *attachments=new TiXmlElement("Attachments");\r
+ root->appendChild(attachments);\r
+ //tid->LinkEndChild(attachments);\r
for(std::vector<fileattachment>::iterator j=m_fileattachments.begin(); j!=m_fileattachments.end(); j++)\r
{\r
- TiXmlElement *f=new TiXmlElement("File");\r
- attachments->LinkEndChild(f);\r
- f->LinkEndChild(XMLCreateCDATAElement("Key",(*j).m_key));\r
- f->LinkEndChild(XMLCreateTextElement("Size",(*j).m_size));\r
+ Poco::XML::Element *f=doc->createElement("File");\r
+ //TiXmlElement *f=new TiXmlElement("File");\r
+ attachments->appendChild(f);\r
+ //attachments->LinkEndChild(f);\r
+ f->appendChild(XMLCreateCDATAElement(doc,"Key",(*j).m_key));\r
+ f->appendChild(XMLCreateTextElement(doc,"Size",(*j).m_size));\r
+ //f->LinkEndChild(XMLCreateCDATAElement("Key",(*j).m_key));\r
+ //f->LinkEndChild(XMLCreateTextElement("Size",(*j).m_size));\r
}\r
}\r
\r
- td.Accept(&tp);\r
- return std::string(tp.CStr());\r
+ //td.Accept(&tp);\r
+ //return std::string(tp.CStr());\r
+ return GenerateXML(doc);\r
}\r
\r
void MessageXML::Initialize()\r
\r
const bool MessageXML::ParseXML(const std::string &xml)\r
{\r
+ bool parsed=false;\r
+ Poco::XML::DOMParser dp;\r
+\r
+ Initialize();\r
+\r
+ try\r
+ {\r
+ Poco::AutoPtr<Poco::XML::Document> doc=dp.parseString(FixCDATA(xml));\r
+ Poco::XML::Element *root=XMLGetFirstChild(doc,"Message");\r
+ Poco::XML::Element *txt=NULL;\r
+\r
+ txt=XMLGetFirstChild(root,"Date");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_date=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(root,"Time");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_time=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(root,"Subject");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_subject=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(root,"MessageID");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_messageid=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(root,"ReplyBoard");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_replyboard=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ StringFunctions::LowerCase(m_replyboard,m_replyboard);\r
+ if(m_replyboard.size()>40)\r
+ {\r
+ m_replyboard.erase(40);\r
+ }\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(root,"Body");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ m_body=txt->firstChild()->getNodeValue();\r
+ }\r
+ }\r
+ Poco::XML::Element *boards=XMLGetFirstChild(root,"Boards");\r
+ if(boards)\r
+ {\r
+ Poco::XML::Element *board=XMLGetFirstChild(boards,"Board");\r
+ while(board)\r
+ {\r
+ if(board->firstChild())\r
+ {\r
+ std::string boardname=SanitizeSingleString(board->firstChild()->getNodeValue());\r
+ StringFunctions::LowerCase(boardname,boardname);\r
+ if(boardname.size()>40)\r
+ {\r
+ boardname.erase(40);\r
+ }\r
+ m_boards.push_back(boardname);\r
+ }\r
+ board=XMLGetNextSibling(board,"Board");\r
+ }\r
+ }\r
+ Poco::XML::Element *inreplyto=XMLGetFirstChild(root,"InReplyTo");\r
+ if(inreplyto)\r
+ {\r
+ Poco::XML::Element *message=XMLGetFirstChild(inreplyto,"Message");\r
+ while(message)\r
+ {\r
+ Poco::XML::Element *orderel=XMLGetFirstChild(message,"Order");\r
+ Poco::XML::Element *messageidel=XMLGetFirstChild(message,"MessageID");\r
+ if(orderel && orderel->firstChild() && messageidel && messageidel->firstChild())\r
+ {\r
+ int order=-1;\r
+ std::string messageid="";\r
+\r
+ StringFunctions::Convert(orderel->firstChild()->getNodeValue(),order);\r
+ messageid=messageidel->firstChild()->getNodeValue();\r
+\r
+ if(order!=-1 && messageid!="")\r
+ {\r
+ m_inreplyto[order]=messageid;\r
+ }\r
+ }\r
+ message=XMLGetNextSibling(message,"Message");\r
+ }\r
+ }\r
+ Poco::XML::Element *attachments=XMLGetFirstChild(root,"Attachments");\r
+ if(attachments)\r
+ {\r
+ Poco::XML::Element *file=XMLGetFirstChild(attachments,"File");\r
+ while(file)\r
+ {\r
+ Poco::XML::Element *keyel=XMLGetFirstChild(file,"Key");\r
+ Poco::XML::Element *sizeel=XMLGetFirstChild(file,"Size");\r
+\r
+ if(keyel && keyel->firstChild() && sizeel && sizeel->firstChild())\r
+ {\r
+ int size=-1;\r
+ std::string key="";\r
+ \r
+ StringFunctions::Convert(sizeel->firstChild()->getNodeValue(),size);\r
+ key=keyel->firstChild()->getNodeValue();\r
+\r
+ if(size!=-1 && key!="")\r
+ {\r
+ m_fileattachments.push_back(fileattachment(key,size));\r
+ }\r
+ }\r
+\r
+ file=XMLGetNextSibling(file,"File");\r
+ }\r
+ }\r
+\r
+ parsed=true;\r
+\r
+ }\r
+ catch(...)\r
+ {\r
+ }\r
+\r
+ return parsed;\r
+\r
+/*\r
TiXmlDocument td;\r
td.Parse(xml.c_str());\r
\r
{\r
return false;\r
}\r
+ */\r
}\r
+++ /dev/null
-#include "../../include/freenet/periodicdbmaintenance.h"\r
-#include "../../include/stringfunctions.h"\r
-#include "../../include/option.h"\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-PeriodicDBMaintenance::PeriodicDBMaintenance()\r
-{\r
- std::string tempval;\r
-\r
- m_check10mins.SetToGMTime();\r
- m_check30mins.SetToGMTime();\r
- m_check1hour.SetToGMTime();\r
- m_check6hours.SetToGMTime();\r
- m_check1day.SetToGMTime();\r
-\r
- // set back times so they will do their first maintenance soon ( within the next hour ) - stagger so not all run at once\r
- m_check30mins.Add(0,-5);\r
- m_check1hour.Add(0,-42);\r
- m_check6hours.Add(0,-1,-5);\r
- m_check1day.Add(0,0,-23);\r
-\r
- tempval="180";\r
- Option::Instance()->Get("DeleteMessagesOlderThan",tempval);\r
- StringFunctions::Convert(tempval,m_deletemessagesolderthan);\r
-\r
-}\r
-\r
-void PeriodicDBMaintenance::Do10MinuteMaintenance()\r
-{\r
-\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"PeriodicDBMaintenance::Do10MinuteMaintenance");\r
-}\r
-\r
-void PeriodicDBMaintenance::Do30MinuteMaintenance()\r
-{\r
-\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"PeriodicDBMaintenance::Do30MinuteMaintenance");\r
-}\r
-\r
-void PeriodicDBMaintenance::Do1HourMaintenance()\r
-{\r
- // recalculate all trust levels - this is CPU instensive\r
- // do 1 identity at a time as doing it with 1 UPDATE statement locks that database for the duration\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT TargetIdentityID,PeerMessageTrust,PeerTrustListTrust FROM vwCalculatedPeerTrust;");\r
- SQLite3DB::Statement upd=m_db->Prepare("UPDATE tblIdentity SET PeerMessageTrust=?, PeerTrustListTrust=? WHERE IdentityID=?");\r
- st.Step();\r
- while(st.RowReturned())\r
- {\r
- int identityid=0;\r
- int trust=0;\r
- \r
- st.ResultInt(0,identityid);\r
-\r
- upd.Bind(0,identityid);\r
- if(st.ResultNull(1)==false)\r
- {\r
- trust=0;\r
- st.ResultInt(1,trust);\r
- upd.Bind(0,trust);\r
- }\r
- else\r
- {\r
- upd.Bind(0);\r
- }\r
- if(st.ResultNull(2)==false)\r
- {\r
- trust=0;\r
- st.ResultInt(2,trust);\r
- upd.Bind(1,trust);\r
- }\r
- else\r
- {\r
- upd.Bind(1);\r
- }\r
- upd.Bind(2,identityid);\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Step();\r
- }\r
-\r
- // set null peer trust for identities without a calculated trust\r
- st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE IdentityID NOT IN (SELECT TargetIdentityID FROM vwCalculatedPeerTrust);");\r
- upd=m_db->Prepare("UPDATE tblIdentity SET PeerMessageTrust=NULL, PeerTrustListTrust=NULL WHERE IdentityID=?;");\r
- st.Step();\r
- while(st.RowReturned())\r
- {\r
- int identityid=0;\r
- st.ResultInt(0,identityid);\r
- upd.Bind(0,identityid);\r
- upd.Step();\r
- upd.Reset();\r
- st.Step();\r
- }\r
-\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"PeriodicDBMaintenance::Do1HourMaintenance");\r
-}\r
-\r
-void PeriodicDBMaintenance::Do6HourMaintenance()\r
-{\r
-\r
- // if we remove a board and the reply boardid is still set to it, we need to replace it with a boardid that does exist\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT MessageID FROM tblMessage WHERE ReplyBoardID NOT IN (SELECT BoardID FROM tblBoard);");\r
- SQLite3DB::Statement st2=m_db->Prepare("SELECT BoardID FROM tblMessageBoard WHERE MessageID=?;");\r
- SQLite3DB::Statement upd=m_db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE MessageID=?;");\r
- st.Step();\r
- while(st.RowReturned())\r
- {\r
- // find a valid boardid for the message\r
- int messageid=0;\r
- int boardid=0;\r
-\r
- st.ResultInt(0,messageid);\r
-\r
- st2.Bind(0,messageid);\r
- st2.Step();\r
- if(st2.RowReturned())\r
- {\r
- st2.ResultInt(0,boardid);\r
- upd.Bind(0,boardid);\r
- upd.Bind(1,messageid);\r
- upd.Step();\r
- upd.Reset();\r
- }\r
- st2.Reset();\r
- \r
- st.Step();\r
- }\r
-\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"PeriodicDBMaintenance::Do6HourMaintenance");\r
-}\r
-\r
-void PeriodicDBMaintenance::Do1DayMaintenance()\r
-{\r
- DateTime date;\r
-\r
- // delete all puzzles 2 or more days old\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-2);\r
- m_db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");\r
- m_db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");\r
-\r
- // delete all identities we've never seen and were added more than 20 days ago\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-20);\r
- m_db->Execute("DELETE FROM tblIdentity WHERE LastSeen IS NULL AND DateAdded<'"+date.Format("%Y-%m-%d")+"';");\r
-\r
- // delete old identity requests - we don't need them anymore\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-2);\r
- m_db->Execute("DELETE FROM tblIdentityRequests WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
-\r
- // delete old board list inserts/requests - we don't need them anymore\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-2);\r
- m_db->Execute("DELETE FROM tblBoardListInserts WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
- m_db->Execute("DELETE FROM tblBoardListRequests WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
-\r
- // delete old local identity inserts - we don't need them anymore\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-2);\r
- m_db->Execute("DELETE FROM tblLocalIdentityInserts WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
-\r
- // delete old message list inserts/requests - we don't need them anymore\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-2);\r
- m_db->Execute("DELETE FROM tblMessageListInserts WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
- m_db->Execute("DELETE FROM tblMessageListRequests WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
-\r
- // delete old trust list inserts/requests - we don't need them anymore\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-2);\r
- m_db->Execute("DELETE FROM tblTrustListInserts WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
- m_db->Execute("DELETE FROM tblTrustListRequests WHERE Day<'"+date.Format("%Y-%m-%d")+"';");\r
-\r
- // delete trust lists from identities we aren't trusting anymore\r
- m_db->Execute("DELETE FROM tblPeerTrust WHERE IdentityID NOT IN (SELECT IdentityID FROM tblIdentity WHERE (LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust')) AND (PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust')));");\r
-\r
- // remove identityid from messages where the identity has been deleted\r
- m_db->Execute("UPDATE tblMessage SET IdentityID=NULL WHERE IdentityID NOT IN (SELECT IdentityID FROM tblIdentity);");\r
-\r
- // try to re-attach messages from identities that were previously deleted, but have been since re-added\r
- // first get the names from messages that have a NULL IdentityID\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT FromName FROM tblMessage WHERE IdentityID IS NULL GROUP BY FromName;");\r
- st.Step();\r
- while(st.RowReturned())\r
- {\r
- std::string name="";\r
- std::string namepart="";\r
- std::string publickey="";\r
- int identityid=0;\r
- st.ResultText(0,name);\r
-\r
- std::vector<std::string> parts;\r
- StringFunctions::Split(name,"@",parts);\r
-\r
- // name can have a @ in it - so reattach all parts except the last which is the key\r
- for(long i=0; i<parts.size()-1; i++)\r
- {\r
- if(i!=0)\r
- {\r
- namepart+="@";\r
- }\r
- namepart+=parts[i];\r
- }\r
-\r
- // find identities with this name\r
- SQLite3DB::Statement st2=m_db->Prepare("SELECT IdentityID,PublicKey FROM tblIdentity WHERE Name=?;");\r
- st2.Bind(0,namepart);\r
- st2.Step();\r
- while(st2.RowReturned())\r
- {\r
- publickey="";\r
- identityid=0;\r
- st2.ResultText(1,publickey);\r
- // check if public key matches 2nd part\r
- if(parts.size()>1 && publickey.find(parts[1])==4)\r
- {\r
- // we have the identity - so update the messages table with the identityid\r
- st2.ResultInt(0,identityid);\r
-\r
- SQLite3DB::Statement st3=m_db->Prepare("UPDATE tblMessage SET IdentityID=? WHERE FromName=? AND IdentityID IS NULL;");\r
- st3.Bind(0,identityid);\r
- st3.Bind(1,name);\r
- st3.Step();\r
- }\r
- st2.Step();\r
- }\r
-\r
- st.Step();\r
- }\r
-\r
- // delete single use identities that are older than 7 days\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-7);\r
- st=m_db->Prepare("DELETE FROM tblIdentity WHERE SingleUse='true' AND DateAdded<?;");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
- st.Step();\r
-\r
- // delete local single use identities that are older than 7 days\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-7);\r
- st=m_db->Prepare("DELETE FROM tblLocalIdentity WHERE SingleUse='true' AND DateCreated<?;");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
- st.Step();\r
-\r
- // delete old messages\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-m_deletemessagesolderthan);\r
- st=m_db->Prepare("DELETE FROM tblMessage WHERE MessageDate<?;");\r
- st.Bind(0,date.Format("%Y-%m-%d"));\r
- st.Step();\r
-\r
- // delete tblIdentityTrust for local identities and identities that have been deleted\r
- m_db->Execute("DELETE FROM tblIdentityTrust WHERE LocalIdentityID NOT IN (SELECT LocalIdentityID FROM tblLocalIdentity);");\r
- m_db->Execute("DELETE FROM tblIdentityTrust WHERE IdentityID NOT IN (SELECT IdentityID FROM tblIdentity);");\r
-\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"PeriodicDBMaintenance::Do1DayMaintenance");\r
-\r
-}\r
-\r
-void PeriodicDBMaintenance::Process()\r
-{\r
- DateTime now;\r
- now.SetToGMTime();\r
- \r
- if(m_check10mins<=(now-((1.0/1440.0)*10.0)))\r
- {\r
- Do10MinuteMaintenance();\r
- m_check10mins=now;\r
- }\r
- if(m_check30mins<=(now-((1.0/1440.0)*30.0)))\r
- {\r
- Do30MinuteMaintenance();\r
- m_check30mins=now;\r
- }\r
- if(m_check1hour<=(now-(1.0/24.0)))\r
- {\r
- Do1HourMaintenance();\r
- m_check1hour=now;\r
- }\r
- if(m_check6hours<=(now-(1.0/4.0)))\r
- {\r
- Do6HourMaintenance();\r
- m_check6hours=now;\r
- }\r
- if(m_check1day<=(now-(1.0)))\r
- {\r
- Do1DayMaintenance();\r
- m_check1day=now;\r
- }\r
-\r
-}\r
-\r
-void PeriodicDBMaintenance::RegisterWithThread(FreenetMasterThread *thread)\r
-{\r
- thread->RegisterPeriodicProcessor(this);\r
-}\r
#include "../../include/freenet/siteinserter.h"\r
#include "../../include/global.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timespan.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
// only do 1 insert at a time\r
if(m_inserting.size()==0)\r
{\r
- DateTime date;\r
- date.SetToGMTime();\r
- date.SetHour(0);\r
- date.SetMinute(0);\r
- date.SetSecond(0);\r
- date.Normalize();\r
+ Poco::DateTime date;\r
+ date.assign(date.year(),date.month(),date.day(),0,0,0);\r
\r
SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID FROM tblLocalIdentity WHERE PublishFreesite='true' AND (LastInsertedFreesite IS NULL OR LastInsertedFreesite<?);");\r
- st.Bind(0,date.Format("%Y-%m-%d"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
\r
st.Step();\r
if(st.RowReturned())\r
StringFunctions::Convert(edition,editionstr);\r
}\r
\r
+ // make SSK a USK\r
+ if(key.find("SSK@")==0)\r
+ {\r
+ key.erase(0,3);\r
+ key="USK"+key;\r
+ }\r
+ key+=m_messagebase+"/"+editionstr+"/";\r
+ uskkey=key;\r
+\r
filename=name+"-template.htm";\r
FILE *infile=fopen(filename.c_str(),"r+b");\r
if(!infile)\r
// pages["boardlist.htm"]=GenerateBoardList(htmltemplate,localidentityid,name);\r
}\r
\r
- // make SSK a USK\r
- if(key.find("SSK@")==0)\r
- {\r
- key.erase(0,3);\r
- key="USK"+key;\r
- }\r
- key+=m_messagebase+"/"+editionstr+"/";\r
- uskkey=key;\r
-\r
}\r
else\r
{\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::GeneratePages unable to open "+filename+" or site-template.htm.");\r
+ m_log->error("SiteInserter::GeneratePages unable to open "+filename+" or site-template.htm.");\r
}\r
\r
// get extra files that the user wants to add to the Freesite\r
}\r
else\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::GeneratePages could not include user file "+(*i));\r
+ m_log->error("SiteInserter::GeneratePages could not include user file "+(*i));\r
}\r
}\r
}\r
std::string SiteInserter::GenerateTrustList(const std::string &htmltemplate, const long localidentityid, const std::string &name)\r
{\r
std::string content="";\r
- DateTime date;\r
+ Poco::DateTime date;\r
\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-20);\r
+ date-=Poco::Timespan(20,0,0,0,0);\r
SQLite3DB::Statement st=m_db->Prepare("SELECT Name,PublicKey,tblIdentityTrust.LocalMessageTrust,tblIdentityTrust.LocalTrustListTrust,tblIdentity.IdentityID,tblIdentityTrust.MessageTrustComment,tblIdentityTrust.TrustListTrustComment,tblIdentity.FreesiteEdition FROM tblIdentity LEFT JOIN (SELECT IdentityID,LocalMessageTrust,LocalTrustListTrust,MessageTrustComment,TrustListTrustComment FROM tblIdentityTrust WHERE LocalIdentityID=?) AS 'tblIdentityTrust' ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID WHERE PublicKey IS NOT NULL AND LastSeen IS NOT NULL AND LastSeen>=? ORDER BY Name COLLATE NOCASE;");\r
st.Bind(0,localidentityid);\r
- st.Bind(1,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
\r
content+="<table>";\r
\r
RemoveFromInsertList(localidentityid);\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"SiteInserter::HandlePutFailed failed to insert Freesite, Freenet error code : "+message["Code"]);\r
+ m_log->error("SiteInserter::HandlePutFailed failed to insert Freesite, Freenet error code : "+message["Code"]);\r
\r
return true;\r
}\r
std::vector<std::string> uriparts;\r
long localidentityid;\r
int edition=-1;\r
- DateTime now;\r
-\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(idparts[1],localidentityid);\r
}\r
\r
SQLite3DB::Statement st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedFreesite=?, FreesiteEdition=? WHERE LocalIdentityID=?;");\r
- st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
st.Bind(1,edition);\r
st.Bind(2,localidentityid);\r
st.Step();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"SiteInserter::HandlePutSuccessful successfully inserted Freesite.");\r
+ m_log->information("SiteInserter::HandlePutSuccessful successfully inserted Freesite.");\r
\r
RemoveFromInsertList(localidentityid);\r
\r
#include "../../include/freenet/trustlistxml.h"\r
#include "../../include/stringfunctions.h"\r
\r
+#include <Poco/Timespan.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/DateTimeParser.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
\r
void TrustListInserter::CheckForNeededInsert()\r
{\r
- DateTime date;\r
- date.SetToGMTime();\r
- int currentday=date.GetDay();\r
- date.Add(0,0,-6);\r
+ Poco::DateTime date;\r
+ int currentday=date.day();\r
+ date-=Poco::Timespan(0,6,0,0,0);\r
// insert trust lists every 6 hours - if 6 hours ago was different day then set to midnight of current day to insert list today ASAP\r
- if(currentday!=date.GetDay())\r
+ if(currentday!=date.day())\r
{\r
- date.Set(date.GetYear(),date.GetMonth(),currentday);\r
+ date.assign(date.year(),date.month(),currentday,0,0,0);\r
}\r
- SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID, PrivateKey FROM tblLocalIdentity WHERE PrivateKey IS NOT NULL AND PrivateKey <> '' AND PublishTrustList='true' AND InsertingTrustList='false' AND (LastInsertedTrustList<='"+date.Format("%Y-%m-%d %H:%M:%S")+"' OR LastInsertedTrustList IS NULL);");\r
+ SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID, PrivateKey FROM tblLocalIdentity WHERE PrivateKey IS NOT NULL AND PrivateKey <> '' AND PublishTrustList='true' AND InsertingTrustList='false' AND (LastInsertedTrustList<='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")+"' OR LastInsertedTrustList IS NULL);");\r
\r
if(rs.Empty()==false)\r
{\r
if(message["Identifier"].find("TrustListInserter")==0)\r
{\r
\r
- DateTime now;\r
+ Poco::DateTime now;\r
std::vector<std::string> idparts;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
\r
// no action for URIGenerated\r
// non USK\r
if(idparts[0]=="TrustListInserter")\r
{\r
- m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false', LastInsertedTrustList='"+now.Format("%Y-%m-%d %H:%M:%S")+"' WHERE LocalIdentityID="+idparts[1]+";");\r
+ m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false', LastInsertedTrustList='"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S")+"' WHERE LocalIdentityID="+idparts[1]+";");\r
m_db->Execute("INSERT INTO tblTrustListInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"TrustListInserter::HandleMessage inserted TrustList xml");\r
+ m_log->debug("TrustListInserter::HandleMessage inserted TrustList xml");\r
}\r
return true;\r
}\r
if(idparts[0]=="TrustListInserter")\r
{\r
m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false' WHERE LocalIdentityID="+idparts[1]+";");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"TrustListInserter::HandleMessage failure inserting TrustList xml. Code="+message["Code"]+" Description="+message["CodeDescription"]);\r
+ m_log->debug("TrustListInserter::HandleMessage failure inserting TrustList xml. Code="+message["Code"]+" Description="+message["CodeDescription"]);\r
\r
// if code 9 (collision), then insert index into inserted table\r
if(message["Code"]=="9")\r
void TrustListInserter::Initialize()\r
{\r
Option::Instance()->Get("MessageBase",m_messagebase);\r
- m_lastchecked.SetToGMTime();\r
+ m_lastchecked=Poco::Timestamp();\r
}\r
\r
void TrustListInserter::Process()\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
\r
// check every minute\r
- if(m_lastchecked<=(now-(1.0/1440.0)))\r
+ if(m_lastchecked<=(now-Poco::Timespan(0,0,1,0,0)))\r
{\r
CheckForNeededInsert();\r
m_lastchecked=now;\r
std::string publickey;\r
int messagetrust;\r
int trustlisttrust;\r
- DateTime now,date,dateminus30,tempdate;\r
+ Poco::DateTime now,date,dateminus30,tempdate;\r
int index;\r
std::string indexstr;\r
std::string localidentityidstr;\r
bool add=false;\r
std::string dateadded="";\r
\r
- now.SetToGMTime();\r
- date.SetToGMTime();\r
- dateminus30.SetToGMTime();\r
- dateminus30.Add(0,0,0,-30);\r
+ dateminus30-=Poco::Timespan(30,0,0,0,0);\r
\r
// insert all identities not in trust list already\r
m_db->Execute("INSERT INTO tblIdentityTrust(LocalIdentityID,IdentityID) SELECT LocalIdentityID,IdentityID FROM tblLocalIdentity,tblIdentity WHERE LocalIdentityID || '_' || IdentityID NOT IN (SELECT LocalIdentityID || '_' || IdentityID FROM tblIdentityTrust);");\r
SQLite3DB::Statement countst=m_db->Prepare("SELECT COUNT(*) FROM tblMessage WHERE IdentityID=? AND MessageDate>=?;");\r
\r
// build the xml file - we only want to add identities that we recently saw, otherwise we could be inserting a ton of identities\r
- date.Add(0,0,0,-15); // identities seen in last 15 days - the maintenance page lets us delete identities not seen in 20 days, so this gives us a window where the identity won't be deleted and then found in a trust list and readded immediately\r
+ date-=Poco::Timespan(15,0,0,0,0); // identities seen in last 15 days - the maintenance page lets us delete identities not seen in 20 days, so this gives us a window where the identity won't be deleted and then found in a trust list and readded immediately\r
//SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey, LocalMessageTrust, LocalTrustListTrust, MessageTrustComment, TrustListTrustComment FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey<>'' AND LastSeen>=?;");\r
// we want to order by public key so we can't do identity correllation based on the sequence of identities in the list.\r
SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey, tblIdentityTrust.LocalMessageTrust, tblIdentityTrust.LocalTrustListTrust, tblIdentityTrust.MessageTrustComment, tblIdentityTrust.TrustListTrustComment, tblIdentity.IdentityID, tblIdentity.DateAdded FROM tblIdentity INNER JOIN tblIdentityTrust ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID WHERE PublicKey IS NOT NULL AND PublicKey<>'' AND LastSeen>=? AND tblIdentityTrust.LocalIdentityID=? ORDER BY PublicKey;");\r
- st.Bind(0,date.Format("%Y-%m-%d"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
st.Bind(1,localidentityid);\r
st.Step();\r
while(st.RowReturned())\r
\r
// add the identity to the trust list if they have posted a message in the last 30 days\r
countst.Bind(0,identityid);\r
- countst.Bind(1,dateminus30.Format("%Y-%m-%d"));\r
+ countst.Bind(1,Poco::DateTimeFormatter::format(dateminus30,"%Y-%m-%d"));\r
countst.Step();\r
if(countst.RowReturned())\r
{\r
// no messages in last 30 days - add the identity if we learned about them less than 5 days ago\r
if(add==false && dateadded!="")\r
{\r
- tempdate.Set(dateadded);\r
- if(tempdate>=(now-5.0))\r
+ int tzdiff=0;\r
+ if(Poco::DateTimeParser::tryParse(dateadded,tempdate,tzdiff)==false)\r
+ {\r
+ tempdate=Poco::Timestamp();\r
+ m_log->fatal("TrustListInserter::StartInsert could not parse date "+dateadded);\r
+ }\r
+ if(tempdate>=(now-Poco::Timespan(5,0,0,0,0)))\r
{\r
add=true;\r
}\r
// get next insert index\r
st=m_db->Prepare("SELECT MAX(InsertIndex) FROM tblTrustListInserts WHERE LocalIdentityID=? AND Day=?;");\r
st.Bind(0,localidentityid);\r
- st.Bind(1,now.Format("%Y-%m-%d"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
st.Step();\r
\r
index=0;\r
StringFunctions::Convert(data.size(),datasizestr);\r
\r
message.SetName("ClientPut");\r
- message["URI"]=privatekey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|TrustList|"+indexstr+".xml";\r
+ message["URI"]=privatekey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|TrustList|"+indexstr+".xml";\r
message["Identifier"]="TrustListInserter|"+localidentityidstr+"|"+indexstr+"|"+message["URI"];\r
message["UploadFrom"]="direct";\r
message["DataLength"]=datasizestr;\r
// insert to USK\r
message.Reset();\r
message.SetName("ClientPutComplexDir");\r
- message["URI"]="USK"+privatekey.substr(3)+m_messagebase+"|"+now.Format("%Y.%m.%d")+"|TrustList/0/";\r
+ message["URI"]="USK"+privatekey.substr(3)+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y.%m.%d")+"|TrustList/0/";\r
message["Identifier"]="TrustListInserterUSK|"+message["URI"];\r
message["DefaultName"]="TrustList.xml";\r
message["Files.0.Name"]="TrustList.xml";\r
#include "../../include/stringfunctions.h"\r
#include "../../include/freenet/trustlistxml.h"\r
\r
+#include <Poco/DateTimeFormatter.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
\r
const bool TrustListRequester::HandleAllData(FCPMessage &message)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
SQLite3DB::Statement st;\r
SQLite3DB::Statement trustst;\r
std::vector<std::string> idparts;\r
long identityid;\r
long index;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(message["DataLength"],datalength);\r
StringFunctions::Convert(idparts[1],identityid);\r
if(st.RowReturned()==false)\r
{\r
idinsert.Bind(0,identity);\r
- idinsert.Bind(1,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ idinsert.Bind(1,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
idinsert.Bind(2,"trust list of "+publisherid);\r
idinsert.Step(true);\r
id=idinsert.GetLastInsertRowID();\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"TrustListRequester::HandleAllData parsed TrustList XML file : "+message["Identifier"]);\r
+ m_log->debug("TrustListRequester::HandleAllData parsed TrustList XML file : "+message["Identifier"]);\r
}\r
else\r
{\r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"TrustListRequester::HandleAllData error parsing TrustList XML file : "+message["Identifier"]);\r
+ m_log->error("TrustListRequester::HandleAllData error parsing TrustList XML file : "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
\r
const bool TrustListRequester::HandleGetFailed(FCPMessage &message)\r
{\r
- DateTime now;\r
SQLite3DB::Statement st;\r
std::vector<std::string> idparts;\r
long identityid;\r
long index;\r
\r
- now.SetToGMTime();\r
StringFunctions::Split(message["Identifier"],"|",idparts);\r
StringFunctions::Convert(idparts[1],identityid);\r
StringFunctions::Convert(idparts[2],index); \r
st.Step();\r
st.Finalize();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"TrustListRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
+ m_log->error("TrustListRequester::HandleGetFailed fatal error requesting "+message["Identifier"]);\r
}\r
\r
// remove this identityid from request list\r
if(m_maxrequests<1)\r
{\r
m_maxrequests=1;\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"Option MaxTrustListRequests is currently set at "+tempval+". It must be 1 or greater.");\r
+ m_log->error("Option MaxTrustListRequests is currently set at "+tempval+". It must be 1 or greater.");\r
}\r
if(m_maxrequests>100)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_WARNING,"Option MaxTrustListRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
+ m_log->warning("Option MaxTrustListRequests is currently set at "+tempval+". This value might be incorrectly configured.");\r
}\r
- m_tempdate.SetToGMTime();\r
+ m_tempdate=Poco::Timestamp();\r
}\r
\r
void TrustListRequester::PopulateIDList()\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
int id;\r
std::string sql;\r
\r
- date.SetToGMTime();\r
-\r
// select identities we want to query (we've seen them today and they are publishing trust list) - sort by their trust level (descending) with secondary sort on how long ago we saw them (ascending)\r
sql="SELECT IdentityID FROM tblIdentity ";\r
- sql+="WHERE Name IS NOT NULL AND Name <> '' AND PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+date.Format("%Y-%m-%d")+"' AND PublishTrustList='true' AND LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') )";\r
+ sql+="WHERE Name IS NOT NULL AND Name <> '' AND PublicKey IS NOT NULL AND PublicKey <> '' AND LastSeen>='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"' AND PublishTrustList='true' AND LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') )";\r
sql+="ORDER BY LocalTrustListTrust DESC, LastSeen;";\r
\r
SQLite3DB::Statement st=m_db->Prepare(sql);\r
\r
void TrustListRequester::StartRequest(const long &identityid)\r
{\r
- DateTime now;\r
+ Poco::DateTime now;\r
FCPMessage message;\r
std::string publickey;\r
int index;\r
{\r
st.ResultText(0,publickey);\r
\r
- now.SetToGMTime();\r
-\r
SQLite3DB::Statement st2=m_db->Prepare("SELECT MAX(RequestIndex) FROM tblTrustListRequests WHERE Day=? AND IdentityID=?;");\r
- st2.Bind(0,now.Format("%Y-%m-%d"));\r
+ st2.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
st2.Bind(1,identityid);\r
st2.Step();\r
\r
StringFunctions::Convert(identityid,identityidstr);\r
\r
message.SetName("ClientGet");\r
- message["URI"]=publickey+m_messagebase+"|"+now.Format("%Y-%m-%d")+"|TrustList|"+indexstr+".xml";\r
+ message["URI"]=publickey+m_messagebase+"|"+Poco::DateTimeFormatter::format(now,"%Y-%m-%d")+"|TrustList|"+indexstr+".xml";\r
message["Identifier"]=m_fcpuniquename+"|"+identityidstr+"|"+indexstr+"|"+message["URI"];\r
message["ReturnType"]="direct";\r
message["MaxSize"]="1000000"; // 1 MB\r
\r
std::string TrustListXML::GetXML()\r
{\r
- TiXmlDocument td;\r
- TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
- TiXmlElement *tid;\r
- TiXmlPrinter tp;\r
+ Poco::AutoPtr<Poco::XML::Document> doc=new Poco::XML::Document;\r
+ //TiXmlDocument td;\r
+ //TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
+ Poco::XML::Element *root=doc->createElement("TrustList");\r
+ //TiXmlElement *tid;\r
+ //TiXmlPrinter tp;\r
\r
- td.LinkEndChild(tdec);\r
- tid=new TiXmlElement("TrustList");\r
- td.LinkEndChild(tid);\r
+ doc->appendChild(root);\r
+ //td.LinkEndChild(tdec);\r
+ //tid=new TiXmlElement("TrustList");\r
+ //td.LinkEndChild(tid);\r
\r
for(std::vector<trust>::iterator i=m_trust.begin(); i!=m_trust.end(); i++)\r
{\r
std::string trustlisttrust;\r
StringFunctions::Convert((*i).m_messagetrust,messagetrust);\r
StringFunctions::Convert((*i).m_trustlisttrust,trustlisttrust);\r
- TiXmlElement *tr=new TiXmlElement("Trust");\r
- tid->LinkEndChild(tr);\r
- tr->LinkEndChild(XMLCreateCDATAElement("Identity",(*i).m_identity));\r
+ Poco::XML::Element *tr=doc->createElement("Trust");\r
+ //TiXmlElement *tr=new TiXmlElement("Trust");\r
+ root->appendChild(tr);\r
+ //tid->LinkEndChild(tr);\r
+ tr->appendChild(XMLCreateCDATAElement(doc,"Identity",(*i).m_identity));\r
+ //tr->LinkEndChild(XMLCreateCDATAElement("Identity",(*i).m_identity));\r
if((*i).m_messagetrust>=0)\r
{\r
- tr->LinkEndChild(XMLCreateTextElement("MessageTrustLevel",messagetrust));\r
+ tr->appendChild(XMLCreateTextElement(doc,"MessageTrustLevel",messagetrust));\r
+ //tr->LinkEndChild(XMLCreateTextElement("MessageTrustLevel",messagetrust));\r
}\r
if((*i).m_trustlisttrust>=0)\r
{\r
- tr->LinkEndChild(XMLCreateTextElement("TrustListTrustLevel",trustlisttrust));\r
+ tr->appendChild(XMLCreateTextElement(doc,"TrustListTrustLevel",trustlisttrust));\r
+ //tr->LinkEndChild(XMLCreateTextElement("TrustListTrustLevel",trustlisttrust));\r
}\r
if((*i).m_messagetrustcomment!="")\r
{\r
- tr->LinkEndChild(XMLCreateCDATAElement("MessageTrustComment",(*i).m_messagetrustcomment));\r
+ tr->appendChild(XMLCreateTextElement(doc,"MessageTrustComment",(*i).m_messagetrustcomment));\r
+ //tr->LinkEndChild(XMLCreateCDATAElement("MessageTrustComment",(*i).m_messagetrustcomment));\r
}\r
if((*i).m_trustlisttrustcomment!="")\r
{\r
- tr->LinkEndChild(XMLCreateCDATAElement("TrustListTrustComment",(*i).m_trustlisttrustcomment));\r
+ tr->appendChild(XMLCreateTextElement(doc,"TrustListTrustComment",(*i).m_trustlisttrustcomment));\r
+ //tr->LinkEndChild(XMLCreateCDATAElement("TrustListTrustComment",(*i).m_trustlisttrustcomment));\r
}\r
}\r
\r
- td.Accept(&tp);\r
- return std::string(tp.CStr());\r
+ //td.Accept(&tp);\r
+ //return std::string(tp.CStr());\r
+ return GenerateXML(doc);\r
}\r
\r
void TrustListXML::Initialize()\r
\r
const bool TrustListXML::ParseXML(const std::string &xml)\r
{\r
+\r
+ bool parsed=false;\r
+ Poco::XML::DOMParser dp;\r
+\r
+ Initialize();\r
+\r
+ try\r
+ {\r
+ Poco::AutoPtr<Poco::XML::Document> doc=dp.parseString(FixCDATA(xml));\r
+ Poco::XML::Element *root=XMLGetFirstChild(doc,"TrustList");\r
+ Poco::XML::Element *trustel=NULL;\r
+ Poco::XML::Element *txt=NULL;\r
+\r
+ std::vector<std::string> foundkeys;\r
+\r
+ trustel=XMLGetFirstChild(root,"Trust");\r
+ while(trustel)\r
+ {\r
+ std::string identity="";\r
+ int messagetrust=-1;\r
+ int trustlisttrust=-1;\r
+ std::string messagetrustcomment="";\r
+ std::string trustlisttrustcomment="";\r
+\r
+ txt=XMLGetFirstChild(trustel,"Identity");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ identity=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(trustel,"MessageTrustLevel");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ std::string mtl=txt->firstChild()->getNodeValue();\r
+ StringFunctions::Convert(mtl,messagetrust);\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(trustel,"TrustListTrustLevel");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ std::string tltl=txt->firstChild()->getNodeValue();\r
+ StringFunctions::Convert(tltl,trustlisttrust);\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(trustel,"MessageTrustComment");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ messagetrustcomment=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+ txt=XMLGetFirstChild(trustel,"TrustListTrustComment");\r
+ if(txt)\r
+ {\r
+ if(txt->firstChild())\r
+ {\r
+ trustlisttrustcomment=SanitizeSingleString(txt->firstChild()->getNodeValue());\r
+ }\r
+ }\r
+\r
+ if(identity!="" && messagetrust>=-1 && messagetrust<=100 && trustlisttrust>=-1 && trustlisttrust<=100)\r
+ {\r
+ // check so we don't add the same identity multiple times from a trust list\r
+ if(std::find(foundkeys.begin(),foundkeys.end(),identity)==foundkeys.end())\r
+ {\r
+ foundkeys.push_back(identity);\r
+ m_trust.push_back(trust(identity,messagetrust,trustlisttrust,messagetrustcomment,trustlisttrustcomment));\r
+ }\r
+ }\r
+ else\r
+ {\r
+ m_log->error("TrustListXML::ParseXML malformed Trust in TrustList.xml");\r
+ }\r
+\r
+ trustel=XMLGetNextSibling(root,"Trust");\r
+ }\r
+\r
+ parsed=true;\r
+ }\r
+ catch(...)\r
+ {\r
+ }\r
+\r
+ return parsed;\r
+\r
+ /*\r
TiXmlDocument td;\r
td.Parse(xml.c_str());\r
\r
{\r
return false;\r
}\r
+ */\r
}\r
#include "../../include/freenet/unkeyedidcreator.h"\r
#include "../../include/stringfunctions.h"\r
\r
+#include <Poco/Timestamp.h>\r
+\r
#include <sstream>\r
\r
#ifdef XMEM\r
}\r
\r
// set last checked time to now\r
- m_lastchecked.SetToGMTime();\r
+ m_lastchecked=Poco::Timestamp();\r
\r
}\r
\r
SaveKeys(id,message["RequestURI"],message["InsertURI"]);\r
}\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"UnkeyedIDCreator::HandleMessage received keypair");\r
+ m_log->information("UnkeyedIDCreator::HandleMessage received keypair");\r
\r
m_waiting=false;\r
\r
void UnkeyedIDCreator::Initialize()\r
{\r
m_waiting=false;\r
- m_lastchecked.SetToGMTime();\r
+ m_lastchecked=Poco::Timestamp();\r
}\r
\r
void UnkeyedIDCreator::Process()\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
\r
// only perform check every minute (1/1440 of 1 day)\r
- if(m_waiting==false && m_lastchecked<(now-(1.0/1440.0)))\r
+ if(m_waiting==false && m_lastchecked<(now-Poco::Timespan(0,0,1,0,0)))\r
{\r
CheckForUnkeyedID();\r
}\r
#include "../include/global.h"\r
-#include "../include/datetime.h"\r
-#include "../include/logfile.h"\r
-#include "../include/option.h"\r
#include "../include/stringfunctions.h"\r
-#include "../include/db/sqlite3db.h"\r
-#include "../include/freenet/freenetmasterthread.h"\r
-#include "../include/nntp/nntplistener.h"\r
-#include "../include/http/httpthread.h"\r
-#include "../include/threadcontroller.h"\r
-\r
-#ifdef _WIN32\r
- #include <winsock2.h>\r
-#endif\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-volatile bool wantshutdown=false;\r
\r
std::string CreateShortIdentityName(const std::string &name, const std::string &publickey)\r
{\r
\r
return result;\r
}\r
-\r
-void SetupDB()\r
-{\r
-\r
- DateTime date;\r
- std::string tempval="";\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
-\r
- db->Open("fms.db3");\r
- db->SetBusyTimeout(10000); // set timeout to 10 seconds\r
-\r
- tempval="";\r
- Option::Instance()->Get("VacuumOnStartup",tempval);\r
- if(tempval=="true")\r
- {\r
- db->Execute("VACUUM;");\r
- }\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblDBVersion(\\r
- Major INTEGER,\\r
- Minor INTEGER\\r
- );");\r
-\r
- SQLite3DB::Statement st=db->Prepare("SELECT Major,Minor FROM tblDBVersion;");\r
- st.Step();\r
- if(st.RowReturned())\r
- {\r
- int major;\r
- int minor;\r
- st.ResultInt(0,major);\r
- st.ResultInt(1,minor);\r
- st.Finalize();\r
- if(major==1 && minor==0)\r
- {\r
- ConvertDB0100To0101();\r
- major=1;\r
- minor=1;\r
- }\r
- if(major==1 && (minor==1 || minor==2))\r
- {\r
- ConvertDB0101To0103();\r
- major=1;\r
- minor=3;\r
- }\r
- if(major==1 && minor==3)\r
- {\r
- ConvertDB0103To0104();\r
- major=1;\r
- minor=4;\r
- }\r
- if(major==1 && minor==4)\r
- {\r
- ConvertDB0104To0105();\r
- major=1;\r
- minor=5;\r
- }\r
- if(major==1 && minor==5)\r
- {\r
- ConvertDB0105To0106();\r
- major=1;\r
- minor=6;\r
- }\r
- if(major==1 && minor==6)\r
- {\r
- ConvertDB0106To0107();\r
- major=1;\r
- minor=7;\r
- }\r
- if(major==1 && minor==7)\r
- {\r
- ConvertDB0107To0108();\r
- major=1;\r
- minor=8;\r
- }\r
- if(major==1 && minor==8)\r
- {\r
- ConvertDB0108To0109();\r
- major=1;\r
- minor=9;\r
- }\r
- if(major==1 && minor==9)\r
- {\r
- ConvertDB0109To0110();\r
- major=1;\r
- minor=10;\r
- }\r
- if(major==1 && minor==10)\r
- {\r
- ConvertDB0110To0111();\r
- major=1;\r
- minor=11;\r
- }\r
- if(major==1 && minor==11)\r
- {\r
- ConvertDB0111To0112();\r
- major=1;\r
- minor=12;\r
- }\r
- }\r
- else\r
- {\r
- db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,12);");\r
- }\r
-\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=12;");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\\r
- Option TEXT UNIQUE,\\r
- OptionValue TEXT NOT NULL,\\r
- OptionDescription TEXT,\\r
- Section TEXT,\\r
- SortOrder INTEGER,\\r
- ValidValues TEXT\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
- LocalIdentityID INTEGER PRIMARY KEY,\\r
- Name TEXT,\\r
- PublicKey TEXT UNIQUE,\\r
- PrivateKey TEXT UNIQUE,\\r
- SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
- PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
- PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
- PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\\r
- FreesiteEdition INTEGER,\\r
- InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\\r
- LastInsertedIdentity DATETIME,\\r
- InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\\r
- LastInsertedPuzzle DATETIME,\\r
- InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\\r
- LastInsertedTrustList DATETIME,\\r
- LastInsertedBoardList DATETIME,\\r
- LastInsertedMessageList DATETIME,\\r
- LastInsertedFreesite DATETIME,\\r
- DateCreated DATETIME,\\r
- MinMessageDelay INTEGER DEFAULT 0,\\r
- MaxMessageDelay INTEGER DEFAULT 0\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\\r
- LocalIdentityID INTEGER,\\r
- Day DATE,\\r
- InsertIndex INTEGER\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\\r
- LocalIdentityID INTEGER,\\r
- Day DATE,\\r
- InsertIndex INTEGER\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\\r
- IdentityID INTEGER,\\r
- Day DATE,\\r
- RequestIndex INTEGER,\\r
- Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\\r
- UUID TEXT UNIQUE,\\r
- LocalIdentityID INTEGER,\\r
- Day DATE,\\r
- InsertIndex INTEGER,\\r
- Type TEXT,\\r
- MimeType TEXT,\\r
- PuzzleData TEXT,\\r
- PuzzleSolution TEXT,\\r
- FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
- IdentityID INTEGER PRIMARY KEY,\\r
- PublicKey TEXT UNIQUE,\\r
- Name TEXT,\\r
- SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
- PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
- PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
- FreesiteEdition INTEGER,\\r
- DateAdded DATETIME,\\r
- LastSeen DATETIME,\\r
- LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- AddedMethod TEXT,\\r
- Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false',\\r
- PurgeDate DATETIME\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\\r
- IdentityID INTEGER,\\r
- Day DATE,\\r
- RequestIndex INTEGER,\\r
- Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\\r
- IdentityID INTEGER,\\r
- Day DATE,\\r
- RequestIndex INTEGER,\\r
- Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\\r
- UUID TEXT UNIQUE,\\r
- Type TEXT,\\r
- MimeType TEXT,\\r
- PuzzleData TEXT\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\\r
- LocalIdentityID INTEGER,\\r
- Day DATE,\\r
- UUID TEXT UNIQUE,\\r
- Solution TEXT,\\r
- Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityTrust(\\r
- LocalIdentityID INTEGER,\\r
- IdentityID INTEGER,\\r
- LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- MessageTrustComment TEXT,\\r
- LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- TrustListTrustComment TEXT\\r
- );");\r
-\r
- db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxIdentityTrust_IDs ON tblIdentityTrust(LocalIdentityID,IdentityID);");\r
-\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOnIdentityTrust AFTER INSERT ON tblIdentityTrust \\r
- FOR EACH ROW \\r
- BEGIN \\r
- UPDATE tblIdentity SET LocalMessageTrust=(SELECT MAX(LocalMessageTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID), LocalTrustListTrust=(SELECT MAX(LocalTrustListTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID) WHERE tblIdentity.IdentityID=new.IdentityID; \\r
- END;");\r
-\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOnIdentityTrust AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentityTrust \\r
- FOR EACH ROW \\r
- BEGIN \\r
- UPDATE tblIdentity SET LocalMessageTrust=(SELECT MAX(LocalMessageTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID), LocalTrustListTrust=(SELECT MAX(LocalTrustListTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID) WHERE tblIdentity.IdentityID=new.IdentityID; \\r
- END;");\r
-\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOnIdentityTrust AFTER DELETE ON tblIdentityTrust \\r
- FOR EACH ROW \\r
- BEGIN \\r
- UPDATE tblIdentity SET LocalMessageTrust=(SELECT MAX(LocalMessageTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=old.IdentityID GROUP BY tblIdentityTrust.IdentityID), LocalTrustListTrust=(SELECT MAX(LocalTrustListTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=old.IdentityID GROUP BY tblIdentityTrust.IdentityID) WHERE tblIdentity.IdentityID=old.IdentityID; \\r
- END;");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\\r
- IdentityID INTEGER,\\r
- TargetIdentityID INTEGER,\\r
- MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\\r
- TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100),\\r
- MessageTrustComment TEXT,\\r
- TrustListTrustComment TEXT\\r
- );");\r
-\r
- db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_IdentityID ON tblPeerTrust (IdentityID);");\r
- db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_TargetIdentityID ON tblPeerTrust (TargetIdentityID);");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\\r
- BoardID INTEGER PRIMARY KEY,\\r
- BoardName TEXT UNIQUE,\\r
- BoardDescription TEXT,\\r
- DateAdded DATETIME,\\r
- SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true',\\r
- AddedMethod TEXT\\r
- );");\r
-\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('fms','Freenet Message System','2007-12-01 12:00:00','Initial Board');");\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00','Initial Board');");\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('public','Public discussion','2007-12-01 12:00:00','Initial Board');");\r
- db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('test','Test board','2007-12-01 12:00:00','Initial Board');");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\\r
- MessageID INTEGER PRIMARY KEY,\\r
- IdentityID INTEGER,\\r
- FromName TEXT,\\r
- MessageDate DATE,\\r
- MessageTime TIME,\\r
- Subject TEXT,\\r
- MessageUUID TEXT UNIQUE,\\r
- ReplyBoardID INTEGER,\\r
- Body TEXT,\\r
- MessageIndex INTEGER\\r
- );");\r
-\r
- db->Execute("CREATE INDEX IF NOT EXISTS idxMessage_IdentityID ON tblMessage (IdentityID);");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\\r
- MessageID INTEGER,\\r
- ReplyToMessageUUID TEXT,\\r
- ReplyOrder INTEGER\\r
- );");\r
-\r
- db->Execute("CREATE INDEX IF NOT EXISTS idxMessageReplyTo_MessageID ON tblMessageReplyTo (MessageID);");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\\r
- MessageID INTEGER,\\r
- BoardID INTEGER\\r
- );");\r
-\r
- db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_MessageID ON tblMessageBoard (MessageID);");\r
- db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_BoardID ON tblMessageBoard (BoardID);");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\\r
- IdentityID INTEGER,\\r
- Day DATE,\\r
- RequestIndex INTEGER,\\r
- Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\\r
- IdentityID INTEGER,\\r
- Day DATE,\\r
- RequestIndex INTEGER,\\r
- FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\\r
- Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
- );");\r
-\r
- db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\\r
- LocalIdentityID INTEGER,\\r
- Day DATE,\\r
- InsertIndex INTEGER,\\r
- MessageUUID TEXT UNIQUE,\\r
- MessageXML TEXT,\\r
- Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false',\\r
- SendDate DATETIME\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\\r
- FileInsertID INTEGER PRIMARY KEY,\\r
- MessageUUID TEXT,\\r
- FileName TEXT,\\r
- Key TEXT,\\r
- Size INTEGER,\\r
- MimeType TEXT,\\r
- Data BLOB\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\\r
- LocalIdentityID INTEGER,\\r
- Day DATE,\\r
- InsertIndex INTEGER,\\r
- Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\\r
- BoardID INTEGER UNIQUE,\\r
- ModifyLocalMessageTrust INTEGER,\\r
- ModifyLocalTrustListTrust INTEGER\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\\r
- LocalIdentityID INTEGER,\\r
- Day DATE,\\r
- InsertIndex INTEGER,\\r
- Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
- );");\r
-\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\\r
- IdentityID INTEGER,\\r
- Day DATE,\\r
- RequestIndex INTEGER,\\r
- Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
- );"); \r
-\r
- // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed\r
- db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\\r
- LocalIdentityID INTEGER,\\r
- Date DATETIME\\r
- );");\r
-\r
- // A temporary table that will hold a local identity id of the last identity who was loaded in the trust list page\r
- db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpLocalIdentityPeerTrustPage(\\r
- LocalIdentityID INTEGER\\r
- );");\r
-\r
- // low / high / message count for each board\r
- db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \\r
- SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \\r
- FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \\r
- WHERE MessageID>=0 OR MessageID IS NULL \\r
- GROUP BY tblBoard.BoardID;");\r
-\r
- // calculates peer trust\r
- // do the (MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1)/100.0 - so if MessageTrust or TrustListTrust is NULL, the calc will be NULL and it won't be included at all in the average\r
- // need the +1 so that when the values are 0 the result is not 0\r
- db->Execute("DROP VIEW IF EXISTS vwCalculatedPeerTrust;");\r
- db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \\r
- SELECT TargetIdentityID, \\r
- ROUND(SUM(MessageTrust*(LocalTrustListTrust/100.0))/SUM(((MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1))/100.0),0) AS 'PeerMessageTrust', \\r
- ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(((TrustListTrust+1)*LocalTrustListTrust/(TrustListTrust+1))/100.0),0) AS 'PeerTrustListTrust' \\r
- FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \\r
- WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \\r
- AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \\r
- GROUP BY TargetIdentityID;");\r
-\r
- db->Execute("CREATE VIEW IF NOT EXISTS vwIdentityStats AS \\r
- SELECT tblIdentity.IdentityID, COUNT(tblMessage.MessageID) AS MessageCount, MIN(tblMessage.MessageDate) AS FirstMessageDate, MAX(tblMessage.MessageDate) AS LastMessageDate \\r
- FROM tblIdentity LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID \\r
- GROUP BY tblIdentity.IdentityID;");\r
-\r
- /*\r
- These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed\r
- All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class\r
- */\r
- // drop existing triggers\r
- db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");\r
- db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");\r
- db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");\r
- db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");\r
-/*\r
- // update PeerTrustLevel when deleting a record from tblPeerTrust\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \\r
- FOR EACH ROW \\r
- BEGIN \\r
- UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID) WHERE IdentityID=old.TargetIdentityID;\\r
- END;");\r
-\r
- // update PeerTrustLevel when inserting a record into tblPeerTrust\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \\r
- FOR EACH ROW \\r
- BEGIN \\r
- UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID) WHERE IdentityID=new.TargetIdentityID;\\r
- END;");\r
-\r
- // update PeerTrustLevel when updating a record in tblPeerTrust\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \\r
- FOR EACH ROW \\r
- BEGIN \\r
- UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID) WHERE IdentityID=old.TargetIdentityID;\\r
- UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID) WHERE IdentityID=new.TargetIdentityID;\\r
- END;");\r
-\r
- // recalculate all Peer TrustLevels when updating Local TrustLevels on tblIdentity - doesn't really need to be all, but rather all identities the updated identity has a trust level for. It's easier to update everyone for now.\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \\r
- FOR EACH ROW \\r
- BEGIN \\r
- UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\\r
- END;");\r
-*/\r
-\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \\r
- FOR EACH ROW \\r
- BEGIN \\r
- DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\\r
- DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\\r
- END;");\r
-\r
- db->Execute("DROP TRIGGER IF EXISTS trgDeleteIdentity;");\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \\r
- FOR EACH ROW \\r
- BEGIN \\r
- DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\\r
- DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\\r
- DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\\r
- DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\\r
- DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\\r
- DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\\r
- DELETE FROM tblIdentityTrust WHERE IdentityID=old.IdentityID;\\r
- END;");\r
-\r
- db->Execute("DROP TRIGGER IF EXISTS trgDeleteLocalIdentity;");\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \\r
- FOR EACH ROW \\r
- BEGIN \\r
- DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
- DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
- DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
- DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
- DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
- DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
- DELETE FROM tblIdentityTrust WHERE LocalIdentityID=old.LocalIdentityID;\\r
- END;");\r
-\r
- db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \\r
- FOR EACH ROW \\r
- BEGIN \\r
- DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\\r
- END;");\r
-\r
- // delete introduction puzzles that were half-way inserted\r
- db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");\r
-\r
- // delete stale introduction puzzles (2 or more days old)\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-2);\r
- db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");\r
- db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");\r
-\r
- date.SetToGMTime();\r
- // insert SomeDude's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,LocalTrustListTrust,AddedMethod) VALUES('SSK@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw,iXez4j3qCpd596TxXiJgZyTq9o-CElEuJxm~jNNZAuA,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"',50,'Initial Identity');");\r
- // insert Shadow Panther's public key - haven't seen in a while - disabling for now\r
- //db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
- // insert garfield's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
- // insert alek's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@lTjeI6V0lQsktXqaqJ6Iwk4TdsHduQI54rdUpHfhGbg,0oTYfrxxx8OmdU1~60gqpf3781qzEicM4Sz97mJsBM4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
- // insert Luke771's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@mdXK~ZVlfTZhF1SLBrvZ--i0vOsOpa~w9wv~~psQ-04,gXonsXKc7aexKSO8Gt8Fwre4Qgmmbt2WueO7VzxNKkk,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
- // insert falafel's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@IxVqeqM0LyYdTmYAf5z49SJZUxr7NtQkOqVYG0hvITw,RM2wnMn5zAufCMt5upkkgq25B1elfBAxc7htapIWg1c,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
- // insert cptn_insano's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@bloE1LJ~qzSYUkU2nt7sB9kq060D4HTQC66pk5Q8NpA,DOOASUnp0kj6tOdhZJ-h5Tk7Ka50FSrUgsH7tCG1usU,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
- // insert Flink's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@q2TtkNBOuuniyJ56~8NSopCs3ttwe5KlB31ugZtWmXA,6~PzIupS8YK7L6oFNpXGKJmHT2kBMDfwTg73nHdNur8,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
- // insert Kane's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@Ofm~yZivDJ5Z2fSzZbMiLEUUQaIc0KHRdZMBTaPLO6I,WLm4s4hNbOOurJ6ijfOq4odz7-dN7uTUvYxJRwWnlMI,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
- // inserts boardstat's public key\r
- db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@aYWBb6zo2AM13XCNhsmmRKMANEx6PG~C15CWjdZziKA,X1pAG4EIqR1gAiyGFVZ1iiw-uTlh460~rFACJ7ZHQXk,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");\r
-\r
- // TODO remove sometime after 0.1.17\r
- FixCapitalBoardNames();\r
-\r
- // run analyze - may speed up some queries\r
- db->Execute("ANALYZE;");\r
-\r
-}\r
-\r
-void ConvertDB0100To0101()\r
-{\r
- // added unique constraint to public and private key\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");\r
- db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
- LocalIdentityID INTEGER PRIMARY KEY,\\r
- Name TEXT,\\r
- PublicKey TEXT UNIQUE,\\r
- PrivateKey TEXT UNIQUE,\\r
- SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
- PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
- PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
- InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\\r
- LastInsertedIdentity DATETIME,\\r
- InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\\r
- LastInsertedPuzzle DATETIME,\\r
- InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\\r
- LastInsertedTrustList DATETIME,\\r
- InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\\r
- LastInsertedBoardList DATETIME,\\r
- InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\\r
- LastInsertedMessageList DATETIME\\r
- );");\r
- db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");\r
- db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");\r
-}\r
-\r
-void ConvertDB0101To0103()\r
-{\r
- // remove default 50 from trust fields and set default to NULL\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");\r
- db->Execute("DROP TABLE IF EXISTS tblIdentity;");\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
- IdentityID INTEGER PRIMARY KEY,\\r
- PublicKey TEXT UNIQUE,\\r
- Name TEXT,\\r
- SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
- PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
- PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
- DateAdded DATETIME,\\r
- LastSeen DATETIME,\\r
- LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\\r
- );");\r
- db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");\r
- db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");\r
-\r
- // add SaveReceivedMessages field to tblBoard\r
- db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");\r
-\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");\r
-}\r
-\r
-void ConvertDB0103To0104()\r
-{\r
- // add MessageIndex to tblMessage\r
- DateTime date;\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;");\r
- db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");\r
- db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");\r
- date.SetToGMTime();\r
- db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");\r
-}\r
-\r
-void ConvertDB0104To0105()\r
-{\r
- // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity\r
- // add MessageTrustComment,TrustListTrustComment to tblPeerTrust\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;");\r
- db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;");\r
- db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;");\r
- db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;");\r
- db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;");\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;");\r
-}\r
-\r
-void ConvertDB0105To0106()\r
-{\r
- // add Publish Freesite\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';");\r
- db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;");\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");\r
-}\r
-\r
-void ConvertDB0106To0107()\r
-{\r
- // add AddedMethod to tblBoard\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- db->Execute("ALTER TABLE tblBoard ADD COLUMN AddedMethod TEXT;");\r
- db->Execute("ALTER TABLE tblIdentity ADD COLUMN Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false';");\r
- db->Execute("UPDATE tblIdentity SET Hidden='false' WHERE Hidden IS NULL;");\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=7;");\r
-}\r
-\r
-void ConvertDB0107To0108()\r
-{\r
- // add FreesiteEdition to tblLocalIdentity and tblIdentity\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN FreesiteEdition INTEGER;");\r
- db->Execute("ALTER TABLE tblIdentity ADD COLUMN FreesiteEdition INTEGER;");\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=8;");\r
-}\r
-\r
-void ConvertDB0108To0109()\r
-{\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\\r
- FileInsertID INTEGER PRIMARY KEY,\\r
- MessageUUID TEXT,\\r
- FileName TEXT,\\r
- Key TEXT,\\r
- Size INTEGER,\\r
- Data BLOB\\r
- );");\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;");\r
-}\r
-\r
-void ConvertDB0109To0110()\r
-{\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- db->Execute("ALTER TABLE tblFileInserts ADD COLUMN MimeType TEXT;");\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=10;");\r
-}\r
-\r
-void ConvertDB0110To0111()\r
-{\r
- /*\r
- Drop MessageTrustComment, TrustListTrustComment FROM tblIdentity\r
-\r
- Drop InsertingMessageList, InsertingBoardList FROM tblLocalIdentity\r
- Add MinMessageDelay, MaxMessageDelay to tblLocalIdentity Default 0\r
-\r
- Add SendDate to tblMessageInserts\r
- */\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
-\r
- db->Execute("ALTER TABLE tblMessageInserts ADD COLUMN SendDate DATETIME;");\r
-\r
- db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");\r
- db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
- LocalIdentityID INTEGER PRIMARY KEY,\\r
- Name TEXT,\\r
- PublicKey TEXT UNIQUE,\\r
- PrivateKey TEXT UNIQUE,\\r
- SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
- PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
- PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
- PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\\r
- FreesiteEdition INTEGER,\\r
- InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\\r
- LastInsertedIdentity DATETIME,\\r
- InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\\r
- LastInsertedPuzzle DATETIME,\\r
- InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\\r
- LastInsertedTrustList DATETIME,\\r
- LastInsertedBoardList DATETIME,\\r
- LastInsertedMessageList DATETIME,\\r
- LastInsertedFreesite DATETIME,\\r
- DateCreated DATETIME,\\r
- MinMessageDelay INTEGER DEFAULT 0,\\r
- MaxMessageDelay INTEGER DEFAULT 0\\r
- );");\r
- db->Execute("INSERT INTO tblLocalIdentity SELECT LocalIdentityID,Name,PublicKey,PrivateKey,SingleUse,PublishTrustList,PublishBoardList,PublishFreesite,FreesiteEdition,InsertingIdentity,LastInsertedIdentity,InsertingPuzzle,LastInsertedPuzzle,InsertingTrustList,LastInsertedTrustList,LastInsertedBoardList,LastInsertedMessageList,LastInsertedFreesite,DateCreated,0,0 FROM tblLocalIdentityTemp;");\r
- db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");\r
-\r
- db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");\r
- db->Execute("DROP TABLE IF EXISTS tblIdentity;");\r
- db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
- IdentityID INTEGER PRIMARY KEY,\\r
- PublicKey TEXT UNIQUE,\\r
- Name TEXT,\\r
- SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
- PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
- PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
- FreesiteEdition INTEGER,\\r
- DateAdded DATETIME,\\r
- LastSeen DATETIME,\\r
- LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
- AddedMethod TEXT,\\r
- Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false'\\r
- );");\r
- db->Execute("INSERT INTO tblIdentity SELECT IdentityID,PublicKey,Name,SingleUse,PublishTrustList,PublishBoardList,FreesiteEdition,DateAdded,LastSeen,LocalMessageTrust,PeerMessageTrust,LocalTrustListTrust,PeerTrustListTrust,AddedMethod,Hidden FROM tblIdentityTemp;");\r
- db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");\r
-\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=11;");\r
-}\r
-\r
-void ConvertDB0111To0112()\r
-{\r
- /*\r
- Add Section, SortOrder, ValidValues to tblOption\r
- Add PurgeDate to tblIdentity\r
- */\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
-\r
- db->Execute("ALTER TABLE tblOption ADD COLUMN Section TEXT;");\r
- db->Execute("ALTER TABLE tblOption ADD COLUMN SortOrder INTEGER;");\r
- db->Execute("ALTER TABLE tblOption ADD COLUMN ValidValues TEXT;");\r
-\r
- db->Execute("ALTER TABLE tblIdentity ADD COLUMN PurgeDate DATETIME;");\r
-\r
- db->Execute("UPDATE tblDBVersion SET Major=1, Minor=12;");\r
-}\r
-\r
-void SetupDefaultOptions()\r
-{\r
- // OptionValue should always be inserted as a string, even if the option really isn't a string - just to keep the field data type consistent\r
-\r
- std::ostringstream tempstr; // must set tempstr to "" between db inserts\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
- SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");\r
- SQLite3DB::Statement upd=db->Prepare("UPDATE tblOption SET Section=?, SortOrder=?, ValidValues=? WHERE Option=?;");\r
- int order=0;\r
-\r
- // LogLevel\r
- tempstr.str("");\r
- tempstr << LogFile::LOGLEVEL_DEBUG;\r
- st.Bind(0,"LogLevel");\r
- st.Bind(1,tempstr.str());\r
- st.Bind(2,"The maximum logging level that will be written to file. 0=Fatal Errors, 1=Errors, 2=Warnings, 3=Informational Messages, 4=Debug Messages. Higher levels will include all messages from the previous levels.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Program");\r
- upd.Bind(1,order++);\r
- upd.Bind(2,"0|0 - Fatal Errors|1|1 - Errors|2|2 - Warnings|3|3 - Informational Messages|4|4 - Debug Messages");\r
- upd.Bind(3,"LogLevel");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"VacuumOnStartup");\r
- st.Bind(1,"false");\r
- st.Bind(2,"VACUUM the database every time FMS starts. This will defragment the free space in the database and create a smaller database file. Vacuuming the database can be CPU and disk intensive.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Program");\r
- upd.Bind(1,order++);\r
- upd.Bind(2,"true|true|false|false");\r
- upd.Bind(3,"VacuumOnStartup");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MessageBase");\r
- st.Bind(1,"fms");\r
- st.Bind(2,"A unique string shared by all clients who want to communicate with each other. This should not be changed unless you want to create your own separate communications network.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Program");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MessageBase");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- // StartNNTP\r
- st.Bind(0,"StartNNTP");\r
- st.Bind(1,"true");\r
- st.Bind(2,"Start NNTP server.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"NNTP Server");\r
- upd.Bind(1,order++);\r
- upd.Bind(2,"true|true|false|false");\r
- upd.Bind(3,"StartNNTP");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- // NNTPListenPort\r
- st.Bind(0,"NNTPListenPort");\r
- st.Bind(1,"1119");\r
- st.Bind(2,"The port that the NNTP service will listen for incoming connections.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"NNTP Server");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"NNTPListenPort");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- // NNTPBindAddresses\r
- st.Bind(0,"NNTPBindAddresses");\r
- st.Bind(1,"localhost");\r
- st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"NNTP Server");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"NNTPBindAddresses");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"NNTPAllowPost");\r
- st.Bind(1,"true");\r
- st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"NNTP Server");\r
- upd.Bind(1,order++);\r
- upd.Bind(2,"true|true|false|false");\r
- upd.Bind(3,"NNTPAllowPost");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"StartHTTP");\r
- st.Bind(1,"true");\r
- st.Bind(2,"Start HTTP server. WARNING: If you turn this off, you won't be able to access the administration pages.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"HTTP Server");\r
- upd.Bind(1,order++);\r
- upd.Bind(2,"true|true|false|false");\r
- upd.Bind(3,"StartHTTP");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"HTTPListenPort");\r
- st.Bind(1,"8080");\r
- st.Bind(2,"Port HTTP server will listen on.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"HTTP Server");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"HTTPListenPort");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"HTTPAccessControl");\r
- st.Bind(1,"-0.0.0.0/0,+127.0.0.1");\r
- st.Bind(2,"Comma separated list of addresses and/or subnet masks that are allowed access to the administration pages. Default is localhost only. + allows a host, - denies a host.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"HTTP Server");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"HTTPAccessControl");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- // StartFreenetUpdater\r
- st.Bind(0,"StartFreenetUpdater");\r
- st.Bind(1,"true");\r
- st.Bind(2,"Set to true to start the Freenet Updater thread and connect to Freenet. Set to false to prevent communication with Freenet.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Freenet Connection");\r
- upd.Bind(1,order++);\r
- upd.Bind(2,"true|true|false|false");\r
- upd.Bind(3,"StartFreenetUpdater");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- // FCPHost\r
- st.Bind(0,"FCPHost");\r
- st.Bind(1,"127.0.0.1");\r
- st.Bind(2,"Host name or address of Freenet node.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Freenet Connection");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"FCPHost");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- // FCPPort\r
- st.Bind(0,"FCPPort");\r
- st.Bind(1,"9481");\r
- st.Bind(2,"The port that Freenet is listening for FCP connections on.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Freenet Connection");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"FCPPort");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"FProxyPort");\r
- st.Bind(1,"8888");\r
- st.Bind(2,"The port that Freenet is listening for http connections on.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Freenet Connection");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"FProxyPort");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MaxIdentityRequests");\r
- st.Bind(1,"5");\r
- st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Requests");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MaxIdentityRequests");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MaxIdentityIntroductionRequests");\r
- st.Bind(1,"5");\r
- st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Requests");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MaxIdentityIntroductionRequests");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MaxIntroductionPuzzleRequests");\r
- st.Bind(1,"5");\r
- st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Requests");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MaxIntroductionPuzzleRequests");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MaxTrustListRequests");\r
- st.Bind(1,"5");\r
- st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Requests");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MaxTrustListRequests");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MaxMessageListRequests");\r
- st.Bind(1,"5");\r
- st.Bind(2,"Maximum number of concurrent requests for new Message Lists");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Requests");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MaxMessageListRequests");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MaxMessageRequests");\r
- st.Bind(1,"20");\r
- st.Bind(2,"Maximum number of concurrent requests for new Messages");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Requests");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MaxMessageRequests");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MaxBoardListRequests");\r
- st.Bind(1,"5");\r
- st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Requests");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MaxBoardListRequests");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MinLocalMessageTrust");\r
- st.Bind(1,"50");\r
- st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Trust");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MinLocalMessageTrust");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MinPeerMessageTrust");\r
- st.Bind(1,"30");\r
- st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Trust");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MinPeerMessageTrust");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MinLocalTrustListTrust");\r
- st.Bind(1,"50");\r
- st.Bind(2,"Specifies a local trust list trust level that a peer must have before its trust list will be included in the weighted average. Any peers below this number will be excluded from the results.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Trust");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MinLocalTrustListTrust");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MinPeerTrustListTrust");\r
- st.Bind(1,"30");\r
- st.Bind(2,"Specifies a peer trust list trust level that a peer must have before its trust list will be included in the weighted average. Any peers below this number will be excluded from the results.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Trust");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MinPeerTrustListTrust");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"LocalTrustOverridesPeerTrust");\r
- st.Bind(1,"false");\r
- st.Bind(2,"Set to true if you want your local trust levels to override the peer levels when determining which identities you will poll.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Trust");\r
- upd.Bind(1,order++);\r
- upd.Bind(2,"true|true|false|false");\r
- upd.Bind(3,"LocalTrustOverridesPeerTrust");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MessageDownloadMaxDaysBackward");\r
- st.Bind(1,"5");\r
- st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Messages");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MessageDownloadMaxDaysBackward");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MessageListDaysBackward");\r
- st.Bind(1,"5");\r
- st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Messages");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MessageListDaysBackward");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MaxPeerMessagesPerDay");\r
- st.Bind(1,"200");\r
- st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Messages");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MaxPeerMessagesPerDay");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"MaxBoardsPerMessage");\r
- st.Bind(1,"8");\r
- st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Messages");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"MaxBoardsPerMessage");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"SaveMessagesFromNewBoards");\r
- st.Bind(1,"true");\r
- st.Bind(2,"Set to true to automatically save messages posted to new boards. Set to false to ignore messages to new boards.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Messages");\r
- upd.Bind(1,order++);\r
- upd.Bind(2,"true|true|false|false");\r
- upd.Bind(3,"SaveMessagesFromNewBoards");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"ChangeMessageTrustOnReply");\r
- st.Bind(1,"0");\r
- st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Messages");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"ChangeMessageTrustOnReply");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"AddNewPostFromIdentities");\r
- st.Bind(1,"false");\r
- st.Bind(2,"Set to true to automatically create new identities when you send a message using a new name. If you set this to false, posting messages will fail until you manually create the identity.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Messages");\r
- upd.Bind(1,order++);\r
- upd.Bind(2,"true|true|false|false");\r
- upd.Bind(3,"AddNewPostFromIdentities");\r
- upd.Step();\r
- upd.Reset();\r
-\r
- st.Bind(0,"DeleteMessagesOlderThan");\r
- st.Bind(1,"180");\r
- st.Bind(2,"Automatically delete messages older than this many days.");\r
- st.Step();\r
- st.Reset();\r
- upd.Bind(0,"Messages");\r
- upd.Bind(1,order++);\r
- upd.Bind(2);\r
- upd.Bind(3,"DeleteMessagesOlderThan");\r
- upd.Step();\r
- upd.Reset();\r
-\r
-}\r
-\r
-void SetupLogFile()\r
-{\r
- DateTime date;\r
- std::string configval;\r
- int loglevel;\r
-\r
- date.SetToGMTime();\r
-\r
- LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");\r
- LogFile::Instance()->OpenFile();\r
- LogFile::Instance()->SetWriteNewLine(true);\r
- LogFile::Instance()->SetWriteDate(true);\r
- LogFile::Instance()->SetWriteLogLevel(true);\r
-\r
- if(Option::Instance()->Get("LogLevel",configval)==false)\r
- {\r
- configval="4";\r
- Option::Instance()->Set("LogLevel",configval);\r
- }\r
- if(StringFunctions::Convert(configval,loglevel)==false)\r
- {\r
- loglevel=LogFile::LOGLEVEL_DEBUG;\r
- Option::Instance()->Set("LogLevel",loglevel);\r
- }\r
- LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);\r
-}\r
-\r
-void SetupNetwork()\r
-{\r
-#ifdef _WIN32\r
- WSAData wsadata;\r
- WSAStartup(MAKEWORD(2,2),&wsadata);\r
-#endif\r
-}\r
-\r
-void Shutdown()\r
-{\r
-\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"FMS starting shutdown");\r
-\r
- ThreadController::Instance()->ShutdownThreads();\r
-\r
- ShutdownNetwork();\r
-\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");\r
- LogFile::Instance()->WriteNewLine();\r
-}\r
-\r
-void ShutdownNetwork()\r
-{\r
-#ifdef _WIN32\r
- WSACleanup();\r
-#endif\r
-}\r
-\r
-void SigHandler(int signum)\r
-{\r
- Shutdown();\r
- exit(0);\r
-}\r
-\r
-void FixCapitalBoardNames()\r
-{\r
- SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
-\r
- SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);");\r
- SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");\r
- SQLite3DB::Statement del=db->Prepare("DELETE FROM tblBoard WHERE BoardID=?;");\r
- SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;");\r
- SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;");\r
- SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;");\r
-\r
- st.Step();\r
- while(st.RowReturned())\r
- {\r
- int boardid=0;\r
- int newboardid=0;\r
- std::string name="";\r
- std::string lowername="";\r
-\r
- st.ResultInt(0,boardid);\r
- st.ResultText(1,name);\r
-\r
- lowername=name;\r
- StringFunctions::LowerCase(lowername,lowername);\r
- \r
- if(name!=lowername)\r
- {\r
- st2.Bind(0,lowername);\r
- st2.Step();\r
-\r
- if(st2.RowReturned())\r
- {\r
- st2.ResultInt(0,newboardid);\r
-\r
- upd2.Bind(0,newboardid);\r
- upd2.Bind(1,boardid);\r
- upd2.Step();\r
- upd2.Reset();\r
-\r
- upd3.Bind(0,newboardid);\r
- upd3.Bind(1,boardid);\r
- upd3.Step();\r
- upd3.Reset();\r
-\r
- del.Bind(0,boardid);\r
- del.Step();\r
- del.Reset();\r
- }\r
- else\r
- {\r
- upd.Bind(0,lowername);\r
- upd.Bind(1,boardid);\r
- upd.Step();\r
- upd.Reset();\r
- }\r
-\r
- st2.Reset();\r
- }\r
- \r
- st.Step();\r
- }\r
-\r
-}\r
--- /dev/null
+#include "../../include/http/fmshttprequesthandlerfactory.h"\r
+#include "../../include/option.h"\r
+#include "../../include/stringfunctions.h"\r
+#include "../../include/http/pages/homepage.h"\r
+#include "../../include/http/pages/optionspage.h"\r
+#include "../../include/http/pages/createidentitypage.h"\r
+#include "../../include/http/pages/localidentitiespage.h"\r
+#include "../../include/http/pages/confirmpage.h"\r
+#include "../../include/http/pages/showcaptchapage.h"\r
+#include "../../include/http/pages/announceidentitypage.h"\r
+#include "../../include/http/pages/execquerypage.h"\r
+#include "../../include/http/pages/boardspage.h"\r
+#include "../../include/http/pages/insertedfilespage.h"\r
+#include "../../include/http/pages/addpeerpage.h"\r
+#include "../../include/http/pages/peerdetailspage.h"\r
+#include "../../include/http/pages/controlboardpage.h"\r
+#include "../../include/http/pages/peermaintenancepage.h"\r
+#include "../../include/http/pages/peertrustpage.h"\r
+\r
+FMSHTTPRequestHandlerFactory::FMSHTTPRequestHandlerFactory()\r
+{\r
+ // set template\r
+ std::string templatestr="<html><head></head><body><a href=\"home.htm\">Home</a><br><h1>Could not open template.htm! Place in program directory and restart!</h1><br>[CONTENT]</body></html>";\r
+ FILE *infile=fopen("template.htm","r+b");\r
+ if(infile)\r
+ {\r
+ fseek(infile,0,SEEK_END);\r
+ long len=ftell(infile);\r
+ std::vector<char> data(len,0);\r
+ fseek(infile,0,SEEK_SET);\r
+ fread(&data[0],1,len,infile);\r
+ fclose(infile);\r
+ templatestr.assign(data.begin(),data.end());\r
+ }\r
+ else\r
+ {\r
+ m_log->error("HTTPThread::HTTPThread could not open template.htm");\r
+ }\r
+\r
+ // push back page handlers\r
+ m_pagehandlers.push_back(new OptionsPage(templatestr));\r
+ m_pagehandlers.push_back(new CreateIdentityPage(templatestr));\r
+ m_pagehandlers.push_back(new LocalIdentitiesPage(templatestr));\r
+ m_pagehandlers.push_back(new ConfirmPage(templatestr));\r
+ m_pagehandlers.push_back(new ShowCaptchaPage());\r
+ m_pagehandlers.push_back(new AnnounceIdentityPage(templatestr));\r
+ m_pagehandlers.push_back(new ExecQueryPage(templatestr));\r
+ m_pagehandlers.push_back(new BoardsPage(templatestr));\r
+ m_pagehandlers.push_back(new InsertedFilesPage(templatestr));\r
+ m_pagehandlers.push_back(new AddPeerPage(templatestr));\r
+ m_pagehandlers.push_back(new PeerDetailsPage(templatestr));\r
+ m_pagehandlers.push_back(new ControlBoardPage(templatestr));\r
+ m_pagehandlers.push_back(new PeerMaintenancePage(templatestr));\r
+ m_pagehandlers.push_back(new PeerTrustPage(templatestr));\r
+ // homepage must be last - catch all page handler\r
+ m_pagehandlers.push_back(new HomePage(templatestr));\r
+\r
+ // initialize the access control list\r
+ std::string aclstr;\r
+ std::vector<std::string> aclparts;\r
+ Option::Instance()->Get("HTTPAccessControl",aclstr);\r
+ StringFunctions::Split(aclstr,",",aclparts);\r
+ for(std::vector<std::string>::iterator i=aclparts.begin(); i!=aclparts.end(); i++)\r
+ {\r
+ m_acl.Add((*i));\r
+ }\r
+}\r
+\r
+FMSHTTPRequestHandlerFactory::~FMSHTTPRequestHandlerFactory()\r
+{\r
+\r
+ for(std::vector<IPageHandler *>::iterator i=m_pagehandlers.begin(); i!=m_pagehandlers.end(); i++)\r
+ {\r
+ delete (*i);\r
+ }\r
+\r
+}\r
+\r
+Poco::Net::HTTPRequestHandler *FMSHTTPRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest &request)\r
+{\r
+ if(m_acl.IsAllowed(request.clientAddress().host()))\r
+ {\r
+ for(std::vector<IPageHandler *>::iterator i=m_pagehandlers.begin(); i!=m_pagehandlers.end(); i++)\r
+ {\r
+ if((*i)->WillHandleURI(request.getURI()))\r
+ {\r
+ // we need to return a new object because the HTTPServer will destory it when it's done.\r
+ return (*i)->New();\r
+ }\r
+ }\r
+ }\r
+ return 0;\r
+}\r
#include "../../include/http/httpthread.h"\r
+#include "../../include/http/fmshttprequesthandlerfactory.h"\r
#include "../../include/option.h"\r
#include "../../include/stringfunctions.h"\r
-#include "../../include/http/pages/homepage.h"\r
-#include "../../include/http/pages/optionspage.h"\r
-#include "../../include/http/pages/showcaptchapage.h"\r
-#include "../../include/http/pages/createidentitypage.h"\r
-#include "../../include/http/pages/localidentitiespage.h"\r
-#include "../../include/http/pages/announceidentitypage.h"\r
-#include "../../include/http/pages/addpeerpage.h"\r
-#include "../../include/http/pages/peertrustpage.h"\r
-#include "../../include/http/pages/controlboardpage.h"\r
-#include "../../include/http/pages/peerdetailspage.h"\r
-#include "../../include/http/pages/peermaintenancepage.h"\r
-#include "../../include/http/pages/execquerypage.h"\r
-#include "../../include/http/pages/boardspage.h"\r
-#include "../../include/http/pages/insertedfilespage.h"\r
-#include "../../include/http/pages/confirmpage.h"\r
+\r
+#include <Poco/Net/ServerSocket.h>\r
+#include <Poco/Net/HTTPServer.h>\r
+#include <Poco/Net/HTTPServerParams.h>\r
\r
#include <iostream>\r
\r
\r
HTTPThread::HTTPThread()\r
{\r
- std::string templatestr;\r
- int port;\r
+ m_listenport=8080;\r
std::string portstr;\r
Option::Instance()->Get("HTTPListenPort",portstr);\r
- StringFunctions::Convert(portstr,port);\r
-\r
- std::string aclstr;\r
- Option::Instance()->Get("HTTPAccessControl",aclstr);\r
-\r
- // set template\r
- templatestr="<html><head></head><body><a href=\"home.htm\">Home</a><br><h1>Could not find template.htm! Place in program directory and restart!</h1><br>[CONTENT]</body></html>";\r
- FILE *infile=fopen("template.htm","r+b");\r
- if(infile)\r
- {\r
- fseek(infile,0,SEEK_END);\r
- long len=ftell(infile);\r
- std::vector<char> data(len,0);\r
- fseek(infile,0,SEEK_SET);\r
- fread(&data[0],1,len,infile);\r
- fclose(infile);\r
- templatestr.assign(data.begin(),data.end());\r
- }\r
- else\r
- {\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"HTTPThread::HTTPThread could not open template.htm");\r
- }\r
+ StringFunctions::Convert(portstr,m_listenport);\r
\r
// push back page handlers\r
+ /*\r
m_pagehandlers.push_back(new ShowCaptchaPage());\r
m_pagehandlers.push_back(new OptionsPage(templatestr));\r
m_pagehandlers.push_back(new LocalIdentitiesPage(templatestr));\r
m_pagehandlers.push_back(new ConfirmPage(templatestr));\r
// homepage must be last - catch all page handler\r
m_pagehandlers.push_back(new HomePage(templatestr));\r
-\r
- m_ctx=0;\r
- m_ctx=shttpd_init();\r
- shttpd_set_option(m_ctx,"ports",portstr.c_str());\r
- shttpd_set_option(m_ctx,"acl",aclstr.c_str());\r
-\r
- shttpd_register_uri(m_ctx,"*",HTTPThread::PageCallback,this);\r
-\r
-}\r
-\r
-HTTPThread::~HTTPThread()\r
-{\r
- shttpd_fini(m_ctx);\r
-\r
- for(std::vector<IPageHandler *>::iterator i=m_pagehandlers.begin(); i!=m_pagehandlers.end(); i++)\r
- {\r
- delete (*i);\r
- }\r
-\r
+ */\r
+ \r
}\r
\r
+/*\r
void HTTPThread::PageCallback(shttpd_arg *arg)\r
{\r
\r
}\r
\r
}\r
-\r
-void HTTPThread::Run()\r
+*/\r
+void HTTPThread::run()\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"HTTPThread::run thread started.");\r
+ m_log->debug("HTTPThread::run thread started.");\r
+\r
+ Poco::Net::ServerSocket sock(m_listenport);\r
+ Poco::Net::HTTPServerParams* pParams = new Poco::Net::HTTPServerParams;\r
+ pParams->setMaxQueued(10);\r
+ pParams->setMaxThreads(5);\r
+ Poco::Net::HTTPServer srv(new FMSHTTPRequestHandlerFactory,sock,pParams);\r
+\r
+ srv.start();\r
\r
do\r
{\r
- shttpd_poll(m_ctx,1000);\r
+ Poco::Thread::sleep(1000);\r
}while(!IsCancelled());\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"HTTPThread::run thread exiting.");\r
+ srv.stop();\r
+\r
+ m_log->debug("HTTPThread::run thread exiting.");\r
\r
}\r
\r
std::string IdentityExportXML::GetXML()\r
{\r
- TiXmlDocument td;\r
- TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
- TiXmlElement *tid;\r
- TiXmlPrinter tp;\r
+ Poco::AutoPtr<Poco::XML::Document> doc=new Poco::XML::Document;\r
+ Poco::XML::Element *root=doc->createElement("IdentityExport");\r
+ Poco::XML::Element *el=NULL;\r
+ //TiXmlDocument td;\r
+ //TiXmlDeclaration *tdec=new TiXmlDeclaration("1.0","UTF-8","");\r
+ //TiXmlElement *tid;\r
+ //TiXmlPrinter tp;\r
\r
- td.LinkEndChild(tdec);\r
- tid=new TiXmlElement("IdentityExport");\r
- td.LinkEndChild(tid);\r
+ doc->appendChild(root);\r
+ //td.LinkEndChild(tdec);\r
+ //tid=new TiXmlElement("IdentityExport");\r
+ //td.LinkEndChild(tid);\r
\r
for(std::vector<identity>::iterator i=m_identities.begin(); i!=m_identities.end(); i++)\r
{\r
- TiXmlElement *tr=new TiXmlElement("Identity");\r
- tid->LinkEndChild(tr);\r
- tr->LinkEndChild(XMLCreateCDATAElement("Name",(*i).m_name));\r
- tr->LinkEndChild(XMLCreateTextElement("PublicKey",(*i).m_publickey));\r
- tr->LinkEndChild(XMLCreateTextElement("PrivateKey",(*i).m_privatekey));\r
- tr->LinkEndChild(XMLCreateBooleanElement("SingleUse",(*i).m_singleuse));\r
- tr->LinkEndChild(XMLCreateBooleanElement("PublishTrustList",(*i).m_publishtrustlist));\r
- tr->LinkEndChild(XMLCreateBooleanElement("PublishBoardList",(*i).m_publishboardlist));\r
- tr->LinkEndChild(XMLCreateBooleanElement("PublishFreesite",(*i).m_publishfreesite));\r
+ el=doc->createElement("Identity");\r
+ //TiXmlElement *tr=new TiXmlElement("Identity");\r
+ root->appendChild(el);\r
+ //tid->LinkEndChild(tr);\r
+\r
+ el->appendChild(XMLCreateCDATAElement(doc,"Name",(*i).m_name));\r
+ el->appendChild(XMLCreateTextElement(doc,"PublicKey",(*i).m_publickey));\r
+ el->appendChild(XMLCreateTextElement(doc,"PrivateKey",(*i).m_privatekey));\r
+ el->appendChild(XMLCreateBooleanElement(doc,"SingleUse",(*i).m_singleuse));\r
+ el->appendChild(XMLCreateBooleanElement(doc,"PublishTrustList",(*i).m_publishtrustlist));\r
+ el->appendChild(XMLCreateBooleanElement(doc,"PublishBoardList",(*i).m_publishboardlist));\r
+ el->appendChild(XMLCreateBooleanElement(doc,"PublishFreesite",(*i).m_publishfreesite));\r
+\r
+ //tr->LinkEndChild(XMLCreateCDATAElement("Name",(*i).m_name));\r
+ //tr->LinkEndChild(XMLCreateTextElement("PublicKey",(*i).m_publickey));\r
+ //tr->LinkEndChild(XMLCreateTextElement("PrivateKey",(*i).m_privatekey));\r
+ //tr->LinkEndChild(XMLCreateBooleanElement("SingleUse",(*i).m_singleuse));\r
+ //tr->LinkEndChild(XMLCreateBooleanElement("PublishTrustList",(*i).m_publishtrustlist));\r
+ //tr->LinkEndChild(XMLCreateBooleanElement("PublishBoardList",(*i).m_publishboardlist));\r
+ //tr->LinkEndChild(XMLCreateBooleanElement("PublishFreesite",(*i).m_publishfreesite));\r
}\r
\r
- td.Accept(&tp);\r
- return std::string(tp.CStr());\r
+ //td.Accept(&tp);\r
+ //return std::string(tp.CStr());\r
+\r
+ std::string xml;\r
+ xml=GenerateXML(doc);\r
+\r
+ return xml;\r
}\r
\r
void IdentityExportXML::Initialize()\r
\r
const bool IdentityExportXML::ParseXML(const std::string &xml)\r
{\r
- TiXmlDocument td;\r
- td.Parse(xml.c_str());\r
+ bool parsed=false;\r
+ Poco::XML::DOMParser dp;\r
+\r
+ Initialize();\r
+\r
+ try\r
+ {\r
+ Poco::AutoPtr<Poco::XML::Document> doc=dp.parseString(FixCDATA(xml));\r
+ Poco::XML::Element *root=XMLGetFirstChild(doc,"IdentityExport");\r
+ Poco::XML::Element *node=XMLGetFirstChild(root,"Identity");\r
+\r
+ while(node)\r
+ {\r
+ std::string name="";\r
+ std::string publickey="";\r
+ std::string privatekey="";\r
+ bool singleuse=false;\r
+ bool publishtrustlist=false;\r
+ bool publishboardlist=false;\r
+ bool publishfreesite=false; \r
+\r
+ Poco::XML::Element *text=XMLGetFirstChild(node,"Name");\r
+ if(text)\r
+ {\r
+ if(text->firstChild())\r
+ {\r
+ std::string asdf=text->innerText();\r
+ asdf=text->firstChild()->innerText();\r
+ name=text->firstChild()->getNodeValue();\r
+ }\r
+ }\r
+ text=XMLGetFirstChild(node,"PublicKey");\r
+ if(text)\r
+ {\r
+ if(text->firstChild())\r
+ {\r
+ publickey=text->firstChild()->getNodeValue();\r
+ }\r
+ }\r
+ text=XMLGetFirstChild(node,"PrivateKey");\r
+ if(text)\r
+ {\r
+ if(text->firstChild())\r
+ {\r
+ privatekey=text->firstChild()->getNodeValue();\r
+ }\r
+ }\r
+\r
+ singleuse=XMLGetBooleanElement(node,"SingleUse");\r
+ publishtrustlist=XMLGetBooleanElement(node,"PublishTrustList");\r
+ publishboardlist=XMLGetBooleanElement(node,"PublishBoardList");\r
+ publishfreesite=XMLGetBooleanElement(node,"PublishFreesite");\r
+\r
+ if(name!="" && publickey!="" && privatekey!="")\r
+ {\r
+ m_identities.push_back(identity(name,publickey,privatekey,singleuse,publishtrustlist,publishboardlist,publishfreesite));\r
+ }\r
+\r
+ node=XMLGetNextSibling(node,"Identity");\r
+ }\r
+\r
+ parsed=true;\r
+ }\r
+ catch(...)\r
+ {\r
+ }\r
+\r
+ return parsed;\r
\r
+ //TiXmlDocument td;\r
+ //td.Parse(xml.c_str());\r
+/*\r
if(!td.Error())\r
{\r
std::string name;\r
{\r
return false;\r
}\r
+*/\r
}\r
#include "../../include/http/ipagehandler.h"\r
-#include "../../include/http/httpdefs.h"\r
#include "../../include/stringfunctions.h"\r
+#include "../../include/http/multipartparser.h"\r
+\r
+#include <Poco/Net/HTMLForm.h>\r
\r
#include <cstring>\r
\r
return rval;\r
}\r
\r
-const bool IPageHandler::Handle(shttpd_arg *arg)\r
+void IPageHandler::CreateQueryVarMap(Poco::Net::HTTPServerRequest &request, std::map<std::string,std::string> &vars)\r
{\r
- const char *uri=shttpd_get_env(arg,"REQUEST_URI");\r
- const char *method=shttpd_get_env(arg,"REQUEST_METHOD");\r
- std::string methodstr="";\r
- if(method)\r
+ for(Poco::Net::HTTPServerRequest::ConstIterator i=request.begin(); i!=request.end(); i++)\r
{\r
- methodstr=method;\r
+ vars[(*i).first]=(*i).second;\r
}\r
\r
- if(uri && WillHandleURI(std::string(uri)))\r
+ // handle HTMLForm and multiparts\r
+ MultiPartParser mpp;\r
+ Poco::Net::HTMLForm form(request,request.stream(),mpp);\r
+ for(Poco::Net::HTMLForm::ConstIterator i=form.begin(); i!=form.end(); i++)\r
{\r
- httpstate *mystate=(httpstate *)arg->state;\r
-\r
- // first check if there was a connection error - if so delete the input/output and state buffers and return immediately\r
- if((arg->flags & SHTTPD_CONNECTION_ERROR)==SHTTPD_CONNECTION_ERROR)\r
- {\r
- if(mystate && mystate->m_indata)\r
- {\r
- delete mystate->m_indata;\r
- mystate->m_indata=NULL;\r
- }\r
- if(mystate && mystate->m_outdata)\r
- {\r
- delete mystate->m_outdata;\r
- mystate->m_outdata=NULL;\r
- }\r
- if(mystate)\r
- {\r
- delete mystate;\r
- mystate=NULL;\r
- }\r
- return true;\r
- }\r
-\r
- // this is a new request - create a new arg object\r
- if(arg->state==NULL)\r
- {\r
- arg->state=new httpstate;\r
- memset(arg->state,0,sizeof(httpstate));\r
- mystate=(httpstate *)arg->state;\r
-\r
- // if post then create input buffer\r
- if(methodstr=="POST")\r
- {\r
- const char *lenstr=shttpd_get_header(arg,"Content-Length");\r
- if(lenstr)\r
- {\r
- long len=0;\r
- StringFunctions::Convert(std::string(lenstr),len);\r
- mystate->m_indata=new char[len+1];\r
- mystate->m_indata[len]='\0';\r
- mystate->m_indatalen=len;\r
- mystate->m_indatapos=0;\r
- }\r
- }\r
- }\r
-\r
- // we have more POST data to get\r
- if(arg->in.len>0)\r
- {\r
- int pos=0;\r
- while(pos<arg->in.len)\r
- {\r
- mystate->m_indata[mystate->m_indatapos++]=arg->in.buf[pos++];\r
- }\r
- arg->in.num_bytes=arg->in.len;\r
- }\r
-\r
- // we have all POST data (or it was 0 to begin with) - generate the page\r
- if(mystate->m_indatalen==mystate->m_indatapos && mystate->m_outdata==NULL)\r
- {\r
- //parse POST data and any QUERY_STRING before generating page\r
- std::map<std::string,std::string> args;\r
- std::vector<std::string> argparts;\r
- std::string contenttype="";\r
- \r
- if(shttpd_get_header(arg,"Content-Type"))\r
- {\r
- contenttype=shttpd_get_header(arg,"Content-Type");\r
- }\r
- \r
- if(contenttype.find("multipart/form-data")!=std::string::npos)\r
- {\r
- HandleMultiPartData(contenttype,mystate->m_indata,mystate->m_indatalen,args);\r
- }\r
- else\r
- {\r
- // split apart non-multipart POST\r
- if(mystate->m_indata)\r
- {\r
- StringFunctions::Split(mystate->m_indata,"&",argparts);\r
- }\r
- // split apart query string\r
- if(shttpd_get_env(arg,"QUERY_STRING"))\r
- {\r
- StringFunctions::Split(shttpd_get_env(arg,"QUERY_STRING"),"&",argparts);\r
- }\r
-\r
- for(std::vector<std::string>::iterator argi=argparts.begin(); argi!=argparts.end(); argi++)\r
- {\r
- std::vector<std::string> parts;\r
- StringFunctions::Split((*argi),"=",parts);\r
- if(parts.size()>0)\r
- {\r
- // replace + with space before UriDecoding\r
- parts[0]=StringFunctions::Replace(parts[0],"+"," ");\r
- args[StringFunctions::UriDecode(parts[0])];\r
- if(parts.size()>1)\r
- {\r
- // replace + with space before UriDecoding\r
- parts[1]=StringFunctions::Replace(parts[1],"+"," ");\r
- args[StringFunctions::UriDecode(parts[0])]=StringFunctions::UriDecode(parts[1]);\r
- }\r
- }\r
- }\r
- }\r
-\r
- std::string page=GeneratePage(methodstr,args);\r
- mystate->m_outdata=new char[page.size()];\r
- memcpy(mystate->m_outdata,page.c_str(),page.size());\r
- mystate->m_outdatalen=page.size();\r
- mystate->m_outdatapos=0;\r
- }\r
-\r
- // if we have output data, push next block of data onto out buffer\r
- if(mystate->m_outdata && mystate->m_outdatapos<mystate->m_outdatalen)\r
- {\r
- int pos=0;\r
- while(mystate->m_outdatapos<mystate->m_outdatalen && pos<arg->out.len)\r
- {\r
- arg->out.buf[pos++]=mystate->m_outdata[mystate->m_outdatapos++];\r
- }\r
- arg->out.num_bytes=pos;\r
- }\r
-\r
- // if we have no more output data to send - delete the data pointers and set end of output flag\r
- if(mystate->m_outdata && mystate->m_outdatapos==mystate->m_outdatalen)\r
- {\r
- if(mystate->m_indata)\r
- {\r
- delete [] mystate->m_indata;\r
- }\r
- if(mystate->m_outdata)\r
- {\r
- delete [] mystate->m_outdata;\r
- }\r
- delete mystate;\r
- arg->state=NULL;\r
-\r
- arg->flags|=SHTTPD_END_OF_OUTPUT;\r
- }\r
-\r
- return true;\r
+ vars[(*i).first]=(*i).second;\r
}\r
- else\r
+\r
+ // get any multiparts\r
+ std::map<std::string,std::string> mpvars=mpp.GetVars();\r
+ for(std::map<std::string,std::string>::iterator i=mpvars.begin(); i!=mpvars.end(); i++)\r
{\r
- return false;\r
+ vars[(*i).first]=(*i).second;\r
}\r
+\r
}\r
\r
-void IPageHandler::HandleMultiPartData(const std::string &contenttypeheader, char *data, const long datalen, std::map<std::string,std::string> &args)\r
+void IPageHandler::handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response)\r
{\r
- if(data)\r
- {\r
- std::string datastr(data,data+datalen);\r
- std::vector<std::string> parts;\r
- std::string boundary="";\r
- std::string::size_type pos=contenttypeheader.find("boundary=");\r
+ m_log->trace("IPageHandler::handleRequest from "+request.clientAddress().toString());\r
\r
- // find boundary\r
- if(pos!=std::string::npos)\r
- {\r
- boundary=contenttypeheader.substr(pos+9);\r
- // strip off any " and ;\r
- boundary=StringFunctions::Replace(boundary,"\"","");\r
- boundary=StringFunctions::Replace(boundary,";","");\r
- }\r
+ std::map<std::string,std::string> vars;\r
\r
- // split into parts separated by boundary\r
- StringFunctions::Split(datastr,"--"+boundary+"\r\n",parts);\r
+ CreateQueryVarMap(request,vars);\r
\r
- // go through each part and get name=value\r
- for(std::vector<std::string>::iterator i=parts.begin(); i!=parts.end(); i++)\r
- {\r
- std::string data="";\r
- std::string name="";\r
+ response.setChunkedTransferEncoding(true);\r
+ response.setContentType("text/html");\r
\r
- // find name\r
- pos=(*i).find("name=");\r
- if(pos!=std::string::npos)\r
- {\r
- std::string::size_type pos2=(*i).find(";",pos);\r
- if(pos2!=std::string::npos)\r
- {\r
- name=(*i).substr(pos+5,pos2-(pos+5));\r
- }\r
- else\r
- {\r
- pos2=(*i).find("\r\n",pos);\r
- if(pos2!=std::string::npos)\r
- {\r
- name=(*i).substr(pos+5,pos2-(pos+5));\r
- }\r
- }\r
+ std::ostream &ostr = response.send();\r
+ ostr << GeneratePage(request.getMethod(),vars);\r
\r
- name=StringFunctions::Replace(name,"\"","");\r
- }\r
-\r
- // find header boundary\r
- pos=(*i).find("\r\n\r\n");\r
- if(pos!=std::string::npos)\r
- {\r
- data=(*i).substr(pos+4);\r
- // strip off final \r\n from data\r
- if(data.size()>2 && data.rfind("\r\n")==data.size()-2)\r
- {\r
- data.erase(data.size()-2);\r
- }\r
- }\r
- if(name!="" && data!="")\r
- {\r
- args[name]=data;\r
- }\r
- }\r
- }\r
}\r
\r
const std::string IPageHandler::SanitizeOutput(const std::string &input)\r
--- /dev/null
+#include "../../include/http/multipartparser.h"\r
+\r
+#include <Poco/Net/MessageHeader.h>\r
+#include <Poco/StreamCopier.h>\r
+\r
+void MultiPartParser::handlePart(const Poco::Net::MessageHeader &header, std::istream &stream)\r
+{\r
+ std::string name="";\r
+ std::string data="";\r
+\r
+ if(header.has("Content-Disposition"))\r
+ {\r
+ std::string disp;\r
+ Poco::Net::NameValueCollection nvc;\r
+ Poco::Net::MessageHeader::splitParameters(header["Content-Disposition"],disp,nvc);\r
+ name=nvc.get("name","");\r
+\r
+ Poco::StreamCopier sc;\r
+ sc.copyToString(stream,data);\r
+\r
+ vars[name]=data;\r
+ }\r
+}\r
#include "../../../include/http/pages/addpeerpage.h"\r
#include "../../../include/stringfunctions.h"\r
-#include "../../../include/datetime.h"\r
+\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
\r
#ifdef XMEM\r
#include <xmem.h>\r
\r
if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="add")\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
std::string publickey="";\r
if(queryvars.find("publickey")!=queryvars.end())\r
{\r
}\r
if(publickey!="" && publickey.find("SSK@")==0 && publickey[publickey.size()-1]=='/')\r
{\r
- date.SetToGMTime();\r
SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES(?,?,?);");\r
st.Bind(0,publickey);\r
- st.Bind(1,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Bind(2,"manually");\r
st.Step();\r
st.Reset();\r
content+="<input type=\"submit\" value=\"Add\">";\r
content+="</form>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool AddPeerPage::WillHandleURI(const std::string &uri)\r
#include "../../../include/http/pages/announceidentitypage.h"\r
#include "../../../include/stringfunctions.h"\r
-#include "../../../include/datetime.h"\r
#include "../../../include/global.h"\r
\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+\r
#ifdef XMEM\r
#include <xmem.h>\r
#endif\r
\r
const std::string AnnounceIdentityPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
{\r
- DateTime date;\r
+ Poco::DateTime date;\r
std::string content;\r
int shown=0;\r
std::string countstr="";\r
content+="<tr><td colspan=\"4\"><center>Type the answers of a few puzzles. The puzzles are case sensitive. Getting announced will take some time. DO NOT continuously solve captchas. Solve 30 at most, wait a day, and if your identity has not been announced, repeat until it is.</td></tr>";\r
content+="<tr>";\r
\r
-\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-1);\r
- SQLite3DB::Statement st=m_db->Prepare("SELECT UUID,Day,IdentityID,RequestIndex FROM tblIntroductionPuzzleRequests WHERE UUID NOT IN (SELECT UUID FROM tblIdentityIntroductionInserts) AND UUID NOT IN (SELECT UUID FROM tblIntroductionPuzzleInserts) AND Day>='"+date.Format("%Y-%m-%d")+"' AND Found='true' ORDER BY IdentityID, Day DESC, RequestIndex DESC;");\r
+ date-=Poco::Timespan(1,0,0,0,0);\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT UUID,Day,IdentityID,RequestIndex FROM tblIntroductionPuzzleRequests WHERE UUID NOT IN (SELECT UUID FROM tblIdentityIntroductionInserts) AND UUID NOT IN (SELECT UUID FROM tblIntroductionPuzzleInserts) AND Day>='"+Poco::DateTimeFormatter::format(date,"%Y-%m-%d")+"' AND Found='true' ORDER BY IdentityID, Day DESC, RequestIndex DESC;");\r
st.Step();\r
\r
if(st.RowReturned()==false)\r
content+="</table>";\r
content+="</form>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool AnnounceIdentityPage::WillHandleURI(const std::string &uri)\r
#include "../../../include/http/pages/boardspage.h"\r
#include "../../../include/stringfunctions.h"\r
-#include "../../../include/datetime.h"\r
+\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
\r
#ifdef XMEM\r
#include <xmem.h>\r
std::string startrowstr="0";\r
std::string boardsearch="";\r
std::string sql="";\r
- DateTime now;\r
- now.SetToGMTime();\r
+ Poco::DateTime now;\r
\r
if(queryvars.find("formaction")!=queryvars.end())\r
{\r
SQLite3DB::Statement addst=m_db->Prepare("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES(?,?,?,?);");\r
addst.Bind(0,boardname);\r
addst.Bind(1,boarddescription);\r
- addst.Bind(2,now.Format("%Y-%m-%d %H:%M:%S"));\r
+ addst.Bind(2,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
addst.Bind(3,"Added manually");\r
addst.Step();\r
}\r
content+="* If you uncheck this box, any new messages you download that are posted to this board will be discarded.";\r
content+="</p>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool BoardsPage::WillHandleURI(const std::string &uri)\r
content+="<input type=\"submit\" value=\"Cancel\">";\r
content+="</form>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
\r
#include "../../../include/http/pages/controlboardpage.h"\r
#include "../../../include/stringfunctions.h"\r
-#include "../../../include/datetime.h"\r
+\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
\r
#ifdef XMEM\r
#include <xmem.h>\r
}\r
if((*queryvars.find("formaction")).second=="addboard" && queryvars.find("boardname")!=queryvars.end() && (*queryvars.find("boardname")).second!="")\r
{\r
- DateTime date;\r
- date.SetToGMTime();\r
+ Poco::DateTime date;\r
st=m_db->Prepare("INSERT INTO tblBoard(BoardName,DateAdded) VALUES(?,?);");\r
st.Bind(0,(*queryvars.find("boardname")).second);\r
- st.Bind(1,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
if(st.Step(true))\r
{\r
boardid=st.GetLastInsertRowID();\r
content+="</tr>";\r
content+="</table>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool ControlBoardPage::WillHandleURI(const std::string &uri)\r
#include "../../../include/http/pages/createidentitypage.h"\r
#include "../../../include/stringfunctions.h"\r
-#include "../../../include/datetime.h"\r
+\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
\r
#ifdef XMEM\r
#include <xmem.h>\r
{\r
SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblLocalIdentity(Name,PublishTrustList,DateCreated) VALUES(?,'false',?);");\r
std::string name="";\r
- DateTime date;\r
- date.SetToGMTime();\r
+ Poco::DateTime date;\r
\r
if(queryvars.find("name")!=queryvars.end())\r
{\r
}\r
\r
st.Bind(0,name);\r
- st.Bind(1,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(1,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
\r
content+="<h2>Created Identity</h2>";\r
content+="</form>";\r
}\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool CreateIdentityPage::WillHandleURI(const std::string &uri)\r
content+="<input type=\"submit\" value=\"Execute Query\">";\r
content+="</form>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool ExecQueryPage::WillHandleURI(const std::string &uri)\r
#include "../../../include/http/pages/homepage.h"\r
#include "../../../include/stringfunctions.h"\r
#include "../../../include/global.h"\r
+#include "../../../include/fmsapp.h"\r
+#include "../../../include/option.h"\r
\r
#ifdef XMEM\r
#include <xmem.h>\r
\r
std::string messagecountstr="";\r
std::string filecountstr="";\r
+ std::string fcphost="127.0.0.1";\r
+ std::string fproxyport="8888";\r
+\r
+ Option::Instance()->Get("FCPHost",fcphost);\r
+ Option::Instance()->Get("FProxyPort",fproxyport);\r
\r
if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="shutdown")\r
{\r
- wantshutdown=true;\r
+ m_log->trace("HomePage::GeneratePage requested shutdown");\r
+ ((FMSApp *)&FMSApp::instance())->Terminate();\r
}\r
\r
std::string content="<h2>Home</h2>";\r
content+="<b>FMS version ";\r
content+=FMS_VERSION;\r
content+="</b><br>";\r
+ content+="Check for new versions at the <a href=\"http://"+fcphost+":"+fproxyport+"/USK@0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/58/\">FMS Freesite</a><br>";\r
content+="Use these pages to administer your FMS installation.";\r
content+="</p>";\r
\r
content+="</form>";\r
content+="</p>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool HomePage::WillHandleURI(const std::string &uri)\r
st.Step();\r
}\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool InsertedFilesPage::WillHandleURI(const std::string &uri)\r
std::string countstr;\r
std::string content="";\r
\r
- if(queryvars.find("formaction")!=queryvars.end())\r
- {\r
- int id;\r
- std::vector<std::string> ids;\r
- std::vector<std::string> singleuse;\r
- std::vector<std::string> publishtrustlist;\r
- std::vector<std::string> publishboardlist;\r
- std::vector<std::string> publishfreesite;\r
- std::vector<std::string> mindelay;\r
- std::vector<std::string> maxdelay;\r
-\r
- CreateArgArray(queryvars,"chkidentityid",ids);\r
- CreateArgArray(queryvars,"singleuse",singleuse);\r
- CreateArgArray(queryvars,"publishtrustlist",publishtrustlist);\r
- CreateArgArray(queryvars,"publishboardlist",publishboardlist);\r
- CreateArgArray(queryvars,"publishfreesite",publishfreesite);\r
- CreateArgArray(queryvars,"mindelay",mindelay);\r
- CreateArgArray(queryvars,"maxdelay",maxdelay);\r
-\r
- if((*queryvars.find("formaction")).second=="update")\r
- {\r
- SQLite3DB::Statement update=m_db->Prepare("UPDATE tblLocalIdentity SET SingleUse=?, PublishTrustList=?, PublishBoardList=?, PublishFreesite=?, MinMessageDelay=?, MaxMessageDelay=? WHERE LocalIdentityID=?;");\r
- for(int i=0; i<ids.size(); i++)\r
- {\r
- if(ids[i]!="")\r
- {\r
- int minmessagedelay=0;\r
- int maxmessagedelay=0;\r
- StringFunctions::Convert(ids[i],id);\r
- StringFunctions::Convert(mindelay[i],minmessagedelay);\r
- StringFunctions::Convert(maxdelay[i],maxmessagedelay);\r
- update.Bind(0,singleuse[i]);\r
- update.Bind(1,publishtrustlist[i]);\r
- update.Bind(2,publishboardlist[i]);\r
- update.Bind(3,publishfreesite[i]);\r
- update.Bind(4,minmessagedelay);\r
- update.Bind(5,maxmessagedelay);\r
- update.Bind(6,id);\r
- update.Step();\r
- update.Reset();\r
- }\r
- }\r
- }\r
- if((*queryvars.find("formaction")).second=="delete")\r
- {\r
- SQLite3DB::Statement del=m_db->Prepare("DELETE FROM tblLocalIdentity WHERE LocalIdentityID=?;");\r
- for(int i=0; i<ids.size(); i++)\r
- {\r
- if(ids[i]!="")\r
- {\r
- StringFunctions::Convert(ids[i],id);\r
- del.Bind(0,id);\r
- del.Step();\r
- del.Reset();\r
- }\r
- }\r
- }\r
- if((*queryvars.find("formaction")).second=="export")\r
- {\r
- IdentityExportXML xml;\r
- SQLite3DB::Statement exp=m_db->Prepare("SELECT Name,PublicKey,PrivateKey,SingleUse,PublishTrustList,PublishBoardList,PublishFreesite FROM tblLocalIdentity WHERE PublicKey IS NOT NULL AND PrivateKey IS NOT NULL;");\r
- exp.Step();\r
- while(exp.RowReturned())\r
- {\r
- std::string name="";\r
- std::string publickey="";\r
- std::string privatekey="";\r
- std::string tempval="";\r
- bool singleuse=false;\r
- bool publishtrustlist=false;\r
- bool publishboardlist=false;\r
- bool publishfreesite=false;\r
-\r
- exp.ResultText(0,name);\r
- exp.ResultText(1,publickey);\r
- exp.ResultText(2,privatekey);\r
- exp.ResultText(3,tempval);\r
- if(tempval=="true")\r
- {\r
- singleuse=true;\r
- }\r
- exp.ResultText(4,tempval);\r
- if(tempval=="true")\r
- {\r
- publishtrustlist=true;\r
- }\r
- exp.ResultText(5,tempval);\r
- if(tempval=="true")\r
- {\r
- publishboardlist=true;\r
- }\r
- exp.ResultText(6,tempval);\r
- if(tempval=="true")\r
- {\r
- publishfreesite=true;\r
- }\r
-\r
- xml.AddIdentity(name,publickey,privatekey,singleuse,publishtrustlist,publishboardlist,publishfreesite);\r
-\r
- exp.Step();\r
- }\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\nContent-Disposition: attachment; filename=identities.xml\r\n\r\n"+xml.GetXML();\r
- }\r
- if((*queryvars.find("formaction")).second=="import")\r
- {\r
- if(queryvars.find("file")!=queryvars.end())\r
- {\r
- IdentityExportXML xml;\r
- if(xml.ParseXML((*queryvars.find("file")).second))\r
- {\r
- SQLite3DB::Statement imp=m_db->Prepare("INSERT INTO tblLocalIdentity(Name,PublicKey,PrivateKey,SingleUse,PublishTrustList,PublishBoardList,PublishFreesite) VALUES(?,?,?,?,?,?,?);");\r
- for(int i=0; i<xml.GetCount(); i++)\r
- {\r
- std::string tempval="false";\r
- imp.Bind(0,xml.GetName(i));\r
- imp.Bind(1,xml.GetPublicKey(i));\r
- imp.Bind(2,xml.GetPrivateKey(i));\r
- if(xml.GetSingleUse(i))\r
- {\r
- tempval="true";\r
- }\r
- else\r
- {\r
- tempval="false";\r
- }\r
- imp.Bind(3,tempval);\r
- if(xml.GetPublishTrustList(i))\r
- {\r
- tempval="true";\r
- }\r
- else\r
- {\r
- tempval="false";\r
- }\r
- imp.Bind(4,tempval);\r
- if(xml.GetPublishBoardList(i))\r
- {\r
- tempval="true";\r
- }\r
- else\r
- {\r
- tempval="false";\r
- }\r
- imp.Bind(5,tempval);\r
- if(xml.GetPublishFreesite(i))\r
- {\r
- tempval="true";\r
- }\r
- else\r
- {\r
- tempval="false";\r
- }\r
- imp.Bind(6,tempval);\r
- imp.Step();\r
- imp.Reset();\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
content+="<h2>Local Identities</h2>";\r
\r
content+="<table><tr><th>Export Identities</th><th>Import Identities</th></tr>";\r
\r
content+="<hr>";\r
\r
-// content+="<form name=\"frmlocalidentity\" method=\"POST\">";\r
-// content+="<input type=\"hidden\" name=\"formaction\" value=\"update\">";\r
content+="<table><tr><th>Name</th><th>Single Use</th><th>Publish Trust List</th><th>Publish Board List</th><th>Publish Freesite</th><th>Min Message Delay</th><th>Max Message Delay</th><th>Announced? *</th></tr>";\r
\r
SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID,tblLocalIdentity.Name,tblLocalIdentity.PublicKey,tbLLocalIdentity.PublishTrustList,tblLocalIdentity.SingleUse,tblLocalIdentity.PublishBoardList,tblIdentity.IdentityID,tblLocalIdentity.PublishFreesite,tblLocalIdentity.MinMessageDelay,tblLocalIdentity.MaxMessageDelay FROM tblLocalIdentity LEFT JOIN tblIdentity ON tblLocalIdentity.PublicKey=tblIdentity.PublicKey ORDER BY tblLocalIdentity.Name;");\r
st.ResultText(9,maxmessagedelay);\r
\r
content+="<tr>";\r
-// content+="<td><input type=\"checkbox\" name=\"chkidentityid["+countstr+"]\" value=\""+id+"\"></td>";\r
content+="<td title=\""+publickey+"\"><form name=\"frmupdate\""+countstr+"\" method=\"POST\"><input type=\"hidden\" name=\"formaction\" value=\"update\"><input type=\"hidden\" name=\"chkidentityid["+countstr+"]\" value=\""+id+"\">"+SanitizeOutput(CreateShortIdentityName(name,publickey))+"</td>";\r
content+="<td>"+CreateTrueFalseDropDown("singleuse["+countstr+"]",singleuse)+"</td>";\r
content+="<td>"+CreateTrueFalseDropDown("publishtrustlist["+countstr+"]",publishtrustlist)+"</td>";\r
}\r
trustst.Reset();\r
\r
-/*\r
- if(st.ResultNull(6))\r
- {\r
- content+="<td>No</td>";\r
- }\r
- else\r
- {\r
- content+="<td>Yes</td>";\r
- }\r
-*/\r
-\r
content+="<td><input type=\"submit\" value=\"Update\"></form></td>";\r
content+="<td><form name=\"frmdel\""+countstr+"\" method=\"POST\" action=\"confirm.htm\"><input type=\"hidden\" name=\"formaction\" value=\"delete\"><input type=\"hidden\" name=\"chkidentityid["+countstr+"]\" value=\""+id+"\"><input type=\"hidden\" name=\"targetpage\" value=\"localidentities.htm\"><input type=\"hidden\" name=\"confirmdescription\" value=\"Are you sure you want to delete "+SanitizeOutput(CreateShortIdentityName(name,publickey))+"?\"><input type=\"submit\" value=\"Delete\"></form></td>";\r
content+="</tr>";\r
count++;\r
}\r
\r
-// content+="<tr><td colspan=\"5\"><center><input type=\"submit\" value=\"Update Selected\"> <input type=\"submit\" value=\"Delete Selected\" onClick=\"if(confirm('Delete Selected Identities?')){frmlocalidentity.formaction.value='delete';}else{return false;}\"></td></tr>";\r
content+="</table>";\r
content+="<p class=\"paragraph\">* An identity is considered successfully announced when you have downloaded a trust list from someone that contains the identity. The number in parenthesis is how many trust lists that identity appears in.</p>";\r
content+="<p class=\"paragraph\">Single Use Identities will automatically be deleted 7 days after creation.</p>";\r
content+="<p class=\"paragraph\">Messages that each identity sends may be delayed by a random number of minutes between min and max. Set both to 0 to send messages as soon as possible.</p>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+}\r
+\r
+void LocalIdentitiesPage::HandleDelete(const std::map<std::string,std::string> &queryvars)\r
+{\r
+ int id=0;\r
+ std::vector<std::string> ids;\r
+ CreateArgArray(queryvars,"chkidentityid",ids);\r
+\r
+ SQLite3DB::Statement del=m_db->Prepare("DELETE FROM tblLocalIdentity WHERE LocalIdentityID=?;");\r
+ for(int i=0; i<ids.size(); i++)\r
+ {\r
+ if(ids[i]!="")\r
+ {\r
+ StringFunctions::Convert(ids[i],id);\r
+ del.Bind(0,id);\r
+ del.Step();\r
+ del.Reset();\r
+ }\r
+ }\r
+}\r
+\r
+const std::string LocalIdentitiesPage::HandleExport()\r
+{\r
+ IdentityExportXML xml;\r
+ SQLite3DB::Statement exp=m_db->Prepare("SELECT Name,PublicKey,PrivateKey,SingleUse,PublishTrustList,PublishBoardList,PublishFreesite FROM tblLocalIdentity WHERE PublicKey IS NOT NULL AND PrivateKey IS NOT NULL;");\r
+ exp.Step();\r
+ while(exp.RowReturned())\r
+ {\r
+ std::string name="";\r
+ std::string publickey="";\r
+ std::string privatekey="";\r
+ std::string tempval="";\r
+ bool singleuse=false;\r
+ bool publishtrustlist=false;\r
+ bool publishboardlist=false;\r
+ bool publishfreesite=false;\r
+\r
+ exp.ResultText(0,name);\r
+ exp.ResultText(1,publickey);\r
+ exp.ResultText(2,privatekey);\r
+ exp.ResultText(3,tempval);\r
+ if(tempval=="true")\r
+ {\r
+ singleuse=true;\r
+ }\r
+ exp.ResultText(4,tempval);\r
+ if(tempval=="true")\r
+ {\r
+ publishtrustlist=true;\r
+ }\r
+ exp.ResultText(5,tempval);\r
+ if(tempval=="true")\r
+ {\r
+ publishboardlist=true;\r
+ }\r
+ exp.ResultText(6,tempval);\r
+ if(tempval=="true")\r
+ {\r
+ publishfreesite=true;\r
+ }\r
+\r
+ xml.AddIdentity(name,publickey,privatekey,singleuse,publishtrustlist,publishboardlist,publishfreesite);\r
+\r
+ exp.Step();\r
+ }\r
+ return xml.GetXML();\r
+}\r
+\r
+void LocalIdentitiesPage::HandleImport(const std::map<std::string,std::string> &queryvars)\r
+{\r
+ if(queryvars.find("file")!=queryvars.end())\r
+ {\r
+ IdentityExportXML xml;\r
+ if(xml.ParseXML((*queryvars.find("file")).second))\r
+ {\r
+ SQLite3DB::Statement imp=m_db->Prepare("INSERT INTO tblLocalIdentity(Name,PublicKey,PrivateKey,SingleUse,PublishTrustList,PublishBoardList,PublishFreesite) VALUES(?,?,?,?,?,?,?);");\r
+ for(int i=0; i<xml.GetCount(); i++)\r
+ {\r
+ std::string tempval="false";\r
+ imp.Bind(0,xml.GetName(i));\r
+ imp.Bind(1,xml.GetPublicKey(i));\r
+ imp.Bind(2,xml.GetPrivateKey(i));\r
+ if(xml.GetSingleUse(i))\r
+ {\r
+ tempval="true";\r
+ }\r
+ else\r
+ {\r
+ tempval="false";\r
+ }\r
+ imp.Bind(3,tempval);\r
+ if(xml.GetPublishTrustList(i))\r
+ {\r
+ tempval="true";\r
+ }\r
+ else\r
+ {\r
+ tempval="false";\r
+ }\r
+ imp.Bind(4,tempval);\r
+ if(xml.GetPublishBoardList(i))\r
+ {\r
+ tempval="true";\r
+ }\r
+ else\r
+ {\r
+ tempval="false";\r
+ }\r
+ imp.Bind(5,tempval);\r
+ if(xml.GetPublishFreesite(i))\r
+ {\r
+ tempval="true";\r
+ }\r
+ else\r
+ {\r
+ tempval="false";\r
+ }\r
+ imp.Bind(6,tempval);\r
+ imp.Step();\r
+ imp.Reset();\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void LocalIdentitiesPage::handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response)\r
+{\r
+ m_log->trace("LocalIdentitiesPages::handleRequest from "+request.clientAddress().toString());\r
+\r
+ std::map<std::string,std::string> vars;\r
+ CreateQueryVarMap(request,vars);\r
+\r
+ std::string formaction="";\r
+ if(vars.find("formaction")!=vars.end())\r
+ {\r
+ formaction=(*vars.find("formaction")).second;\r
+ if(formaction=="update")\r
+ {\r
+ HandleUpdate(vars);\r
+ }\r
+ else if(formaction=="delete")\r
+ {\r
+ HandleDelete(vars);\r
+ }\r
+ else if(formaction=="export")\r
+ {\r
+ response.setChunkedTransferEncoding(true);\r
+ response.setContentType("application/xml");\r
+ response.set("Content-Disposition","attachment; filename=identities.xml");\r
+ std::ostream &out=response.send();\r
+ out << HandleExport();\r
+ return;\r
+ }\r
+ else if(formaction=="import")\r
+ {\r
+ HandleImport(vars);\r
+ }\r
+ }\r
+\r
+ response.setChunkedTransferEncoding(true);\r
+ response.setContentType("text/html");\r
+\r
+ std::ostream &ostr = response.send();\r
+ ostr << GeneratePage(request.getMethod(),vars);\r
+}\r
+\r
+void LocalIdentitiesPage::HandleUpdate(const std::map<std::string,std::string> &queryvars)\r
+{\r
+ int id;\r
+ std::vector<std::string> ids;\r
+ std::vector<std::string> singleuse;\r
+ std::vector<std::string> publishtrustlist;\r
+ std::vector<std::string> publishboardlist;\r
+ std::vector<std::string> publishfreesite;\r
+ std::vector<std::string> mindelay;\r
+ std::vector<std::string> maxdelay;\r
+\r
+ CreateArgArray(queryvars,"chkidentityid",ids);\r
+ CreateArgArray(queryvars,"singleuse",singleuse);\r
+ CreateArgArray(queryvars,"publishtrustlist",publishtrustlist);\r
+ CreateArgArray(queryvars,"publishboardlist",publishboardlist);\r
+ CreateArgArray(queryvars,"publishfreesite",publishfreesite);\r
+ CreateArgArray(queryvars,"mindelay",mindelay);\r
+ CreateArgArray(queryvars,"maxdelay",maxdelay);\r
+\r
+ SQLite3DB::Statement update=m_db->Prepare("UPDATE tblLocalIdentity SET SingleUse=?, PublishTrustList=?, PublishBoardList=?, PublishFreesite=?, MinMessageDelay=?, MaxMessageDelay=? WHERE LocalIdentityID=?;");\r
+ for(int i=0; i<ids.size(); i++)\r
+ {\r
+ if(ids[i]!="")\r
+ {\r
+ int minmessagedelay=0;\r
+ int maxmessagedelay=0;\r
+ StringFunctions::Convert(ids[i],id);\r
+ StringFunctions::Convert(mindelay[i],minmessagedelay);\r
+ StringFunctions::Convert(maxdelay[i],maxmessagedelay);\r
+ update.Bind(0,singleuse[i]);\r
+ update.Bind(1,publishtrustlist[i]);\r
+ update.Bind(2,publishboardlist[i]);\r
+ update.Bind(3,publishfreesite[i]);\r
+ update.Bind(4,minmessagedelay);\r
+ update.Bind(5,maxmessagedelay);\r
+ update.Bind(6,id);\r
+ update.Step();\r
+ update.Reset();\r
+ }\r
+ }\r
}\r
\r
const bool LocalIdentitiesPage::WillHandleURI(const std::string &uri)\r
update.Reset();\r
}\r
}\r
+\r
}\r
\r
SQLite3DB::Statement st=m_db->Prepare("SELECT Option,OptionValue,OptionDescription,Section,ValidValues FROM tblOption ORDER BY SortOrder;");\r
st.Step();\r
count++;\r
}\r
-\r
+content+="<input type=\"hidden\" name=\"param[0]\" value=\"\">";\r
content+="<tr><td colspan=\"3\"><center><input type=\"submit\" value=\"Save\"></form></td></tr>";\r
content+="</table>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool OptionsPage::WillHandleURI(const std::string &uri)\r
}\r
content+="</table>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const std::string PeerDetailsPage::GetClassString(const std::string &trustlevel)\r
#include "../../../include/http/pages/peermaintenancepage.h"\r
#include "../../../include/stringfunctions.h"\r
-#include "../../../include/datetime.h"\r
+\r
+#include <Poco/DateTime.h>\r
+#include <Poco/Timestamp.h>\r
+#include <Poco/Timespan.h>\r
+#include <Poco/DateTimeFormatter.h>\r
\r
#ifdef XMEM\r
#include <xmem.h>\r
std::string content="";\r
SQLite3DB::Statement st;\r
std::string tempval;\r
- DateTime date;\r
+ Poco::DateTime date;\r
\r
if(queryvars.find("formaction")!=queryvars.end())\r
{\r
}\r
else if((*queryvars.find("formaction")).second=="removelastseen20")\r
{\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-20);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(20,0,0,0,0);\r
st=m_db->Prepare("DELETE FROM tblIdentity WHERE LastSeen<?;");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
}\r
else if((*queryvars.find("formaction")).second=="removeneversent")\r
}\r
else if((*queryvars.find("formaction")).second=="removelastseenneversent20")\r
{\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-20);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(20,0,0,0,0);\r
st=m_db->Prepare("DELETE FROM tblIdentity WHERE IdentityID NOT IN (SELECT IdentityID FROM tblMessage GROUP BY IdentityID) AND LastSeen<?;");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
}\r
else if((*queryvars.find("formaction")).second=="removedaysago" && queryvars.find("daysago")!=queryvars.end() && (*queryvars.find("daysago")).second!="")\r
{\r
int tempint=10000;\r
StringFunctions::Convert((*queryvars.find("daysago")).second,tempint);\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-tempint);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(tempint,0,0,0,0);\r
st=m_db->Prepare("DELETE FROM tblIdentity WHERE LastSeen<?;");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
}\r
else if((*queryvars.find("formaction")).second=="removenulldaysago" && queryvars.find("daysago")!=queryvars.end() && (*queryvars.find("daysago")).second!="")\r
{\r
int tempint=10000;\r
StringFunctions::Convert((*queryvars.find("daysago")).second,tempint);\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-tempint);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(tempint,0,0,0,0);\r
st=m_db->Prepare("DELETE FROM tblIdentity WHERE LastSeen<? AND LocalMessageTrust IS NULL AND LocalTrustListTrust IS NULL;");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
}\r
else if((*queryvars.find("formaction")).second=="removeposted30daysago")\r
{\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-30);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(30,0,0,0,0);\r
st=m_db->Prepare("DELETE FROM tblIdentity WHERE IdentityID IN (SELECT tblIdentity.IdentityID FROM tblIdentity INNER JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE (SELECT MAX(MessageDate) FROM tblMessage WHERE tblMessage.IdentityID=tblIdentity.IdentityID)<=? GROUP BY tblIdentity.IdentityID);");\r
- st.Bind(0,date.Format("%Y-%m-%d"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
st.Step();\r
}\r
else if((*queryvars.find("formaction")).second=="removeadded20daysneversent")\r
{\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-20);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(20,0,0,0,0);\r
st=m_db->Prepare("DELETE FROM tblIdentity WHERE IdentityID IN (SELECT tblIdentity.IdentityID FROM tblIdentity LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE tblMessage.IdentityID IS NULL AND tblIdentity.DateAdded<?);");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
}\r
}\r
content+="</td>";\r
content+="</tr>";\r
\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-20);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(20,0,0,0,0);\r
st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity WHERE LastSeen<?;");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
st.ResultText(0,tempval);\r
content+="<tr>";\r
content+="</td>";\r
content+="</tr>";\r
\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-30);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(30,0,0,0,0);\r
st=m_db->Prepare("SELECT COUNT(*) FROM (SELECT tblIdentity.IdentityID FROM tblIdentity INNER JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE (SELECT MAX(MessageDate) FROM tblMessage WHERE tblMessage.IdentityID=tblIdentity.IdentityID)<=? GROUP BY tblIdentity.IdentityID);");\r
- st.Bind(0,date.Format("%Y-%m-%d"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d"));\r
st.Step();\r
st.ResultText(0,tempval);\r
content+="<tr>";\r
content+="</td>";\r
content+="</tr>";\r
\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-20);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(20,0,0,0,0);\r
st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE tblMessage.IdentityID IS NULL AND tblIdentity.DateAdded<?;");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
st.ResultText(0,tempval);\r
content+="<tr>";\r
content+="</td>";\r
content+="</tr>";\r
\r
- date.SetToGMTime();\r
- date.Add(0,0,0,-20);\r
+ date=Poco::Timestamp();\r
+ date-=Poco::Timespan(20,0,0,0,0);\r
st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID WHERE tblMessage.IdentityID IS NULL AND tblIdentity.LastSeen<?;");\r
- st.Bind(0,date.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
st.ResultText(0,tempval);\r
content+="<tr>";\r
\r
content+="</table>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const bool PeerMaintenancePage::WillHandleURI(const std::string &uri)\r
content+="</tr>\r\n";\r
\r
// get count of identities we are showing\r
- sql="SELECT COUNT(*) FROM tblIdentity LEFT JOIN (SELECT IdentityID FROM tblIdentityTrust WHERE LocalIdentityID=?) AS 'tblIdentityTrust' ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID ";\r
- sql+="WHERE tblIdentity.Hidden='false'";\r
+ sql="SELECT COUNT(*) FROM tblIdentity LEFT JOIN tblIdentityTrust ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID ";\r
+ sql+="WHERE tblIdentity.Hidden='false' AND tblIdentityTrust.LocalIdentityID=?";\r
if(namesearch!="")\r
{\r
sql+=" AND (Name LIKE '%' || ? || '%' OR PublicKey LIKE '%' || ? || '%')";\r
st.Finalize();\r
\r
sql="SELECT tblIdentity.IdentityID,Name,tblIdentityTrust.LocalMessageTrust,PeerMessageTrust,tblIdentityTrust.LocalTrustListTrust,PeerTrustListTrust,PublicKey,tblIdentityTrust.MessageTrustComment,tblIdentityTrust.TrustListTrustComment,COUNT(MessageID) AS 'MessageCount',tblIdentity.PublishTrustList ";\r
- sql+="FROM tblIdentity LEFT JOIN (SELECT LocalIdentityID,IdentityID,LocalMessageTrust,LocalTrustListTrust,MessageTrustComment,TrustListTrustComment FROM tblIdentityTrust WHERE LocalIdentityID=?) AS tblIdentityTrust ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID ";\r
- sql+="WHERE tblIdentity.Hidden='false'";\r
+ sql+="FROM tblIdentity LEFT JOIN tblIdentityTrust ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID ";\r
+ sql+="WHERE tblIdentity.Hidden='false' AND tblIdentityTrust.LocalIdentityID=?";\r
if(namesearch!="")\r
{\r
sql+=" AND (Name LIKE '%' || ? || '%' OR PublicKey LIKE '%' || ? || '%')";\r
content+="</table>";\r
content+="</form>";\r
\r
- return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
+ return StringFunctions::Replace(m_template,"[CONTENT]",content);\r
}\r
\r
const std::string PeerTrustPage::GetClassString(const std::string &trustlevel)\r
#include <xmem.h>\r
#endif\r
\r
-const std::string ShowCaptchaPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
+void ShowCaptchaPage::handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response)\r
{\r
- std::string content="HTTP/1.1 200 OK\r\n";\r
+ m_log->trace("ShowCaptchaPage::handleRequest from "+request.clientAddress().toString());\r
+\r
+ std::map<std::string,std::string> queryvars;\r
+ CreateQueryVarMap(request,queryvars);\r
+\r
+ response.setChunkedTransferEncoding(true);\r
+\r
+ std::string content="";\r
if(queryvars.find("UUID")!=queryvars.end())\r
{\r
SQLite3DB::Statement st=m_db->Prepare("SELECT MimeType,PuzzleData FROM tblIntroductionPuzzleRequests WHERE Type='captcha' AND UUID=?;");\r
std::string mime;\r
std::string b64data;\r
std::vector<unsigned char> data;\r
- std::string lenstr;\r
\r
st.ResultText(0,mime);\r
st.ResultText(1,b64data);\r
Base64::Decode(b64data,data);\r
- StringFunctions::Convert(data.size(),lenstr);\r
\r
// mime type should be short and have a / in it - otherwise skip\r
if(mime.size()<50 && mime.find("/")!=std::string::npos)\r
{\r
- content+="Content-Type: "+mime+"\r\n";\r
- content+="Content-Length: "+lenstr+"\r\n\r\n";\r
+ response.setContentType(mime);\r
+ response.setContentLength(data.size());\r
content+=std::string(data.begin(),data.end());\r
}\r
}\r
}\r
- return content;\r
+\r
+ std::ostream &ostr = response.send();\r
+ ostr << content;\r
}\r
\r
const bool ShowCaptchaPage::WillHandleURI(const std::string &uri)\r
--- /dev/null
+#include "../include/ipaddressacl.h"\r
+#include "../include/stringfunctions.h"\r
+\r
+#include <sstream>\r
+#include <cmath>\r
+\r
+IPAddressACL::IPAddressACL():m_allowbydefault(true)\r
+{\r
+\r
+}\r
+\r
+const bool IPAddressACL::Add(const std::string &aclentry)\r
+{\r
+ bool allow=m_allowbydefault;\r
+ int maskbits=0;\r
+ std::string::size_type strpos=std::string::npos;\r
+ std::string entrystr=aclentry;\r
+\r
+ // look for +/- at beginning of string then strip off\r
+ if(entrystr.size()>0)\r
+ {\r
+ if(entrystr[0]=='-')\r
+ {\r
+ allow=false;\r
+ entrystr.erase(0,1);\r
+ }\r
+ else if(entrystr[0]=='+')\r
+ {\r
+ allow=true;\r
+ entrystr.erase(0,1);\r
+ }\r
+ }\r
+\r
+ // look for /mask at end of string then strip off and convert to mask\r
+ if((strpos=entrystr.find("/"))!=std::string::npos)\r
+ {\r
+ if(strpos!=entrystr.size()-1)\r
+ {\r
+ std::string bitmaskstr=entrystr.substr(strpos+1);\r
+ entrystr.erase(strpos);\r
+\r
+ std::istringstream i(bitmaskstr);\r
+ i >> maskbits;\r
+ }\r
+ else\r
+ {\r
+ entrystr.erase(strpos);\r
+ }\r
+ }\r
+\r
+ // try to parse address\r
+ Poco::Net::IPAddress ip;\r
+ if(Poco::Net::IPAddress::tryParse(entrystr,ip))\r
+ {\r
+ m_entries.push_back(entry(allow,Poco::Net::IPAddress(CreateMask(maskbits)),ip));\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}\r
+\r
+const std::string IPAddressACL::CreateMask(const int maskbits)\r
+{\r
+ int bitsleft=maskbits;\r
+ int parts[4]={255,255,255,255};\r
+ std::ostringstream ipstr;\r
+\r
+ for(int i=3; i>=0; i--)\r
+ {\r
+ for(int b=0; b<8 && bitsleft>0; b++)\r
+ {\r
+ parts[i]-=pow((float)2,b);\r
+ bitsleft--;\r
+ }\r
+ }\r
+\r
+ ipstr << parts[0] << "." << parts[1] << "." << parts[2] << "." << parts[3];\r
+\r
+ return ipstr.str();\r
+}\r
+\r
+const bool IPAddressACL::IsAllowed(const Poco::Net::IPAddress &addr)\r
+{\r
+ bool found=false;\r
+ bool rval=m_allowbydefault;\r
+\r
+ for(std::vector<entry>::iterator i=m_entries.begin(); i!=m_entries.end() && found==false; i++)\r
+ {\r
+ Poco::Net::IPAddress ip1=addr;\r
+ Poco::Net::IPAddress ip2=(*i).m_addr;\r
+\r
+ //ip1.mask((*i).m_mask);\r
+ //ip2.mask((*i).m_mask);\r
+\r
+ ip1=MaskAddress(ip1,(*i).m_mask);\r
+ ip2=MaskAddress(ip2,(*i).m_mask);\r
+\r
+ if(ip1==ip2)\r
+ {\r
+ found=true;\r
+ rval=(*i).m_allow;\r
+ }\r
+ }\r
+\r
+ return rval;\r
+}\r
+\r
+const bool IPAddressACL::IsAllowed(const std::string &addrstr)\r
+{\r
+ Poco::Net::IPAddress ip;\r
+ if(Poco::Net::IPAddress::tryParse(addrstr,ip))\r
+ {\r
+ return IsAllowed(ip);\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}\r
+\r
+Poco::Net::IPAddress IPAddressACL::MaskAddress(const Poco::Net::IPAddress &addr, const Poco::Net::IPAddress &mask)\r
+{\r
+ Poco::Net::IPAddress raddr=addr;\r
+ std::vector<std::string> parts1;\r
+ int intparts1[4]={0,0,0,0};\r
+ std::vector<std::string> parts2;\r
+ int intparts2[4]={0,0,0,0};\r
+ int result[4]={0,0,0,0};\r
+ std::ostringstream res;\r
+\r
+ StringFunctions::Split(raddr.toString(),".",parts1);\r
+ StringFunctions::Split(mask.toString(),".",parts2);\r
+\r
+ if(parts1.size()>=4 && parts2.size()>=4)\r
+ {\r
+ for(int i=0; i<4; i++)\r
+ {\r
+ StringFunctions::Convert(parts1[i],intparts1[i]);\r
+ StringFunctions::Convert(parts2[i],intparts2[i]);\r
+ //result[i]=intparts1[i];\r
+ //result[i]|=intparts2[i]&~intparts1[i];\r
+ result[i]=(intparts1[i]&intparts2[i]);\r
+ }\r
+ res << result[0] << "." << result[1] << "." << result[2] << "." << result[3];\r
+ Poco::Net::IPAddress::tryParse(res.str(),raddr);\r
+ }\r
+\r
+ return raddr;\r
+\r
+}\r
+++ /dev/null
-#include "../include/logfile.h"\r
-\r
-#include <ctime>\r
-#include <cstdarg>\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-LogFile::LogFile()\r
-{\r
- m_fileptr=NULL;\r
- m_loglevel=LOGLEVEL_DEBUG;\r
- m_writedate=false;\r
- m_writeloglevel=false;\r
- m_writenewline=true;\r
- m_datebuffer=new char[100];\r
-}\r
-\r
-LogFile::LogFile(const std::string &filename)\r
-{\r
- m_fileptr=NULL; \r
- m_loglevel=LOGLEVEL_DEBUG;\r
- m_writedate=false;\r
- m_writeloglevel=false;\r
- m_filename=filename;\r
- m_writenewline=true;\r
- m_datebuffer=new char[100];\r
-}\r
-\r
-LogFile::~LogFile()\r
-{\r
- CloseFile();\r
- delete [] m_datebuffer;\r
-}\r
-\r
-bool LogFile::CloseFile()\r
-{\r
- //ZThread::Guard<ZThread::Mutex> g(m_logmutex);\r
- PThread::Guard g(m_logmutex);\r
-\r
- if(m_fileptr)\r
- {\r
- fclose(m_fileptr);\r
- m_fileptr=NULL;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-bool LogFile::OpenFile()\r
-{\r
- CloseFile();\r
-\r
- //ZThread::Guard<ZThread::Mutex> g(m_logmutex);\r
- PThread::Guard g(m_logmutex);\r
-\r
- m_fileptr=fopen(m_filename.c_str(),"a+b");\r
-\r
- if(m_fileptr)\r
- {\r
- return true;\r
- }\r
- else\r
- {\r
- return false; \r
- }\r
-}\r
-\r
-void LogFile::WriteDate()\r
-{\r
- if(m_fileptr)\r
- {\r
- time_t rawtime=time(NULL);\r
- struct tm *timeinfo=gmtime(&rawtime);\r
- \r
- strftime(m_datebuffer,99,"%Y-%m-%d %H:%M:%S : ",timeinfo);\r
- m_datebuffer[99]='\0';\r
- \r
- fputs(m_datebuffer,m_fileptr);\r
- }\r
-}\r
-\r
-void LogFile::WriteLog(const char *format, ...)\r
-{\r
- va_list va;\r
- va_start(va,format);\r
- \r
- if(!m_fileptr)\r
- {\r
- OpenFile();\r
- }\r
- \r
- if(m_fileptr)\r
- {\r
- //ZThread::Guard<ZThread::Mutex> g(m_logmutex);\r
- PThread::Guard g(m_logmutex);\r
- if(m_writedate)\r
- {\r
- WriteDate();\r
- }\r
- vfprintf(m_fileptr,format,va);\r
- if(m_writenewline==true)\r
- {\r
- fputs("\r\n",m_fileptr);\r
- }\r
- fflush(m_fileptr);\r
- }\r
- \r
- va_end(va);\r
-\r
-}\r
-\r
-void LogFile::WriteLog(const std::string &text)\r
-{\r
- if(!m_fileptr)\r
- {\r
- OpenFile(); \r
- }\r
- \r
- if(m_fileptr)\r
- {\r
- //ZThread::Guard<ZThread::Mutex> g(m_logmutex);\r
- PThread::Guard g(m_logmutex);\r
- if(m_writedate)\r
- {\r
- WriteDate(); \r
- }\r
- fputs(text.c_str(),m_fileptr);\r
- if(m_writenewline==true)\r
- {\r
- fputs("\r\n",m_fileptr);\r
- }\r
- fflush(m_fileptr);\r
- }\r
-}\r
-\r
-void LogFile::WriteLog(const LogLevel level, const char *format, ...)\r
-{\r
- if(level<=m_loglevel)\r
- {\r
- \r
- va_list va;\r
- va_start(va,format);\r
- \r
- if(!m_fileptr)\r
- {\r
- OpenFile(); \r
- }\r
- \r
- if(m_fileptr)\r
- {\r
- //ZThread::Guard<ZThread::Mutex> g(m_logmutex);\r
- PThread::Guard g(m_logmutex);\r
- if(m_writedate)\r
- {\r
- WriteDate(); \r
- }\r
- if(m_writeloglevel)\r
- {\r
- WriteLogLevel(level); \r
- }\r
- vfprintf(m_fileptr,format,va);\r
- if(m_writenewline==true)\r
- {\r
- fputs("\r\n",m_fileptr);\r
- }\r
- fflush(m_fileptr);\r
- }\r
- \r
- va_end(va);\r
- }\r
-}\r
-\r
-void LogFile::WriteLog(const LogLevel level, const std::string &text)\r
-{\r
- if(level<=m_loglevel)\r
- {\r
- if(!m_fileptr)\r
- {\r
- OpenFile(); \r
- }\r
- \r
- if(m_fileptr)\r
- {\r
- //ZThread::Guard<ZThread::Mutex> g(m_logmutex);\r
- PThread::Guard g(m_logmutex);\r
- if(m_writedate)\r
- {\r
- WriteDate(); \r
- }\r
- if(m_writeloglevel)\r
- {\r
- WriteLogLevel(level);\r
- }\r
- fputs(text.c_str(),m_fileptr);\r
- if(m_writenewline==true)\r
- {\r
- fputs("\r\n",m_fileptr);\r
- }\r
- fflush(m_fileptr);\r
- }\r
- } \r
-}\r
-\r
-void LogFile::WriteLogLevel(LogLevel level)\r
-{\r
- if(m_fileptr)\r
- {\r
- switch(level)\r
- {\r
- case LOGLEVEL_FATAL:\r
- fputs("FATAL : ",m_fileptr);\r
- break; \r
- case LOGLEVEL_ERROR:\r
- fputs("ERROR : ",m_fileptr);\r
- break;\r
- case LOGLEVEL_WARNING:\r
- fputs("WARN : ",m_fileptr);\r
- break;\r
- case LOGLEVEL_INFO:\r
- fputs("INFO : ",m_fileptr);\r
- break;\r
- case LOGLEVEL_DEBUG:\r
- fputs("DEBUG : ",m_fileptr);\r
- break;\r
- default:\r
- fputs("???? : ",m_fileptr);\r
- break;\r
- }\r
- }\r
-}\r
-\r
-void LogFile::WriteNewLine()\r
-{\r
- //ZThread::Guard<ZThread::Mutex> g(m_logmutex);\r
- PThread::Guard g(m_logmutex);\r
-\r
- if(m_fileptr)\r
- {\r
- fputs("\r\n",m_fileptr);\r
- fflush(m_fileptr);\r
- }\r
-}\r
-\r
-#include "../include/global.h"\r
-#include "../include/commandthread.h"\r
-#include "../include/threadcontroller.h"\r
+#include "../include/fmsapp.h"\r
+#include <Poco/Util/ServerApplication.h>\r
\r
-#include <ctime>\r
-#include <csignal>\r
-#include <iostream>\r
-#include <cstring>\r
-#include <cstdlib>\r
-\r
-#ifdef _WIN32\r
- #include "../include/fmsservice.h"\r
-#else\r
- #include "../include/fmsdaemon.h"\r
-#endif\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-\r
- bool daemon=false;\r
-\r
- #ifdef XMEM\r
- xmem_disable_print();\r
- #endif\r
-\r
- // check arguments\r
- if(argc>1)\r
- {\r
- #ifndef _WIN32\r
- if(argv[1] && strncmp(argv[1],"-d",2)==0)\r
- {\r
- Daemonize();\r
- daemon=true;\r
- }\r
- #else\r
- if(argv[1] && strncmp(argv[1],"-i",2)==0)\r
- {\r
- if(ServiceIsInstalled())\r
- {\r
- std::cout << "FMS Service is already installed" << std::endl;\r
- }\r
- else\r
- {\r
- if(ServiceInstall())\r
- {\r
- std::cout << "FMS Service Installed" << std::endl;\r
- }\r
- else\r
- {\r
- std::cout << "Error installing FMS Service" << std::endl;\r
- }\r
- }\r
- return 0;\r
- }\r
- else if(argv[1] && strncmp(argv[1],"-u",2)==0)\r
- {\r
- if(ServiceIsInstalled())\r
- {\r
- if(ServiceUninstall())\r
- {\r
- std::cout << "FMS Service uninstalled" << std::endl;\r
- }\r
- else\r
- {\r
- std::cout << "There was a problem uninstalling the service" << std::endl;\r
- }\r
- }\r
- else\r
- {\r
- std::cout << "FMS Service is not currently installed" << std::endl;\r
- }\r
- return 0;\r
- }\r
- else if(argv[1] && strncmp(argv[1],"-s",2)==0)\r
- {\r
- if(ServiceStart())\r
- {\r
- }\r
- else\r
- {\r
- std::cout << "FMS Service could not be started at this time" << std::endl;\r
- }\r
- return 0;\r
- }\r
- #endif\r
- }\r
-\r
- signal(SIGINT,SigHandler);\r
- signal(SIGTERM,SigHandler);\r
- signal(SIGABRT,SigHandler);\r
-#ifdef _WIN32\r
- signal(SIGBREAK,SigHandler);\r
-#endif\r
-\r
- if(daemon==false)\r
- {\r
- std::cout << "FMS Running in console mode." << std::endl;\r
- std::cout << "Use the administration pages, or CTRL+C to exit" << std::endl << std::endl;\r
- std::cout << "Available command line arguments:" << std::endl;\r
- #ifdef _WIN32\r
- std::cout << "-i\tinstall service" << std::endl;\r
- std::cout << "-u\tuninstall service" << std::endl;\r
- #else\r
- std::cout << "-d\trun as daemon" << std::endl;\r
- #endif\r
- }\r
-\r
- MainFunction();\r
-\r
- return 0;\r
-}\r
-\r
-void MainFunction()\r
-{\r
- srand(time(NULL));\r
-\r
- SetupDB();\r
- SetupDefaultOptions();\r
-\r
- SetupLogFile();\r
-\r
- SetupNetwork();\r
-\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS startup v"FMS_VERSION);\r
-\r
- ThreadController::Instance()->StartThreads();\r
-\r
- do\r
- {\r
- PThread::Sleep(1000);\r
- }while(!wantshutdown);\r
-\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"FMS wants to shutdown");\r
-\r
- Shutdown();\r
-}\r
+POCO_SERVER_MAIN(FMSApp);\r
#include "../include/message.h"\r
#include "../include/nntp/mime/Mime.h"\r
-#include "../include/uuidgenerator.h"\r
#include "../include/stringfunctions.h"\r
#include "../include/freenet/messagexml.h"\r
#include "../include/option.h"\r
\r
+#include <Poco/DateTimeParser.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/UUIDGenerator.h>\r
+#include <Poco/UUID.h>\r
#include <algorithm>\r
\r
#ifdef DO_CHARSET_CONVERSION\r
{\r
if(m_addnewpostfromidentities==true)\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
- st=m_db->Prepare("INSERT INTO tblLocalIdentity(Name) VALUES(?);");\r
+ Poco::DateTime now;\r
+ st=m_db->Prepare("INSERT INTO tblLocalIdentity(Name,DateCreated) VALUES(?,?);");\r
st.Bind(0,name);\r
+ st.Bind(1,Poco::DateTimeFormatter::format(now,"%Y-%m-%d %H:%M:%S"));\r
st.Step(true);\r
return st.GetLastInsertRowID();\r
}\r
rval+="\r\n";\r
rval+="Subject: "+m_subject+"\r\n";\r
// format time as : Wdy, DD Mon YY HH:MM:SS TIMEZONE\r
- rval+="Date: "+m_datetime.Format("%a, %d %b %y %H:%M:%S -0000")+"\r\n";\r
+ rval+="Date: "+Poco::DateTimeFormatter::format(m_datetime,"%w, %d %b %y %H:%M:%S -0000")+"\r\n";\r
if(m_inreplyto.size()>0)\r
{\r
rval+="References: ";\r
std::string messagebody;\r
std::string messagetruststr="";\r
std::string trustlisttruststr="";\r
- UUIDGenerator uuid;\r
- DateTime now;\r
- now.SetToGMTime();\r
+\r
+ Poco::UUIDGenerator uuidgen;\r
+ Poco::UUID uuid;\r
+\r
+ try\r
+ {\r
+ uuid=uuidgen.createRandom();\r
+ }\r
+ catch(...)\r
+ {\r
+ m_log->fatal("Message::HandleAdministrationMessage could not generate a UUID");\r
+ }\r
+\r
+ Poco::DateTime now;\r
StringFunctions::Convert(origmessagetrust,messagetruststr);\r
StringFunctions::Convert(origtrustlisttrust,trustlisttruststr);\r
messagebody="Trust List of "+m_fromname+"\r\n";\r
messagebody+="Local Message Trust : "+messagetruststr+"\r\n";\r
messagebody+="Local Trust List Trust : "+trustlisttruststr+"\r\n";\r
SQLite3DB::Statement insert=m_db->Prepare("INSERT INTO tblMessage(FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body) VALUES('FMS',?,?,?,?,?,?);");\r
- insert.Bind(0,now.Format("%Y-%m-%d"));\r
- insert.Bind(1,now.Format("%H:%M:%S"));\r
+ insert.Bind(0,Poco::DateTimeFormatter::format(now,"%Y-%m-%d"));\r
+ insert.Bind(1,Poco::DateTimeFormatter::format(now,"%H:%M:%S"));\r
insert.Bind(2,identityname+" Trust Changed");\r
- insert.Bind(3,uuid.Generate());\r
+ insert.Bind(3,uuid.toString());\r
insert.Bind(4,boardid);\r
insert.Bind(5,messagebody);\r
insert.Step(true);\r
insert.Bind(1,boardid);\r
insert.Step();\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"Message::HandleAdministrationMessage updated "+identityname+" to "+messagetruststr+" , "+trustlisttruststr);\r
+ m_log->debug("Message::HandleAdministrationMessage updated "+identityname+" to "+messagetruststr+" , "+trustlisttruststr);\r
\r
}\r
}\r
m_subject="";\r
m_body="";\r
m_replyboardname="";\r
- m_datetime.Set();\r
+ m_datetime=Poco::Timestamp();\r
m_fromname="";\r
m_boards.clear();\r
m_inreplyto.clear();\r
st.ResultText(4,m_replyboardname);\r
st.ResultText(5,tempdate);\r
st.ResultText(6,temptime);\r
- m_datetime.Set(tempdate + " " + temptime);\r
st.ResultText(7,m_fromname);\r
st.Finalize();\r
\r
+ int tzdiff=0;\r
+ if(Poco::DateTimeParser::tryParse(tempdate + " " + temptime,m_datetime,tzdiff)==false)\r
+ {\r
+ m_log->error("Message::Load couldn't parse date/time "+tempdate+" "+temptime);\r
+ }\r
+\r
// strip off any \r\n in subject\r
m_subject=StringFunctions::Replace(m_subject,"\r\n","");\r
\r
\r
Initialize();\r
\r
- UUIDGenerator uuid;\r
+ Poco::UUIDGenerator uuidgen;\r
+ Poco::UUID uuid;\r
CMimeMessage mime;\r
mime.Load(nntpmessage.c_str(),nntpmessage.size());\r
\r
// get header info\r
// date is always set to now regardless of what message has\r
- m_datetime.SetToGMTime();\r
+ m_datetime=Poco::Timestamp();\r
\r
// messageuuid is always a unique id we generate regardless of message message-id\r
- m_messageuuid=uuid.Generate();\r
+ try\r
+ {\r
+ uuid=uuidgen.createRandom();\r
+ }\r
+ catch(...)\r
+ {\r
+ m_log->fatal("Message::ParseNNTPMessage could not create UUID");\r
+ }\r
\r
// get from\r
if(mime.GetFieldValue("From"))\r
\r
if(min==max)\r
{\r
- m_datetime.Add(0,min);\r
+ m_datetime+=Poco::Timespan(0,0,min,0,0);\r
}\r
else if(max>min)\r
{\r
int delay=(rand()%(max-min))+min;\r
- m_datetime.Add(0,delay);\r
+ m_datetime+=Poco::Timespan(0,0,delay,0,0);\r
}\r
\r
}\r
st.Finalize();\r
\r
// set date in xml file AFTER we set the delay\r
- xml.SetDate(m_datetime.Format("%Y-%m-%d"));\r
- xml.SetTime(m_datetime.Format("%H:%M:%S"));\r
+ xml.SetDate(Poco::DateTimeFormatter::format(m_datetime,"%Y-%m-%d"));\r
+ xml.SetTime(Poco::DateTimeFormatter::format(m_datetime,"%H:%M:%S"));\r
\r
st=m_db->Prepare("INSERT INTO tblMessageInserts(LocalIdentityID,MessageUUID,MessageXML,SendDate) VALUES(?,?,?,?);");\r
st.Bind(0,localidentityid);\r
st.Bind(1,m_messageuuid);\r
st.Bind(2,xml.GetXML());\r
- st.Bind(3,m_datetime.Format("%Y-%m-%d %H:%M:%S"));\r
+ st.Bind(3,Poco::DateTimeFormatter::format(m_datetime,"%Y-%m-%d %H:%M:%S"));\r
st.Step();\r
\r
// insert file attachments into database\r
#include "../../include/nntp/nntpconnection.h"\r
#include "../../include/nntp/uwildmat.h"\r
#include "../../include/stringfunctions.h"\r
-#include "../../include/datetime.h"\r
#include "../../include/boardlist.h"\r
#include "../../include/message.h"\r
#include "../../include/messagelist.h"\r
#include "../../include/option.h"\r
#include "../../include/nntp/extensiontrust.h"\r
+#include "../../include/threadwrapper/cancelablethread.h"\r
\r
#include <algorithm>\r
-\r
-//#include <zthread/Thread.h>\r
-#include "../../include/pthreadwrapper/thread.h"\r
+#include <Poco/DateTime.h>\r
+#include <Poco/DateTimeFormatter.h>\r
+#include <Poco/Timestamp.h>\r
\r
#ifdef XMEM\r
#include <xmem.h>\r
\r
const bool NNTPConnection::HandleDateCommand(const NNTPCommand &command)\r
{\r
- DateTime now;\r
- now.SetToGMTime();\r
- SendBufferedLine("111 "+now.Format("%Y%m%d%H%M%S"));\r
+ Poco::DateTime now;\r
+ SendBufferedLine("111 "+Poco::DateTimeFormatter::format(now,"%Y%m%d%H%M%S"));\r
return true;\r
}\r
\r
else\r
{\r
SendBufferedLine("501 Syntax error");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleGroupCommand syntax error");\r
+ m_log->debug("NNTPConnection::HandleGroupCommand syntax error");\r
}\r
\r
return true;\r
{\r
// unknown arg\r
SendBufferedLine("501 Syntax error");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListCommand unhandled LIST variant");\r
+ m_log->debug("NNTPConnection::HandleListCommand unhandled LIST variant");\r
}\r
\r
return true;\r
{\r
// unknown arg\r
SendBufferedLine("501 Syntax error");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListGroupCommand unknown arguments");\r
+ m_log->debug("NNTPConnection::HandleListGroupCommand unknown arguments");\r
}\r
\r
if(validgroup)\r
SendBufferedLine("201 Posting prohibited");\r
}\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand set mode to reader");\r
+ m_log->debug("NNTPConnection::HandleModeCommand set mode to reader");\r
}\r
else\r
{\r
SendBufferedLine("501 Syntax error");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand unknown MODE argument : "+arg);\r
+ m_log->debug("NNTPConnection::HandleModeCommand unknown MODE argument : "+arg);\r
}\r
}\r
else\r
{\r
SendBufferedLine("501 Syntax error");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand no argument supplied for MODE"); \r
+ m_log->debug("NNTPConnection::HandleModeCommand no argument supplied for MODE"); \r
}\r
\r
return true;\r
{\r
if(command.m_arguments.size()>=2)\r
{\r
- DateTime date;\r
- int tempint;\r
+ Poco::DateTime date;\r
+ int tempyear=0;\r
+ int tempmonth=0;\r
+ int tempday=0;\r
if(command.m_arguments[0].size()==8)\r
{\r
- StringFunctions::Convert(command.m_arguments[0].substr(0,4),tempint);\r
- date.SetYear(tempint);\r
- StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);\r
- date.SetMonth(tempint);\r
- StringFunctions::Convert(command.m_arguments[0].substr(6,2),tempint);\r
- date.SetDay(tempint);\r
+ StringFunctions::Convert(command.m_arguments[0].substr(0,4),tempyear);\r
+ StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempmonth);\r
+ StringFunctions::Convert(command.m_arguments[0].substr(6,2),tempday);\r
+ try\r
+ {\r
+ date.assign(tempyear,tempmonth,tempday,date.hour(),date.minute(),date.second());\r
+ }\r
+ catch(...)\r
+ {\r
+ m_log->fatal("NNTPConnection::HandleNewGroupsCommand error assigning date");\r
+ }\r
}\r
else\r
{\r
the current year, and the previous century otherwise.\r
*/\r
int century;\r
- DateTime now;\r
- now.SetToGMTime();\r
- century=now.GetYear()-(now.GetYear()%100);\r
+ Poco::DateTime now;\r
+ century=now.year()-(now.year()%100);\r
\r
- StringFunctions::Convert(command.m_arguments[0].substr(0,2),tempint);\r
- tempint<=now.GetYear()-century ? tempint+=century : tempint+=(century-100);\r
+ StringFunctions::Convert(command.m_arguments[0].substr(0,2),tempyear);\r
+ tempyear<=now.year()-century ? tempyear+=century : tempyear+=(century-100);\r
\r
//tempint > 50 ? tempint+=1900 : tempint+=2000;\r
\r
- date.SetYear(tempint);\r
- StringFunctions::Convert(command.m_arguments[0].substr(2,2),tempint);\r
- date.SetMonth(tempint);\r
- StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);\r
- date.SetDay(tempint);\r
+ StringFunctions::Convert(command.m_arguments[0].substr(2,2),tempmonth);\r
+ StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempday);\r
+ try\r
+ {\r
+ date.assign(tempyear,tempmonth,tempday);\r
+ }\r
+ catch(...)\r
+ {\r
+ m_log->fatal("NNTPConnection::HandleNewGroupsCommand error assigning date");\r
+ }\r
}\r
\r
- date.Normalize();\r
-\r
BoardList bl;\r
\r
- bl.LoadNew(date.Format("%Y-%m-%d %H:%M:%S"));\r
+ bl.LoadNew(Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S"));\r
\r
SendBufferedLine("231 List of new newsgroups follows");\r
\r
else\r
{\r
SendBufferedLine("501 Syntax error");\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleNewGroupsCommand syntax error");\r
+ m_log->debug("NNTPConnection::HandleNewGroupsCommand syntax error");\r
}\r
\r
return true;\r
{\r
SendBufferedLine("500 Unknown command");\r
\r
- m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleReceivedData received unhandled NNTP command : "+commandline);\r
+ m_log->debug("NNTPConnection::HandleReceivedData received unhandled NNTP command : "+commandline);\r
}\r
\r
}\r
SendBufferedLine("205 Connection Closing");\r
SocketSend();\r
Disconnect();\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::HandleQuitCommand client closed connection");\r
+ m_log->information("NNTPConnection::HandleQuitCommand client closed connection");\r
return true;\r
}\r
\r
-void NNTPConnection::Run()\r
+void NNTPConnection::run()\r
{\r
struct timeval tv;\r
fd_set writefs,readfs;\r
}\r
else if(rval==SOCKET_ERROR)\r
{\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::run select returned -1 : "+GetSocketErrorMessage()); \r
+ m_log->error("NNTPConnection::run select returned -1 : "+GetSocketErrorMessage()); \r
}\r
\r
-// }while(!Disconnected() && !ZThread::Thread::interrupted());\r
}while(!Disconnected() && !IsCancelled());\r
\r
Disconnect();\r
line=tempval+"\t";\r
line+=message.GetSubject()+"\t";\r
line+=message.GetFromName()+"\t";\r
- line+=message.GetDateTime().Format("%a, %d %b %y %H:%M:%S -0000")+"\t";\r
+ line+=Poco::DateTimeFormatter::format(message.GetDateTime(),"%w, %d %b %y %H:%M:%S -0000")+"\t";\r
line+=message.GetNNTPArticleID()+"\t";\r
references=message.GetInReplyTo();\r
if(references.size()>0)\r
else if(rval==0)\r
{\r
Disconnect();\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::SocketReceive remote host closed connection");\r
+ m_log->information("NNTPConnection::SocketReceive remote host closed connection");\r
}\r
else if(rval==-1)\r
{\r
StringFunctions::Convert(GetSocketErrorNumber(),errnostr);\r
// error on receive - close the connection\r
Disconnect();\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketReceive recv returned -1 : "+errnostr+" - "+GetSocketErrorMessage());\r
+ m_log->error("NNTPConnection::SocketReceive recv returned -1 : "+errnostr+" - "+GetSocketErrorMessage());\r
}\r
}\r
\r
{\r
std::string errnostr;\r
StringFunctions::Convert(GetSocketErrorNumber(),errnostr);\r
- m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketSend returned -1 : "+errnostr+" - "+GetSocketErrorMessage());\r
+ m_log->error("NNTPConnection::SocketSend returned -1 : "+errnostr+" - "+GetSocketErrorMessage());\r
}\r
}\r
}\r
#include "../../include/nntp/nntplistener.h"\r
#include "../../include/nntp/nntpconnection.h"\r
#include "../../include/option.h"\r
-#include "../../include/logfile.h"\r
#include "../../include/global.h"\r
#include "../../include/stringfunctions.h"\r
\r
\r
}\r
\r
-void NNTPListener::Run()\r
+void NNTPListener::run()\r
{\r
int rval;\r
fd_set readfs;\r
std::vector<SOCKET>::iterator listeni;\r
SOCKET highsocket;\r
\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run thread started.");\r
+ m_log->debug("NNTPListener::run thread started.");\r
\r
StartListen();\r
\r
struct sockaddr_storage addr;\r
socklen_t addrlen=sizeof(addr);\r
newsock=accept((*listeni),(struct sockaddr *)&addr,&addrlen);\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPListener::run NNTP client connected");\r
- //m_connections.execute(new NNTPConnection(newsock));\r
- //m_connectionthreads.push_back(new PThread::Thread(new NNTPConnection(newsock)));\r
- m_connections.Execute(new NNTPConnection(newsock));\r
+ m_log->information("NNTPListener::run NNTP client connected");\r
+ m_connections.Start(new NNTPConnection(newsock));\r
}\r
}\r
}\r
-/*\r
- // check for any non-running connection threads that we can delete\r
- for(std::vector<PThread::Thread *>::iterator i=m_connectionthreads.begin(); i!=m_connectionthreads.end(); )\r
- {\r
- if((*i)->IsRunning()==false)\r
- {\r
- delete (*i);\r
- i=m_connectionthreads.erase(i);\r
- }\r
- if(i!=m_connectionthreads.end())\r
- {\r
- i++;\r
- }\r
- }\r
-*/\r
\r
- //}while(!ZThread::Thread::interrupted() && m_listensockets.size()>0);\r
}while(!IsCancelled() && m_listensockets.size()>0);\r
\r
- // see if any threads are still running - just calling interrupt without check would cause assert in debug mode\r
- /*\r
- if(m_connections.wait(1)==false)\r
- {\r
- LogFile::instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run interrupting connection threads and waiting 60 seconds for exit.");\r
- try\r
- {\r
- m_connections.interrupt();\r
- }\r
- catch(...)\r
- {\r
- LogFile::instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run caught unhandled exception.");\r
- }\r
- if(m_connections.wait(60000)==false)\r
- {\r
- LogFile::instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run connection threads did not exit after 60 seconds.");\r
- }\r
- }\r
- */\r
- /*\r
- for(std::vector<PThread::Thread *>::iterator i=m_connectionthreads.begin(); i!=m_connectionthreads.end(); i++)\r
- {\r
- if((*i)->IsRunning())\r
- {\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::Run waiting for connection thread to exit.");\r
- (*i)->Cancel();\r
- (*i)->Join();\r
- }\r
- delete (*i);\r
- }\r
- */\r
m_connections.Cancel();\r
m_connections.Join();\r
\r
}\r
m_listensockets.clear();\r
\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run thread exiting.");\r
+ m_log->debug("NNTPListener::run thread exiting.");\r
\r
}\r
\r
{\r
if(listen(sock,10)==0)\r
{\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPListener::StartListen started listening at "+(*i)+":"+nntpport);\r
+ m_log->information("NNTPListener::StartListen started listening at "+(*i)+":"+nntpport);\r
m_listensockets.push_back(sock);\r
}\r
else\r
{\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen socket listen failed");\r
+ m_log->error("NNTPListener::StartListen socket listen failed");\r
#ifdef _WIN32\r
closesocket(sock);\r
#else\r
}\r
else\r
{\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen socket bind failed");\r
+ m_log->error("NNTPListener::StartListen socket bind failed");\r
#ifdef _WIN32\r
closesocket(sock);\r
#else\r
}\r
else\r
{\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen couldn't create socket");\r
+ m_log->error("NNTPListener::StartListen couldn't create socket");\r
}\r
}\r
}\r
}\r
if(m_listensockets.size()==0)\r
{\r
- LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_FATAL,"NNTPListener::StartListen couldn't start listening on any sockets");\r
+ m_log->fatal("NNTPListener::StartListen couldn't start listening on any sockets");\r
}\r
}\r
--- /dev/null
+#include "../include/optionssetup.h"\r
+#include "../include/db/sqlite3db.h"\r
+\r
+#include <Poco/Message.h>\r
+\r
+#include <string>\r
+#include <sstream>\r
+\r
+void SetupDefaultOptions()\r
+{\r
+ // OptionValue should always be inserted as a string, even if the option really isn't a string - just to keep the field data type consistent\r
+\r
+ std::ostringstream tempstr; // must set tempstr to "" between db inserts\r
+ SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
+ SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue) VALUES(?,?);");\r
+ SQLite3DB::Statement upd=db->Prepare("UPDATE tblOption SET Section=?, SortOrder=?, ValidValues=?, OptionDescription=? WHERE Option=?;");\r
+ int order=0;\r
+\r
+ // LogLevel\r
+ tempstr.str("");\r
+ tempstr << Poco::Message::PRIO_DEBUG;\r
+ st.Bind(0,"LogLevel");\r
+ st.Bind(1,tempstr.str());\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Program");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2,"1|1 - Fatal Errors|2|2 - Critical Errors|3|3 - Errors|4|4 - Warnings|5|5 - Notices|6|6 - Informational Messages|7|7 - Debug Messages|8|8 - Trace Messages");\r
+ upd.Bind(3,"The maximum logging level that will be written to file. Higher levels will include all messages from the previous levels.");\r
+ upd.Bind(4,"LogLevel");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"VacuumOnStartup");\r
+ st.Bind(1,"false");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Program");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2,"true|true|false|false");\r
+ upd.Bind(3,"VACUUM the database every time FMS starts. This will defragment the free space in the database and create a smaller database file. Vacuuming the database can be CPU and disk intensive.");\r
+ upd.Bind(4,"VacuumOnStartup");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MessageBase");\r
+ st.Bind(1,"fms");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Program");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"A unique string shared by all clients who want to communicate with each other. This should not be changed unless you want to create your own separate communications network.");\r
+ upd.Bind(4,"MessageBase");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ // StartNNTP\r
+ st.Bind(0,"StartNNTP");\r
+ st.Bind(1,"true");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"NNTP Server");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2,"true|true|false|false");\r
+ upd.Bind(3,"Start NNTP server.");\r
+ upd.Bind(4,"StartNNTP");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ // NNTPListenPort\r
+ st.Bind(0,"NNTPListenPort");\r
+ st.Bind(1,"1119");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"NNTP Server");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"The port that the NNTP service will listen for incoming connections.");\r
+ upd.Bind(4,"NNTPListenPort");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ // NNTPBindAddresses\r
+ st.Bind(0,"NNTPBindAddresses");\r
+ st.Bind(1,"localhost");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"NNTP Server");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");\r
+ upd.Bind(4,"NNTPBindAddresses");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"NNTPAllowPost");\r
+ st.Bind(1,"true");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"NNTP Server");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2,"true|true|false|false");\r
+ upd.Bind(3,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");\r
+ upd.Bind(4,"NNTPAllowPost");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"StartHTTP");\r
+ st.Bind(1,"true");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"HTTP Server");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2,"true|true|false|false");\r
+ upd.Bind(3,"Start HTTP server. WARNING: If you turn this off, you won't be able to access the administration pages.");\r
+ upd.Bind(4,"StartHTTP");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"HTTPListenPort");\r
+ st.Bind(1,"8080");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"HTTP Server");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Port HTTP server will listen on.");\r
+ upd.Bind(4,"HTTPListenPort");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"HTTPAccessControl");\r
+ st.Bind(1,"-0.0.0.0/0,+127.0.0.1");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"HTTP Server");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Comma separated list of addresses and/or subnet masks that are allowed access to the administration pages. Default is localhost only. + allows a host, - denies a host.");\r
+ upd.Bind(4,"HTTPAccessControl");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ // StartFreenetUpdater\r
+ st.Bind(0,"StartFreenetUpdater");\r
+ st.Bind(1,"true");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Freenet Connection");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2,"true|true|false|false");\r
+ upd.Bind(3,"Set to true to start the Freenet Updater thread and connect to Freenet. Set to false to prevent communication with Freenet.");\r
+ upd.Bind(4,"StartFreenetUpdater");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ // FCPHost\r
+ st.Bind(0,"FCPHost");\r
+ st.Bind(1,"127.0.0.1");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Freenet Connection");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Host name or address of Freenet node.");\r
+ upd.Bind(4,"FCPHost");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ // FCPPort\r
+ st.Bind(0,"FCPPort");\r
+ st.Bind(1,"9481");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Freenet Connection");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"The port that Freenet is listening for FCP connections on.");\r
+ upd.Bind(4,"FCPPort");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"FProxyPort");\r
+ st.Bind(1,"8888");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Freenet Connection");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"The port that Freenet is listening for http connections on.");\r
+ upd.Bind(4,"FProxyPort");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MaxIdentityRequests");\r
+ st.Bind(1,"5");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Requests");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Maximum number of concurrent requests for new Identity xml files");\r
+ upd.Bind(4,"MaxIdentityRequests");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MaxIdentityIntroductionRequests");\r
+ st.Bind(1,"5");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Requests");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");\r
+ upd.Bind(4,"MaxIdentityIntroductionRequests");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MaxIntroductionPuzzleRequests");\r
+ st.Bind(1,"5");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Requests");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");\r
+ upd.Bind(4,"MaxIntroductionPuzzleRequests");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MaxTrustListRequests");\r
+ st.Bind(1,"5");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Requests");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Maximum number of concurrent requests for new Trust Lists");\r
+ upd.Bind(4,"MaxTrustListRequests");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MaxMessageListRequests");\r
+ st.Bind(1,"5");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Requests");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Maximum number of concurrent requests for new Message Lists");\r
+ upd.Bind(4,"MaxMessageListRequests");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MaxMessageRequests");\r
+ st.Bind(1,"20");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Requests");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Maximum number of concurrent requests for new Messages");\r
+ upd.Bind(4,"MaxMessageRequests");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MaxBoardListRequests");\r
+ st.Bind(1,"5");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Requests");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");\r
+ upd.Bind(4,"MaxBoardListRequests");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MinLocalMessageTrust");\r
+ st.Bind(1,"50");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Trust");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");\r
+ upd.Bind(4,"MinLocalMessageTrust");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MinPeerMessageTrust");\r
+ st.Bind(1,"30");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Trust");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");\r
+ upd.Bind(4,"MinPeerMessageTrust");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MinLocalTrustListTrust");\r
+ st.Bind(1,"50");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Trust");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Specifies a local trust list trust level that a peer must have before its trust list will be included in the weighted average. Any peers below this number will be excluded from the results.");\r
+ upd.Bind(4,"MinLocalTrustListTrust");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MinPeerTrustListTrust");\r
+ st.Bind(1,"30");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Trust");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Specifies a peer trust list trust level that a peer must have before its trust list will be included in the weighted average. Any peers below this number will be excluded from the results.");\r
+ upd.Bind(4,"MinPeerTrustListTrust");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"LocalTrustOverridesPeerTrust");\r
+ st.Bind(1,"false");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Trust");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2,"true|true|false|false");\r
+ upd.Bind(3,"Set to true if you want your local trust levels to override the peer levels when determining which identities you will poll.");\r
+ upd.Bind(4,"LocalTrustOverridesPeerTrust");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MessageDownloadMaxDaysBackward");\r
+ st.Bind(1,"5");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Messages");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"The maximum number of days backward that messages will be downloaded from each identity");\r
+ upd.Bind(4,"MessageDownloadMaxDaysBackward");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MessageListDaysBackward");\r
+ st.Bind(1,"5");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Messages");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"The number of days backward that messages you have inserted will appear in your MessageLists");\r
+ upd.Bind(4,"MessageListDaysBackward");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MaxPeerMessagesPerDay");\r
+ st.Bind(1,"200");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Messages");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"The maximum number of messages you will download from each peer on a given day.");\r
+ upd.Bind(4,"MaxPeerMessagesPerDay");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"MaxBoardsPerMessage");\r
+ st.Bind(1,"8");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Messages");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");\r
+ upd.Bind(4,"MaxBoardsPerMessage");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"SaveMessagesFromNewBoards");\r
+ st.Bind(1,"true");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Messages");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2,"true|true|false|false");\r
+ upd.Bind(3,"Set to true to automatically save messages posted to new boards. Set to false to ignore messages to new boards.");\r
+ upd.Bind(4,"SaveMessagesFromNewBoards");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"ChangeMessageTrustOnReply");\r
+ st.Bind(1,"0");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Messages");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"How much the local message trust level of an identity should change when you reply to one of their messages.");\r
+ upd.Bind(4,"ChangeMessageTrustOnReply");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"AddNewPostFromIdentities");\r
+ st.Bind(1,"false");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Messages");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2,"true|true|false|false");\r
+ upd.Bind(3,"Set to true to automatically create new identities when you send a message using a new name. If you set this to false, posting messages will fail until you manually create the identity.");\r
+ upd.Bind(4,"AddNewPostFromIdentities");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+ st.Bind(0,"DeleteMessagesOlderThan");\r
+ st.Bind(1,"180");\r
+ st.Step();\r
+ st.Reset();\r
+ upd.Bind(0,"Messages");\r
+ upd.Bind(1,order++);\r
+ upd.Bind(2);\r
+ upd.Bind(3,"Automatically delete messages older than this many days.");\r
+ upd.Bind(4,"DeleteMessagesOlderThan");\r
+ upd.Step();\r
+ upd.Reset();\r
+\r
+}\r
+++ /dev/null
-#include "../../include/pthreadwrapper/guard.h"\r
-#include "../../include/pthreadwrapper/mutex.h"\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-namespace PThread\r
-{\r
-\r
-Guard::Guard()\r
-{\r
- m_mutex=0;\r
-}\r
-\r
-Guard::Guard(Mutex &mutex)\r
-{\r
- m_mutex=&mutex;\r
- m_mutex->Acquire(); \r
-}\r
-\r
-Guard::~Guard()\r
-{\r
- if(m_mutex)\r
- {\r
- m_mutex->Release(); \r
- }\r
-}\r
-\r
-} // namespace\r
+++ /dev/null
-#include "../../include/pthreadwrapper/mutex.h"\r
-#include <exception>\r
-\r
-#ifndef _WIN32\r
- #include <sys/errno.h>\r
-#endif\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-namespace PThread\r
-{\r
-\r
-Mutex::Mutex()\r
-{\r
- pthread_mutexattr_init(&m_attr);\r
- pthread_mutexattr_settype(&m_attr,PTHREAD_MUTEX_ERRORCHECK);\r
- pthread_mutex_init(&m_mutex,&m_attr);\r
-}\r
-\r
-Mutex::~Mutex()\r
-{\r
- pthread_mutex_destroy(&m_mutex);\r
- pthread_mutexattr_destroy(&m_attr);\r
-}\r
-\r
-void Mutex::Acquire() throw(std::exception)\r
-{\r
- int rval=0;\r
- if((rval=pthread_mutex_lock(&m_mutex))!=0)\r
- {\r
- // deadlock - throw exception\r
- if(rval==EDEADLK)\r
- {\r
- throw DeadlockException();\r
- }\r
- }\r
-}\r
-\r
-void Mutex::Release()\r
-{\r
- pthread_mutex_unlock(&m_mutex);\r
-}\r
-\r
-} // namespace\r
+++ /dev/null
-#include "../../include/pthreadwrapper/runnable.h"\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-namespace PThread\r
-{\r
-\r
-const bool Runnable::IsCancelled()\r
-{\r
- if(m_thread)\r
- {\r
- return m_thread->IsCancelled();\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
-}\r
-\r
-void Runnable::Sleep(const long ms)\r
-{\r
- if(m_thread)\r
- {\r
- m_thread->Sleep(ms);\r
- }\r
-}\r
-\r
-} // namespace\r
+++ /dev/null
-#include "../../include/pthreadwrapper/thread.h"\r
-\r
-#include <sys/timeb.h>\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-namespace PThread\r
-{\r
-\r
-void Sleep(const long ms)\r
-{\r
- pthread_cond_t c;\r
- pthread_mutex_t m;\r
- timespec t;\r
- timeb tb;\r
-\r
- pthread_mutex_init(&m,NULL);\r
- pthread_cond_init(&c,NULL);\r
-\r
- ftime(&tb);\r
-\r
- t.tv_sec=tb.time+(ms/1000);\r
- t.tv_nsec=((1000000L)*(long)tb.millitm)+((1000000L)*(ms%1000));\r
-\r
- pthread_mutex_lock(&m);\r
- pthread_cond_timedwait(&c,&m,&t);\r
- pthread_mutex_unlock(&m);\r
-\r
- pthread_cond_destroy(&c);\r
- pthread_mutex_destroy(&m);\r
-}\r
-\r
-Thread::Thread()\r
-{\r
- m_running=false;\r
- m_cancelled=false;\r
- m_runnable=0;\r
- m_threadnum=0;\r
- m_threadcleaned=true;\r
-}\r
-\r
-Thread::Thread(Runnable *runnable)\r
-{\r
- m_running=false;\r
- m_cancelled=false;\r
- m_runnable=runnable;\r
- m_threadnum=0;\r
- m_threadcleaned=true;\r
- if(m_runnable)\r
- {\r
- m_runnable->m_thread=this;\r
- Start();\r
- }\r
-}\r
-\r
-Thread::~Thread()\r
-{\r
- Cancel();\r
- Join();\r
- if(m_threadcleaned==false)\r
- {\r
- pthread_detach(m_thread);\r
- }\r
- if(m_runnable)\r
- {\r
- delete m_runnable;\r
- }\r
-}\r
-\r
-void Thread::Cancel()\r
-{\r
- if(m_running)\r
- {\r
- m_cancelled=true;\r
- }\r
-}\r
-\r
-void *Thread::EntryPoint(void *pthis)\r
-{\r
- if(pthis)\r
- {\r
- ((Thread *)pthis)->m_runnable->Run();\r
- ((Thread *)pthis)->m_running=false;\r
- ((Thread *)pthis)->m_cancelled=false;\r
- }\r
- ((Thread *)pthis)->m_threadnum=0;\r
- return NULL;\r
-}\r
-\r
-void Thread::Join()\r
-{\r
- if(m_running)\r
- {\r
- pthread_join(m_thread,NULL);\r
- m_threadcleaned=true;\r
- }\r
-}\r
-\r
-void Thread::Sleep(const long ms)\r
-{\r
- if(m_running)\r
- {\r
- pthread_cond_t c;\r
- pthread_mutex_t m;\r
- timespec t;\r
- timeb tb;\r
-\r
- pthread_mutex_init(&m,NULL);\r
- pthread_cond_init(&c,NULL);\r
-\r
- ftime(&tb);\r
-\r
- t.tv_sec=tb.time+(ms/1000);\r
- t.tv_nsec=((1000000L)*(long)tb.millitm)+((1000000L)*(ms%1000));\r
-\r
- pthread_mutex_lock(&m);\r
- pthread_cond_timedwait(&c,&m,&t);\r
- pthread_mutex_unlock(&m);\r
-\r
- pthread_cond_destroy(&c);\r
- pthread_mutex_destroy(&m);\r
- }\r
-}\r
-\r
-void Thread::Start()\r
-{\r
- m_running=true;\r
- m_threadcleaned=false;\r
- m_threadnum=pthread_create(&m_thread,NULL,Thread::EntryPoint,this);\r
-}\r
-\r
-} // namespace\r
+++ /dev/null
-#include "../../include/pthreadwrapper/threadedexecutor.h"\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-namespace PThread\r
-{\r
-\r
-ThreadedExecutor::~ThreadedExecutor()\r
-{\r
- for(std::vector<Thread *>::iterator i=m_threads.begin(); i!=m_threads.end(); i++)\r
- {\r
- (*i)->Cancel();\r
- (*i)->Join();\r
- delete (*i);\r
- }\r
-}\r
-\r
-void ThreadedExecutor::Cancel()\r
-{\r
- for(std::vector<Thread *>::iterator i=m_threads.begin(); i!=m_threads.end(); i++)\r
- {\r
- (*i)->Cancel(); \r
- }\r
-}\r
-\r
-void ThreadedExecutor::CleanupFinished()\r
-{\r
- for(std::vector<Thread *>::iterator i=m_threads.begin(); i!=m_threads.end(); )\r
- {\r
- if((*i)->IsRunning()==false)\r
- {\r
- delete (*i);\r
- i=m_threads.erase(i);\r
- }\r
- else\r
- {\r
- i++;\r
- }\r
- }\r
-}\r
-\r
-void ThreadedExecutor::Execute(Runnable *runnable)\r
-{\r
- CleanupFinished();\r
- m_threads.push_back(new Thread(runnable)); \r
-}\r
-\r
-void ThreadedExecutor::Join()\r
-{\r
- for(std::vector<Thread *>::iterator i=m_threads.begin(); i!=m_threads.end(); i++)\r
- {\r
- (*i)->Join();\r
- }\r
- CleanupFinished();\r
-}\r
-\r
-} // namespace\r
+++ /dev/null
-#include "../include/threadcontroller.h"\r
-#include "../include/option.h"\r
-#include "../include/freenet/freenetmasterthread.h"\r
-#include "../include/nntp/nntplistener.h"\r
-#include "../include/http/httpthread.h"\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-ThreadController::~ThreadController()\r
-{\r
- ShutdownThreads();\r
-}\r
-\r
-void ThreadController::ReadConfig()\r
-{\r
-\r
- std::string tempval="";\r
- Option::Instance()->Get("StartFreenetUpdater",tempval);\r
- if(tempval=="true")\r
- {\r
- m_startfreenet=true;\r
- }\r
- else\r
- {\r
- m_startfreenet=false;\r
- }\r
-\r
- tempval="";\r
- Option::Instance()->Get("StartNNTP",tempval);\r
- if(tempval=="true")\r
- {\r
- m_startnntp=true;\r
- }\r
- else\r
- {\r
- m_startnntp=false;\r
- }\r
-\r
- tempval="";\r
- Option::Instance()->Get("StartHTTP",tempval);\r
- if(tempval=="true")\r
- {\r
- m_starthttp=true;\r
- }\r
- else\r
- {\r
- m_starthttp=false;\r
- }\r
-\r
-}\r
-\r
-void ThreadController::RestartThreads()\r
-{\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"ThreadController::RestartThreads restarting threads.");\r
- ShutdownThreads();\r
- StartThreads();\r
-}\r
-\r
-void ThreadController::ShutdownFreenetThread()\r
-{\r
- if(m_freenetthread)\r
- {\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"ThreadController::ShutdownFreenetThread shutting down Freenet thread.");\r
- m_freenetthread->Cancel();\r
- m_freenetthread->Join();\r
- delete m_freenetthread;\r
- m_freenetthread=NULL;\r
- }\r
-}\r
-\r
-void ThreadController::ShutdownHTTPThread()\r
-{\r
- if(m_httpthread)\r
- {\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"ThreadController::ShutdownHTTPThread shutting down HTTP thread.");\r
- m_httpthread->Cancel();\r
- m_httpthread->Join();\r
- delete m_httpthread;\r
- m_httpthread=NULL;\r
- }\r
-}\r
-\r
-void ThreadController::ShutdownNNTPThread()\r
-{\r
- if(m_nntpthread)\r
- {\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"ThreadController::ShutdownNNTPThread shutting down NNTP thread.");\r
- m_nntpthread->Cancel();\r
- m_nntpthread->Join();\r
- delete m_nntpthread;\r
- m_nntpthread=NULL;\r
- }\r
-}\r
-\r
-void ThreadController::ShutdownThreads()\r
-{\r
- ShutdownFreenetThread();\r
- ShutdownNNTPThread();\r
- ShutdownHTTPThread();\r
-}\r
-\r
-void ThreadController::StartFreenetThread()\r
-{\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"ThreadController::StartFreenetThread starting Freenet thread.");\r
- m_freenetthread=new PThread::Thread(new FreenetMasterThread());\r
-}\r
-\r
-void ThreadController::StartHTTPThread()\r
-{\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"ThreadController::StartHTTPThread starting HTTP thread.");\r
- m_httpthread=new PThread::Thread(new HTTPThread());\r
-}\r
-\r
-void ThreadController::StartNNTPThread()\r
-{\r
- m_log->WriteLog(LogFile::LOGLEVEL_INFO,"ThreadController::StartNNTPThread starting NNTP thread.");\r
- m_nntpthread=new PThread::Thread(new NNTPListener());\r
-}\r
-\r
-void ThreadController::StartThreads()\r
-{\r
- ReadConfig();\r
-\r
- if(m_startfreenet)\r
- {\r
- StartFreenetThread();\r
- }\r
- if(m_startnntp)\r
- {\r
- StartNNTPThread();\r
- }\r
- if(m_starthttp)\r
- {\r
- StartHTTPThread();\r
- }\r
-}\r
-\r
--- /dev/null
+#include "../../include/threadwrapper/threadedexecutor.h"\r
+\r
+ThreadedExecutor::~ThreadedExecutor()\r
+{\r
+ for(std::vector<CancelableThread *>::iterator i=m_threads.begin(); i!=m_threads.end(); i++)\r
+ {\r
+ (*i)->Cancel();\r
+ (*i)->join();\r
+ delete (*i);\r
+ }\r
+}\r
+\r
+void ThreadedExecutor::Cancel()\r
+{\r
+ for(std::vector<CancelableThread *>::iterator i=m_threads.begin(); i!=m_threads.end(); i++)\r
+ {\r
+ if((*i)->isRunning())\r
+ {\r
+ (*i)->Cancel();\r
+ }\r
+ }\r
+}\r
+\r
+void ThreadedExecutor::CleanupCompleted()\r
+{\r
+ for(std::vector<CancelableThread *>::iterator i=m_threads.begin(); i!=m_threads.end(); )\r
+ {\r
+ if((*i)->isRunning()==false)\r
+ {\r
+ delete (*i);\r
+ i=m_threads.erase(i);\r
+ }\r
+ else\r
+ {\r
+ i++;\r
+ }\r
+ }\r
+}\r
+\r
+void ThreadedExecutor::Join()\r
+{\r
+ for(std::vector<CancelableThread *>::iterator i=m_threads.begin(); i!=m_threads.end(); i++)\r
+ {\r
+ (*i)->join();\r
+ }\r
+ CleanupCompleted();\r
+}\r
+\r
+void ThreadedExecutor::Start(CancelableRunnable *runnable)\r
+{\r
+ m_threads.push_back(new CancelableThread(runnable));\r
+ CleanupCompleted();\r
+}\r
+++ /dev/null
-#include "../include/uuidgenerator.h"\r
-\r
-#include <cstdlib>\r
-\r
-#ifdef XMEM\r
- #include <xmem.h>\r
-#endif\r
-\r
-const std::string UUIDGenerator::Generate()\r
-{\r
-\r
- return RandHex(8)+"-"+RandHex(4)+"-4"+RandHex(3)+"-"+RandHex(4)+"-"+RandHex(12);\r
-\r
-}\r
-\r
-const std::string UUIDGenerator::RandHex(const int len)\r
-{\r
- static std::string hexchars="0123456789ABCDEF";\r
- std::string rval="";\r
- for(int i=0; i<len; i++)\r
- {\r
- rval+=hexchars[rand()%hexchars.size()];\r
- }\r
- return rval;\r
-}\r
+++ /dev/null
-/*\r
- * FIPS-180-1 compliant SHA-1 implementation\r
- *\r
- * Copyright (C) 2006-2007 Christophe Devine\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License, version 2.1 as published by the Free Software Foundation.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,\r
- * MA 02110-1301 USA\r
- */\r
-/*\r
- * The SHA-1 standard was published by NIST in 1993.\r
- *\r
- * http://www.itl.nist.gov/fipspubs/fip180-1.htm\r
- */\r
-\r
-#include "../../include/xyssl/config.h"\r
-\r
-#if defined(XYSSL_SHA1_C)\r
-\r
-#include "../../include/xyssl/sha1.h"\r
-\r
-#include <string.h>\r
-#include <stdio.h>\r
-\r
-/*\r
- * 32-bit integer manipulation macros (big endian)\r
- */\r
-#ifndef GET_ULONG_BE\r
-#define GET_ULONG_BE(n,b,i) \\r
-{ \\r
- (n) = ( (unsigned long) (b)[(i) ] << 24 ) \\r
- | ( (unsigned long) (b)[(i) + 1] << 16 ) \\r
- | ( (unsigned long) (b)[(i) + 2] << 8 ) \\r
- | ( (unsigned long) (b)[(i) + 3] ); \\r
-}\r
-#endif\r
-\r
-#ifndef PUT_ULONG_BE\r
-#define PUT_ULONG_BE(n,b,i) \\r
-{ \\r
- (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \\r
- (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \\r
- (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \\r
- (b)[(i) + 3] = (unsigned char) ( (n) ); \\r
-}\r
-#endif\r
-\r
-/*\r
- * SHA-1 context setup\r
- */\r
-void sha1_starts( sha1_context *ctx )\r
-{\r
- ctx->total[0] = 0;\r
- ctx->total[1] = 0;\r
-\r
- ctx->state[0] = 0x67452301;\r
- ctx->state[1] = 0xEFCDAB89;\r
- ctx->state[2] = 0x98BADCFE;\r
- ctx->state[3] = 0x10325476;\r
- ctx->state[4] = 0xC3D2E1F0;\r
-}\r
-\r
-static void sha1_process( sha1_context *ctx, unsigned char data[64] )\r
-{\r
- unsigned long temp, W[16], A, B, C, D, E;\r
-\r
- GET_ULONG_BE( W[ 0], data, 0 );\r
- GET_ULONG_BE( W[ 1], data, 4 );\r
- GET_ULONG_BE( W[ 2], data, 8 );\r
- GET_ULONG_BE( W[ 3], data, 12 );\r
- GET_ULONG_BE( W[ 4], data, 16 );\r
- GET_ULONG_BE( W[ 5], data, 20 );\r
- GET_ULONG_BE( W[ 6], data, 24 );\r
- GET_ULONG_BE( W[ 7], data, 28 );\r
- GET_ULONG_BE( W[ 8], data, 32 );\r
- GET_ULONG_BE( W[ 9], data, 36 );\r
- GET_ULONG_BE( W[10], data, 40 );\r
- GET_ULONG_BE( W[11], data, 44 );\r
- GET_ULONG_BE( W[12], data, 48 );\r
- GET_ULONG_BE( W[13], data, 52 );\r
- GET_ULONG_BE( W[14], data, 56 );\r
- GET_ULONG_BE( W[15], data, 60 );\r
-\r
-#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))\r
-\r
-#define R(t) \\r
-( \\r
- temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \\r
- W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \\r
- ( W[t & 0x0F] = S(temp,1) ) \\r
-)\r
-\r
-#define P(a,b,c,d,e,x) \\r
-{ \\r
- e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \\r
-}\r
-\r
- A = ctx->state[0];\r
- B = ctx->state[1];\r
- C = ctx->state[2];\r
- D = ctx->state[3];\r
- E = ctx->state[4];\r
-\r
-#define F(x,y,z) (z ^ (x & (y ^ z)))\r
-#define K 0x5A827999\r
-\r
- P( A, B, C, D, E, W[0] );\r
- P( E, A, B, C, D, W[1] );\r
- P( D, E, A, B, C, W[2] );\r
- P( C, D, E, A, B, W[3] );\r
- P( B, C, D, E, A, W[4] );\r
- P( A, B, C, D, E, W[5] );\r
- P( E, A, B, C, D, W[6] );\r
- P( D, E, A, B, C, W[7] );\r
- P( C, D, E, A, B, W[8] );\r
- P( B, C, D, E, A, W[9] );\r
- P( A, B, C, D, E, W[10] );\r
- P( E, A, B, C, D, W[11] );\r
- P( D, E, A, B, C, W[12] );\r
- P( C, D, E, A, B, W[13] );\r
- P( B, C, D, E, A, W[14] );\r
- P( A, B, C, D, E, W[15] );\r
- P( E, A, B, C, D, R(16) );\r
- P( D, E, A, B, C, R(17) );\r
- P( C, D, E, A, B, R(18) );\r
- P( B, C, D, E, A, R(19) );\r
-\r
-#undef K\r
-#undef F\r
-\r
-#define F(x,y,z) (x ^ y ^ z)\r
-#define K 0x6ED9EBA1\r
-\r
- P( A, B, C, D, E, R(20) );\r
- P( E, A, B, C, D, R(21) );\r
- P( D, E, A, B, C, R(22) );\r
- P( C, D, E, A, B, R(23) );\r
- P( B, C, D, E, A, R(24) );\r
- P( A, B, C, D, E, R(25) );\r
- P( E, A, B, C, D, R(26) );\r
- P( D, E, A, B, C, R(27) );\r
- P( C, D, E, A, B, R(28) );\r
- P( B, C, D, E, A, R(29) );\r
- P( A, B, C, D, E, R(30) );\r
- P( E, A, B, C, D, R(31) );\r
- P( D, E, A, B, C, R(32) );\r
- P( C, D, E, A, B, R(33) );\r
- P( B, C, D, E, A, R(34) );\r
- P( A, B, C, D, E, R(35) );\r
- P( E, A, B, C, D, R(36) );\r
- P( D, E, A, B, C, R(37) );\r
- P( C, D, E, A, B, R(38) );\r
- P( B, C, D, E, A, R(39) );\r
-\r
-#undef K\r
-#undef F\r
-\r
-#define F(x,y,z) ((x & y) | (z & (x | y)))\r
-#define K 0x8F1BBCDC\r
-\r
- P( A, B, C, D, E, R(40) );\r
- P( E, A, B, C, D, R(41) );\r
- P( D, E, A, B, C, R(42) );\r
- P( C, D, E, A, B, R(43) );\r
- P( B, C, D, E, A, R(44) );\r
- P( A, B, C, D, E, R(45) );\r
- P( E, A, B, C, D, R(46) );\r
- P( D, E, A, B, C, R(47) );\r
- P( C, D, E, A, B, R(48) );\r
- P( B, C, D, E, A, R(49) );\r
- P( A, B, C, D, E, R(50) );\r
- P( E, A, B, C, D, R(51) );\r
- P( D, E, A, B, C, R(52) );\r
- P( C, D, E, A, B, R(53) );\r
- P( B, C, D, E, A, R(54) );\r
- P( A, B, C, D, E, R(55) );\r
- P( E, A, B, C, D, R(56) );\r
- P( D, E, A, B, C, R(57) );\r
- P( C, D, E, A, B, R(58) );\r
- P( B, C, D, E, A, R(59) );\r
-\r
-#undef K\r
-#undef F\r
-\r
-#define F(x,y,z) (x ^ y ^ z)\r
-#define K 0xCA62C1D6\r
-\r
- P( A, B, C, D, E, R(60) );\r
- P( E, A, B, C, D, R(61) );\r
- P( D, E, A, B, C, R(62) );\r
- P( C, D, E, A, B, R(63) );\r
- P( B, C, D, E, A, R(64) );\r
- P( A, B, C, D, E, R(65) );\r
- P( E, A, B, C, D, R(66) );\r
- P( D, E, A, B, C, R(67) );\r
- P( C, D, E, A, B, R(68) );\r
- P( B, C, D, E, A, R(69) );\r
- P( A, B, C, D, E, R(70) );\r
- P( E, A, B, C, D, R(71) );\r
- P( D, E, A, B, C, R(72) );\r
- P( C, D, E, A, B, R(73) );\r
- P( B, C, D, E, A, R(74) );\r
- P( A, B, C, D, E, R(75) );\r
- P( E, A, B, C, D, R(76) );\r
- P( D, E, A, B, C, R(77) );\r
- P( C, D, E, A, B, R(78) );\r
- P( B, C, D, E, A, R(79) );\r
-\r
-#undef K\r
-#undef F\r
-\r
- ctx->state[0] += A;\r
- ctx->state[1] += B;\r
- ctx->state[2] += C;\r
- ctx->state[3] += D;\r
- ctx->state[4] += E;\r
-}\r
-\r
-/*\r
- * SHA-1 process buffer\r
- */\r
-void sha1_update( sha1_context *ctx, unsigned char *input, int ilen )\r
-{\r
- int fill;\r
- unsigned long left;\r
-\r
- if( ilen <= 0 )\r
- return;\r
-\r
- left = ctx->total[0] & 0x3F;\r
- fill = 64 - left;\r
-\r
- ctx->total[0] += ilen;\r
- ctx->total[0] &= 0xFFFFFFFF;\r
-\r
- if( ctx->total[0] < (unsigned long) ilen )\r
- ctx->total[1]++;\r
-\r
- if( left && ilen >= fill )\r
- {\r
- memcpy( (void *) (ctx->buffer + left),\r
- (void *) input, fill );\r
- sha1_process( ctx, ctx->buffer );\r
- input += fill;\r
- ilen -= fill;\r
- left = 0;\r
- }\r
-\r
- while( ilen >= 64 )\r
- {\r
- sha1_process( ctx, input );\r
- input += 64;\r
- ilen -= 64;\r
- }\r
-\r
- if( ilen > 0 )\r
- {\r
- memcpy( (void *) (ctx->buffer + left),\r
- (void *) input, ilen );\r
- }\r
-}\r
-\r
-static const unsigned char sha1_padding[64] =\r
-{\r
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
-};\r
-\r
-/*\r
- * SHA-1 final digest\r
- */\r
-void sha1_finish( sha1_context *ctx, unsigned char output[20] )\r
-{\r
- unsigned long last, padn;\r
- unsigned long high, low;\r
- unsigned char msglen[8];\r
-\r
- high = ( ctx->total[0] >> 29 )\r
- | ( ctx->total[1] << 3 );\r
- low = ( ctx->total[0] << 3 );\r
-\r
- PUT_ULONG_BE( high, msglen, 0 );\r
- PUT_ULONG_BE( low, msglen, 4 );\r
-\r
- last = ctx->total[0] & 0x3F;\r
- padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );\r
-\r
- sha1_update( ctx, (unsigned char *) sha1_padding, padn );\r
- sha1_update( ctx, msglen, 8 );\r
-\r
- PUT_ULONG_BE( ctx->state[0], output, 0 );\r
- PUT_ULONG_BE( ctx->state[1], output, 4 );\r
- PUT_ULONG_BE( ctx->state[2], output, 8 );\r
- PUT_ULONG_BE( ctx->state[3], output, 12 );\r
- PUT_ULONG_BE( ctx->state[4], output, 16 );\r
-}\r
-\r
-/*\r
- * output = SHA-1( input buffer )\r
- */\r
-void sha1( unsigned char *input, int ilen, unsigned char output[20] )\r
-{\r
- sha1_context ctx;\r
-\r
- sha1_starts( &ctx );\r
- sha1_update( &ctx, input, ilen );\r
- sha1_finish( &ctx, output );\r
-\r
- memset( &ctx, 0, sizeof( sha1_context ) );\r
-}\r
-\r
-/*\r
- * output = SHA-1( file contents )\r
- */\r
-int sha1_file( char *path, unsigned char output[20] )\r
-{\r
- FILE *f;\r
- size_t n;\r
- sha1_context ctx;\r
- unsigned char buf[1024];\r
-\r
- if( ( f = fopen( path, "rb" ) ) == NULL )\r
- return( 1 );\r
-\r
- sha1_starts( &ctx );\r
-\r
- while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )\r
- sha1_update( &ctx, buf, (int) n );\r
-\r
- sha1_finish( &ctx, output );\r
-\r
- memset( &ctx, 0, sizeof( sha1_context ) );\r
-\r
- if( ferror( f ) != 0 )\r
- {\r
- fclose( f );\r
- return( 2 );\r
- }\r
-\r
- fclose( f );\r
- return( 0 );\r
-}\r
-\r
-/*\r
- * SHA-1 HMAC context setup\r
- */\r
-void sha1_hmac_starts( sha1_context *ctx, unsigned char *key, int keylen )\r
-{\r
- int i;\r
- unsigned char sum[20];\r
-\r
- if( keylen > 64 )\r
- {\r
- sha1( key, keylen, sum );\r
- keylen = 20;\r
- key = sum;\r
- }\r
-\r
- memset( ctx->ipad, 0x36, 64 );\r
- memset( ctx->opad, 0x5C, 64 );\r
-\r
- for( i = 0; i < keylen; i++ )\r
- {\r
- ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );\r
- ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );\r
- }\r
-\r
- sha1_starts( ctx );\r
- sha1_update( ctx, ctx->ipad, 64 );\r
-\r
- memset( sum, 0, sizeof( sum ) );\r
-}\r
-\r
-/*\r
- * SHA-1 HMAC process buffer\r
- */\r
-void sha1_hmac_update( sha1_context *ctx, unsigned char *input, int ilen )\r
-{\r
- sha1_update( ctx, input, ilen );\r
-}\r
-\r
-/*\r
- * SHA-1 HMAC final digest\r
- */\r
-void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )\r
-{\r
- unsigned char tmpbuf[20];\r
-\r
- sha1_finish( ctx, tmpbuf );\r
- sha1_starts( ctx );\r
- sha1_update( ctx, ctx->opad, 64 );\r
- sha1_update( ctx, tmpbuf, 20 );\r
- sha1_finish( ctx, output );\r
-\r
- memset( tmpbuf, 0, sizeof( tmpbuf ) );\r
-}\r
-\r
-/*\r
- * output = HMAC-SHA-1( hmac key, input buffer )\r
- */\r
-void sha1_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,\r
- unsigned char output[20] )\r
-{\r
- sha1_context ctx;\r
-\r
- sha1_hmac_starts( &ctx, key, keylen );\r
- sha1_hmac_update( &ctx, input, ilen );\r
- sha1_hmac_finish( &ctx, output );\r
-\r
- memset( &ctx, 0, sizeof( sha1_context ) );\r
-}\r
-\r
-#if defined(XYSSL_SELF_TEST)\r
-\r
-/*\r
- * FIPS-180-1 test vectors\r
- */\r
-static const char sha1_test_str[3][57] = \r
-{\r
- { "abc" },\r
- { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },\r
- { "" }\r
-};\r
-\r
-static const unsigned char sha1_test_sum[3][20] =\r
-{\r
- { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,\r
- 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },\r
- { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,\r
- 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },\r
- { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,\r
- 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }\r
-};\r
-\r
-/*\r
- * Checkup routine\r
- */\r
-int sha1_self_test( int verbose )\r
-{\r
- int i, j;\r
- unsigned char buf[1000];\r
- unsigned char sha1sum[20];\r
- sha1_context ctx;\r
-\r
- for( i = 0; i < 3; i++ )\r
- {\r
- if( verbose != 0 )\r
- printf( " SHA-1 test #%d: ", i + 1 );\r
-\r
- sha1_starts( &ctx );\r
-\r
- if( i < 2 )\r
- sha1_update( &ctx, (unsigned char *) sha1_test_str[i],\r
- strlen( sha1_test_str[i] ) );\r
- else\r
- {\r
- memset( buf, 'a', 1000 );\r
- for( j = 0; j < 1000; j++ )\r
- sha1_update( &ctx, buf, 1000 );\r
- }\r
-\r
- sha1_finish( &ctx, sha1sum );\r
-\r
- if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )\r
- {\r
- if( verbose != 0 )\r
- printf( "failed\n" );\r
-\r
- return( 1 );\r
- }\r
-\r
- if( verbose != 0 )\r
- printf( "passed\n" );\r
- }\r
-\r
- if( verbose != 0 )\r
- printf( "\n" );\r
-\r
- return( 0 );\r
-}\r
-\r
-#endif\r
-\r
-#endif\r