version 0.1.10
authorSomeDude <SomeDude@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw>
Fri, 8 Feb 2008 16:41:00 +0000 (17:41 +0100)
committerDavid ‘Bombe’ Roden <bombe@freenetproject.org>
Fri, 8 Feb 2008 16:41:00 +0000 (17:41 +0100)
33 files changed:
CMakeLists.txt
include/fmsdaemon.h [new file with mode: 0644]
include/fmsservice.h [new file with mode: 0644]
include/freenet/messagerequester.h
include/global.h
include/http/identityexportxml.h [new file with mode: 0644]
include/http/ipagehandler.h
include/http/pages/peerdetailspage.h [new file with mode: 0644]
include/pthreadwrapper/thread.h
include/threadcontroller.h
src/db/sqlite3statement.cpp
src/fmsdaemon.cpp [new file with mode: 0644]
src/fmsservice.cpp [new file with mode: 0644]
src/freenet/introductionpuzzleinserter.cpp
src/freenet/introductionpuzzlerequester.cpp
src/freenet/messagerequester.cpp
src/freenet/periodicdbmaintenance.cpp
src/freenet/trustlistxml.cpp
src/global.cpp
src/http/httpthread.cpp
src/http/identityexportxml.cpp [new file with mode: 0644]
src/http/ipagehandler.cpp
src/http/pages/announceidentitypage.cpp
src/http/pages/homepage.cpp
src/http/pages/localidentitiespage.cpp
src/http/pages/peerdetailspage.cpp [new file with mode: 0644]
src/http/pages/peertrustpage.cpp
src/http/pages/showcaptchapage.cpp
src/main.cpp
src/message.cpp
src/nntp/mime/Mime.cpp
src/pthreadwrapper/thread.cpp
src/threadcontroller.cpp

index 3135915..024be6a 100644 (file)
@@ -48,6 +48,7 @@ src/freenet/captcha/easybmp/EasyBMP.cpp
 src/freenet/captcha/easybmp/EasyBMP_Font.cpp\r
 src/freenet/captcha/easybmp/EasyBMP_Geometry.cpp\r
 src/http/httpthread.cpp\r
+src/http/identityexportxml.cpp\r
 src/http/ipagehandler.cpp\r
 src/http/pages/addpeerpage.cpp\r
 src/http/pages/announceidentitypage.cpp\r
@@ -56,6 +57,7 @@ src/http/pages/createidentitypage.cpp
 src/http/pages/homepage.cpp\r
 src/http/pages/localidentitiespage.cpp\r
 src/http/pages/optionspage.cpp\r
+src/http/pages/peerdetailspage.cpp\r
 src/http/pages/peertrustpage.cpp\r
 src/http/pages/showcaptchapage.cpp\r
 src/nntp/nntpconnection.cpp\r
@@ -73,6 +75,12 @@ src/pthreadwrapper/threadedexecutor.cpp
 src/xyssl/sha1.c\r
 )\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
 ADD_DEFINITIONS(-DTIXML_USE_STL)\r
 \r
 # was for ZThreads\r
@@ -81,7 +89,7 @@ ADD_DEFINITIONS(-DTIXML_USE_STL)
 #      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")\r
 #ENDIF(CMAKE_COMPILER_IS_GNUCXX)\r
 \r
-ADD_EXECUTABLE(fms ${FMS_SRC})\r
+ADD_EXECUTABLE(fms ${FMS_SRC} ${FMS_PLATFORM_SRC})\r
 \r
 # For SQLite3 and shttpd\r
 IF(CMAKE_COMPILER_IS_GNUCC)\r
diff --git a/include/fmsdaemon.h b/include/fmsdaemon.h
new file mode 100644 (file)
index 0000000..50ff86c
--- /dev/null
@@ -0,0 +1,9 @@
+#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
diff --git a/include/fmsservice.h b/include/fmsservice.h
new file mode 100644 (file)
index 0000000..5a08fbb
--- /dev/null
@@ -0,0 +1,22 @@
+#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
index d40710f..c4cdb92 100644 (file)
@@ -20,6 +20,7 @@ private:
        const std::string GetIdentityName(const long identityid);\r
 \r
        long m_maxdaysbackward;\r
+       long m_maxpeermessages;\r
        \r
 };\r
 \r
index ba827c4..cb75d5a 100644 (file)
@@ -5,21 +5,29 @@
 //#include <zthread/Thread.h>\r
 #include "pthreadwrapper/thread.h"\r
 \r
-#define FMS_VERSION    "0.1.9"\r
+#define FMS_VERSION    "0.1.10"\r
 \r
 // opens database and creates tables and initial inserts if necessary\r
 void SetupDB();\r
+void ConvertDB0100To0101();\r
 // inserts default options into the database\r
 void SetupDefaultOptions();\r
 // opens logfile and sets it up\r
 void SetupLogFile();\r
 \r
-void StartThreads(std::vector<PThread::Thread *> &threads);\r
-void ShutdownThreads(std::vector<PThread::Thread *> &threads);\r
+void SigHandler(int signum);\r
+\r
+void MainFunction();\r
+void Shutdown();\r
+\r
+//void StartThreads(std::vector<PThread::Thread *> &threads);\r
+//void ShutdownThreads(std::vector<PThread::Thread *> &threads);\r
 \r
 // needed for Windows to setup network\r
 void SetupNetwork();\r
 // cleanup network on Windows\r
 void ShutdownNetwork();\r
 \r
+extern bool wantshutdown;\r
+\r
 #endif // _global_\r
diff --git a/include/http/identityexportxml.h b/include/http/identityexportxml.h
new file mode 100644 (file)
index 0000000..6d6db3a
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _identityexportxml_\r
+#define _identityexportxml_\r
+\r
+#include "../ifmsxmldocument.h"\r
+\r
+class IdentityExportXML:public IFMSXMLDocument\r
+{\r
+public:\r
+       IdentityExportXML();\r
+\r
+       std::string GetXML();\r
+       const bool ParseXML(const std::string &xml);\r
+\r
+       void AddIdentity(const std::string &name, const std::string &publickey, const std::string &privatekey, const bool singleuse=false, const bool publishtrustlist=false, const bool publishboardlist=false);\r
+\r
+       const long GetCount()           { return m_identities.size(); }\r
+\r
+       const std::string GetName(const long index);\r
+       const std::string GetPublicKey(const long index);\r
+       const std::string GetPrivateKey(const long index);\r
+       const bool GetSingleUse(const long index);\r
+       const bool GetPublishTrustList(const long index);\r
+       const bool GetPublishBoardList(const long index);\r
+\r
+private:\r
+       void Initialize();\r
+\r
+       struct identity\r
+       {\r
+               identity(const std::string &name, const std::string &publickey, const std::string &privatekey, const bool singleuse, const bool publishtrustlist, const bool publishboardlist):m_name(name),m_publickey(publickey),m_privatekey(privatekey),m_singleuse(singleuse),m_publishtrustlist(publishtrustlist),m_publishboardlist(publishboardlist)    {}\r
+               std::string m_name;\r
+               std::string m_publickey;\r
+               std::string m_privatekey;\r
+               bool m_singleuse;\r
+               bool m_publishtrustlist;\r
+               bool m_publishboardlist;\r
+       };\r
+\r
+       std::vector<identity> m_identities;\r
+\r
+};\r
+\r
+#endif // _identityexportxml_\r
index be707e5..6cd3052 100644 (file)
@@ -26,6 +26,8 @@ private:
        virtual const std::string GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)=0;\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
 \r
diff --git a/include/http/pages/peerdetailspage.h b/include/http/pages/peerdetailspage.h
new file mode 100644 (file)
index 0000000..5a2b79f
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _peerdetailspage_\r
+#define _peerdetailspage_\r
+\r
+#include "../ipagehandler.h"\r
+#include "../../idatabase.h"\r
+\r
+class PeerDetailsPage:public IPageHandler,public IDatabase\r
+{\r
+public:\r
+       PeerDetailsPage(const std::string templatestr):IPageHandler(templatestr)        {}\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
+       const std::string GetClassString(const std::string &trustlevel);\r
+\r
+};\r
+\r
+#endif // _peerdetailspage_\r
index c1db10a..6e51f73 100644 (file)
@@ -8,6 +8,8 @@
 namespace PThread\r
 {\r
 \r
+void Sleep(const long ms);\r
+\r
 class Runnable;\r
 \r
 class Thread:public NonCopyable\r
index d1190c8..47cb63a 100644 (file)
@@ -1,10 +1,11 @@
 #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>\r
+class ThreadController:public PThread::Singleton<ThreadController>,public ILogger\r
 {\r
 public:\r
        ThreadController():m_freenetthread(NULL),m_httpthread(NULL),m_nntpthread(NULL)          {}\r
index 683e771..81df27a 100644 (file)
@@ -65,7 +65,7 @@ const bool Statement::Bind(const int column)
        if(Valid() && column>=0 && column<m_parametercount)\r
        {\r
                //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
-               PThread::Guard g(DB::Instance()->m_mutex);\r
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                if(sqlite3_bind_null(m_statement,column+1)==SQLITE_OK)\r
                {\r
                        return true;\r
@@ -86,7 +86,7 @@ const bool Statement::Bind(const int column, const int value)
        if(Valid() && column>=0 && column<m_parametercount)\r
        {\r
                //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
-               PThread::Guard g(DB::Instance()->m_mutex);\r
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                if(sqlite3_bind_int(m_statement,column+1,value)==SQLITE_OK)\r
                {\r
                        return true;\r
@@ -107,7 +107,7 @@ const bool Statement::Bind(const int column, const double value)
        if(Valid() && column>=0 && column<m_parametercount)\r
        {\r
                //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
-               PThread::Guard g(DB::Instance()->m_mutex);\r
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                if(sqlite3_bind_double(m_statement,column+1,value)==SQLITE_OK)\r
                {\r
                        return true;\r
@@ -127,16 +127,8 @@ const bool Statement::Bind(const int column, const std::string &value)
 {\r
        if(Valid() && column>=0 && column<m_parametercount)\r
        {\r
-               //char *text=new char[value.size()+1];\r
-               //strncpy(text,value.c_str(),value.size());\r
-               //text[value.size()]=NULL;\r
-               //textptrs.push_back(text);\r
-               \r
                //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
-               PThread::Guard g(DB::Instance()->m_mutex);\r
-               //m_boundtext.push_back(std::vector<char>(value.begin(),value.end()));\r
-               //if(sqlite3_bind_text(m_statement,column+1,text,value.size(),NULL)==SQLITE_OK)\r
-               //if(sqlite3_bind_text(m_statement,column+1,&(m_boundtext[m_boundtext.size()-1][0]),(m_boundtext[m_boundtext.size()-1]).size(),NULL)==SQLITE_OK)                \r
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                if(sqlite3_bind_text(m_statement,column+1,value.c_str(),value.size(),SQLITE_TRANSIENT)==SQLITE_OK)\r
                {\r
                        return true;\r
@@ -157,7 +149,7 @@ const bool Statement::Bind(const int column, const void *data, const int length)
        if(Valid() && column>=0 && column<m_parametercount)\r
        {\r
                //ZThread::Guard<ZThread::Mutex> g(DB::instance()->m_mutex);\r
-               PThread::Guard g(DB::Instance()->m_mutex);\r
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                if(sqlite3_bind_blob(m_statement,column+1,data,length,SQLITE_TRANSIENT)==SQLITE_OK)\r
                {\r
                        return true;\r
@@ -236,7 +228,7 @@ const bool Statement::ResultBlob(const int column, void *data, int &length)
        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
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                data=(void *)sqlite3_column_blob(m_statement,column);\r
                length=sqlite3_column_bytes(m_statement,column);\r
                return true;\r
@@ -252,7 +244,7 @@ const bool Statement::ResultDouble(const int column, double &result)
        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
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                result=sqlite3_column_double(m_statement,column);\r
                return true;\r
        }\r
@@ -267,7 +259,7 @@ const bool Statement::ResultInt(const int column, int &result)
        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
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                result=sqlite3_column_int(m_statement,column);\r
                return true;\r
        }\r
@@ -282,7 +274,7 @@ const bool Statement::ResultNull(const int column)
        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
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                if(sqlite3_column_type(m_statement,column)==SQLITE_NULL)\r
                {\r
                        return true;\r
@@ -303,7 +295,7 @@ const bool Statement::ResultText(const int column, std::string &result)
        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
+               //PThread::Guard g(DB::Instance()->m_mutex);\r
                const unsigned char *cresult=sqlite3_column_text(m_statement,column);\r
                if(cresult)\r
                {\r
diff --git a/src/fmsdaemon.cpp b/src/fmsdaemon.cpp
new file mode 100644 (file)
index 0000000..0086a02
--- /dev/null
@@ -0,0 +1,52 @@
+#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
diff --git a/src/fmsservice.cpp b/src/fmsservice.cpp
new file mode 100644 (file)
index 0000000..e24a53f
--- /dev/null
@@ -0,0 +1,222 @@
+#include "../include/fmsservice.h"\r
+#include "../include/global.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
+                       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
+       MainFunction();\r
+\r
+       ServiceStatus.dwCurrentState=SERVICE_STOPPED;\r
+       SetServiceStatus(hStatus,&ServiceStatus);\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
index 1b5b64f..fef42f1 100644 (file)
@@ -230,7 +230,7 @@ void IntroductionPuzzleInserter::StartInsert(const long localidentityid)
        xml.SetType("captcha");\r
        xml.SetUUID(uuid.Generate());\r
        xml.SetPuzzleData(encodedpuzzle);\r
-       xml.SetMimeType("bitmap/image");\r
+       xml.SetMimeType("image/bmp");\r
 \r
        xmldata=xml.GetXML();\r
        StringFunctions::Convert(xmldata.size(),xmldatasizestr);\r
index 4f85e7a..830bdb3 100644 (file)
@@ -202,7 +202,7 @@ void IntroductionPuzzleRequester::PopulateIDList()
        now.SetToGMTime();\r
 \r
        // select identities that aren't single use and have been seen today ( order by trust DESC and limit to limitnum )\r
-       st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE PublicKey IS NOT NULL AND PublicKey <> '' AND SingleUse='false' AND LastSeen>='"+now.Format("%Y-%m-%d")+"' ORDER BY LocalMessageTrust LIMIT 0,"+limitnum+";");\r
+       st=m_db->Prepare("SELECT IdentityID FROM tblIdentity WHERE 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.Step();\r
 \r
        m_ids.clear();\r
index 980e688..d58494b 100644 (file)
@@ -167,7 +167,7 @@ const bool MessageRequester::HandleAllData(FCPMessage &message)
                }\r
                else    // couldn't insert - was already in database\r
                {\r
-                       m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAddData could not insert message into database.  "+message["Identifier"]);\r
+                       //m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"MessageRequester::HandleAddData could not insert message into database.  "+message["Identifier"]);\r
                }\r
 \r
        }\r
@@ -241,6 +241,17 @@ void MessageRequester::Initialize()
        {\r
                m_log->WriteLog(LogFile::LOGLEVEL_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
+       }\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
+       }\r
 }\r
 \r
 void MessageRequester::PopulateIDList()\r
@@ -250,6 +261,7 @@ void MessageRequester::PopulateIDList()
        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
@@ -270,9 +282,17 @@ void MessageRequester::PopulateIDList()
                st.ResultText(0,val1);\r
                st.ResultText(1,val2);\r
                st.ResultText(2,val3);\r
-               if(m_ids.find(val1+"*"+val2+"*"+val3)==m_ids.end())\r
+\r
+               requestindex=0;\r
+               StringFunctions::Convert(val3,requestindex);\r
+\r
+               // only continue if index is < max messages we will accept from a peer\r
+               if(requestindex<m_maxpeermessages)\r
                {\r
-                       m_ids[val1+"*"+val2+"*"+val3]=false;\r
+                       if(m_ids.find(val1+"*"+val2+"*"+val3)==m_ids.end())\r
+                       {\r
+                               m_ids[val1+"*"+val2+"*"+val3]=false;\r
+                       }\r
                }\r
                st.Step();\r
        }\r
@@ -307,6 +327,7 @@ void MessageRequester::StartRequest(const std::string &requestid)
                message["Identifier"]=m_fcpuniquename+"|"+requestid+"|"+parts[0]+"|"+parts[1]+"|"+parts[2]+"|"+message["URI"];\r
                message["ReturnType"]="direct";\r
                message["MaxSize"]="1000000";           // 1 MB\r
+               message["MaxRetries"]="-1";                     // use new ULPR since we are fairly sure message exists since the author says it does\r
 \r
                m_fcp->SendMessage(message);\r
 \r
index 22a4ccf..0febbbd 100644 (file)
@@ -58,6 +58,33 @@ void PeriodicDBMaintenance::Do1DayMaintenance()
 \r
        m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"PeriodicDBMaintenance::Do1DayMaintenance");\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 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
 }\r
 \r
 void PeriodicDBMaintenance::Process()\r
index 0d0df5c..c3e71db 100644 (file)
@@ -1,6 +1,8 @@
 #include "../../include/freenet/trustlistxml.h"\r
 #include "../../include/stringfunctions.h"\r
 \r
+#include <algorithm>\r
+\r
 #ifdef XMEM\r
        #include <xmem.h>\r
 #endif\r
@@ -99,6 +101,7 @@ const bool TrustListXML::ParseXML(const std::string &xml)
                TiXmlText *txt;\r
                TiXmlHandle hnd(&td);\r
                TiXmlNode *node;\r
+               std::vector<std::string> m_foundkeys;\r
 \r
                Initialize();\r
 \r
@@ -130,7 +133,12 @@ const bool TrustListXML::ParseXML(const std::string &xml)
 \r
                        if(identity!="" && messagetrust>=0 && messagetrust<=100 && trustlisttrust>=0 && trustlisttrust<=100)\r
                        {\r
-                               m_trust.push_back(trust(identity,messagetrust,trustlisttrust));\r
+                               // check so we don't add the same identity multiple times from a trust list\r
+                               if(std::find(m_foundkeys.begin(),m_foundkeys.end(),identity)==m_foundkeys.end())\r
+                               {\r
+                                       m_foundkeys.push_back(identity);\r
+                                       m_trust.push_back(trust(identity,messagetrust,trustlisttrust));\r
+                               }\r
                        }\r
                        else\r
                        {\r
index a3c8111..42a4726 100644 (file)
@@ -7,6 +7,7 @@
 #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
@@ -16,6 +17,8 @@
        #include <xmem.h>\r
 #endif\r
 \r
+bool wantshutdown=false;\r
+\r
 void SetupDB()\r
 {\r
 \r
@@ -42,10 +45,15 @@ void SetupDB()
                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
+               }\r
        }\r
        else\r
        {\r
-               db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,0);");\r
+               db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,1);");\r
        }\r
 \r
        db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\\r
@@ -57,8 +65,8 @@ void SetupDB()
        db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
                                LocalIdentityID                 INTEGER PRIMARY KEY,\\r
                                Name                                    TEXT,\\r
-                               PublicKey                               TEXT,\\r
-                               PrivateKey                              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
@@ -326,12 +334,46 @@ void SetupDB()
        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
-       // insert SomeDude's public key\r
        date.SetToGMTime();\r
+       // insert SomeDude's public key\r
        db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw,iXez4j3qCpd596TxXiJgZyTq9o-CElEuJxm~jNNZAuA,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");\r
+       // insert Shadow Panther's public key\r
+       db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");\r
+       // insert garfield's public key\r
+       db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");\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 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
@@ -487,6 +529,12 @@ void SetupDefaultOptions()
        st.Step();\r
        st.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
+\r
 }\r
 \r
 void SetupLogFile()\r
@@ -524,6 +572,16 @@ void SetupNetwork()
 #endif\r
 }\r
 \r
+void 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
@@ -531,22 +589,18 @@ void ShutdownNetwork()
 #endif\r
 }\r
 \r
+void SigHandler(int signum)\r
+{\r
+       Shutdown();\r
+       exit(0);\r
+}\r
+\r
+/*\r
 void ShutdownThreads(std::vector<PThread::Thread *> &threads)\r
 {\r
        std::vector<PThread::Thread *>::iterator i;\r
        for(i=threads.begin(); i!=threads.end(); i++)\r
        {\r
-/*             if((*i)->wait(1)==false)\r
-               {\r
-                       try\r
-                       {\r
-                               (*i)->interrupt();\r
-                       }\r
-                       catch(...)\r
-                       {\r
-                       }\r
-               }\r
-               */\r
                (*i)->Cancel();\r
        }\r
 \r
@@ -605,3 +659,4 @@ void StartThreads(std::vector<PThread::Thread *> &threads)
        }\r
 \r
 }\r
+*/\r
index f08ebe8..a1f51c7 100644 (file)
@@ -10,6 +10,7 @@
 #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
 \r
 #include <iostream>\r
 \r
@@ -52,6 +53,7 @@ HTTPThread::HTTPThread()
        m_pagehandlers.push_back(new AddPeerPage(templatestr));\r
        m_pagehandlers.push_back(new PeerTrustPage(templatestr));\r
        m_pagehandlers.push_back(new ControlBoardPage(templatestr));\r
+       m_pagehandlers.push_back(new PeerDetailsPage(templatestr));\r
        // homepage must be last - catch all page handler\r
        m_pagehandlers.push_back(new HomePage(templatestr));\r
 \r
diff --git a/src/http/identityexportxml.cpp b/src/http/identityexportxml.cpp
new file mode 100644 (file)
index 0000000..b2609bf
--- /dev/null
@@ -0,0 +1,185 @@
+#include "../../include/http/identityexportxml.h"\r
+\r
+#ifdef XMEM\r
+       #include <xmem.h>\r
+#endif\r
+\r
+IdentityExportXML::IdentityExportXML()\r
+{\r
+       Initialize();\r
+}\r
+\r
+void IdentityExportXML::AddIdentity(const std::string &name, const std::string &publickey, const std::string &privatekey, const bool singleuse, const bool publishtrustlist, const bool publishboardlist)\r
+{\r
+       m_identities.push_back(identity(name,publickey,privatekey,singleuse,publishtrustlist,publishboardlist));\r
+}\r
+\r
+const std::string IdentityExportXML::GetName(const long index)\r
+{\r
+       if(index>=0 && index<GetCount())\r
+       {\r
+               return m_identities[index].m_name;\r
+       }\r
+       else\r
+       {\r
+               return "";\r
+       }\r
+}\r
+\r
+const std::string IdentityExportXML::GetPrivateKey(const long index)\r
+{\r
+       if(index>=0 && index<GetCount())\r
+       {\r
+               return m_identities[index].m_privatekey;\r
+       }\r
+       else\r
+       {\r
+               return "";\r
+       }\r
+}\r
+\r
+const std::string IdentityExportXML::GetPublicKey(const long index)\r
+{\r
+       if(index>=0 && index<GetCount())\r
+       {\r
+               return m_identities[index].m_publickey;\r
+       }\r
+       else\r
+       {\r
+               return "";\r
+       }\r
+}\r
+\r
+const bool IdentityExportXML::GetPublishBoardList(const long index)\r
+{\r
+       if(index>=0 && index<GetCount())\r
+       {\r
+               return m_identities[index].m_publishboardlist;\r
+       }\r
+       else\r
+       {\r
+               return false;\r
+       }\r
+}\r
+\r
+const bool IdentityExportXML::GetPublishTrustList(const long index)\r
+{\r
+       if(index>=0 && index<GetCount())\r
+       {\r
+               return m_identities[index].m_publishtrustlist;\r
+       }\r
+       else\r
+       {\r
+               return false;\r
+       }\r
+}\r
+\r
+const bool IdentityExportXML::GetSingleUse(const long index)\r
+{\r
+       if(index>=0 && index<GetCount())\r
+       {\r
+               return m_identities[index].m_singleuse;\r
+       }\r
+       else\r
+       {\r
+               return false;\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
+\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
+       }\r
+\r
+       td.Accept(&tp);\r
+       return std::string(tp.CStr());\r
+}\r
+\r
+void IdentityExportXML::Initialize()\r
+{\r
+       m_identities.clear();\r
+}\r
+\r
+const bool IdentityExportXML::ParseXML(const std::string &xml)\r
+{\r
+       TiXmlDocument td;\r
+       td.Parse(xml.c_str());\r
+\r
+       if(!td.Error())\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
+               TiXmlText *txt;\r
+               TiXmlHandle hnd(&td);\r
+               TiXmlNode *node;\r
+\r
+               Initialize();\r
+\r
+               node=hnd.FirstChild("IdentityExport").FirstChild("Identity").ToElement();\r
+               while(node)\r
+               {\r
+                       name="";\r
+                       publickey="";\r
+                       privatekey="";\r
+                       singleuse=false;\r
+                       publishtrustlist=false;\r
+                       publishboardlist=false;\r
+\r
+                       TiXmlHandle hnd2(node);\r
+                       txt=hnd2.FirstChild("Name").FirstChild().ToText();\r
+                       if(txt)\r
+                       {\r
+                               name=txt->ValueStr();\r
+                       }\r
+                       txt=hnd2.FirstChild("PublicKey").FirstChild().ToText();\r
+                       if(txt)\r
+                       {\r
+                               publickey=txt->ValueStr();\r
+                       }\r
+                       txt=hnd2.FirstChild("PrivateKey").FirstChild().ToText();\r
+                       if(txt)\r
+                       {\r
+                               privatekey=txt->ValueStr();\r
+                       }\r
+\r
+                       singleuse=XMLGetBooleanElement(node->ToElement(),"SingleUse");\r
+                       publishtrustlist=XMLGetBooleanElement(node->ToElement(),"PublishTrustList");\r
+                       publishboardlist=XMLGetBooleanElement(node->ToElement(),"PublishBoardList");\r
+\r
+                       if(name!="" && publickey!="" && privatekey!="")\r
+                       {\r
+                               m_identities.push_back(identity(name,publickey,privatekey,singleuse,publishtrustlist,publishboardlist));\r
+                       }\r
+                       \r
+                       node=node->NextSibling("Identity");\r
+               }\r
+               return true;\r
+\r
+       }\r
+       else\r
+       {\r
+               return false;\r
+       }\r
+}
\ No newline at end of file
index c4ebbb9..f4ac20f 100644 (file)
@@ -44,6 +44,28 @@ const bool IPageHandler::Handle(shttpd_arg *arg)
        if(uri && WillHandleURI(std::string(uri)))\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
@@ -84,29 +106,45 @@ const bool IPageHandler::Handle(shttpd_arg *arg)
                        //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(mystate->m_indata)\r
+                       if(shttpd_get_header(arg,"Content-Type"))\r
                        {\r
-                               StringFunctions::Split(mystate->m_indata,"&",argparts);\r
+                               contenttype=shttpd_get_header(arg,"Content-Type");\r
                        }\r
-                       if(shttpd_get_env(arg,"QUERY_STRING"))\r
+                       \r
+                       if(contenttype.find("multipart/form-data")!=std::string::npos)\r
                        {\r
-                               StringFunctions::Split(shttpd_get_env(arg,"QUERY_STRING"),"&",argparts);\r
+                               HandleMultiPartData(contenttype,mystate->m_indata,mystate->m_indatalen,args);\r
                        }\r
-                       for(std::vector<std::string>::iterator argi=argparts.begin(); argi!=argparts.end(); argi++)\r
+                       else\r
                        {\r
-                               std::vector<std::string> parts;\r
-                               StringFunctions::Split((*argi),"=",parts);\r
-                               if(parts.size()>0)\r
+                               // split apart non-multipart POST\r
+                               if(mystate->m_indata)\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
+                                       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[1]=StringFunctions::Replace(parts[1],"+"," ");\r
-                                               args[StringFunctions::UriDecode(parts[0])]=StringFunctions::UriDecode(parts[1]);\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
@@ -154,6 +192,73 @@ const bool IPageHandler::Handle(shttpd_arg *arg)
        }\r
 }\r
 \r
+void IPageHandler::HandleMultiPartData(const std::string &contenttypeheader, char *data, const long datalen, std::map<std::string,std::string> &args)\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
+\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
+\r
+               // split into parts separated by boundary\r
+               StringFunctions::Split(datastr,"--"+boundary+"\r\n",parts);\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
+\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
+\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
 {\r
        // must do & first because all other elements have & in them!\r
index 710904c..b67f16f 100644 (file)
@@ -18,12 +18,18 @@ const std::string AnnounceIdentityPage::CreateLocalIdentityDropDown(const std::s
                std::string id;\r
                std::string name;\r
                std::string pubkey;\r
+               std::string keypart="";\r
 \r
                st.ResultText(0,id);\r
                st.ResultText(1,name);\r
                st.ResultText(2,pubkey);\r
 \r
-               rval+="<option value=\""+id+"\" title=\""+pubkey+"\">"+name+"</option>";\r
+               if(pubkey.size()>8)\r
+               {\r
+                       keypart=pubkey.substr(3,5);\r
+               }\r
+\r
+               rval+="<option value=\""+id+"\" title=\""+pubkey+"\">"+SanitizeOutput(name+keypart)+"...</option>";\r
                st.Step();\r
        }\r
        rval+="</select>";\r
@@ -81,7 +87,7 @@ const std::string AnnounceIdentityPage::GeneratePage(const std::string &method,
        content+="<tr><td colspan=\"4\"><center>Select Identity : ";\r
        content+=CreateLocalIdentityDropDown("localidentityid","");\r
        content+="</td></tr>";\r
-       content+="<tr><td colspan=\"4\"><center>Type the answers of a few puzzles</td></tr>";\r
+       content+="<tr><td colspan=\"4\"><center>Type the answers of a few puzzles.  The puzzles are case sensitive.</td></tr>";\r
        content+="<tr>";\r
 \r
        //TODO if we are already inserting a solution for an identity - we shouldn't select any puzzles that are older than the one we are inserting\r
index cbc57e4..c89d92c 100644 (file)
@@ -1,5 +1,6 @@
 #include "../../../include/http/pages/homepage.h"\r
 #include "../../../include/stringfunctions.h"\r
+#include "../../../include/global.h"\r
 \r
 #ifdef XMEM\r
        #include <xmem.h>\r
@@ -7,10 +8,22 @@
 \r
 const std::string HomePage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
 {\r
+\r
+       if(queryvars.find("formaction")!=queryvars.end() && (*queryvars.find("formaction")).second=="shutdown")\r
+       {\r
+               wantshutdown=true;\r
+       }\r
+\r
        std::string content="<h2>Home</h2>";\r
        content+="<p class=\"paragraph\">";\r
        content+="Use these pages to administer your FMS installation.";\r
        content+="</p>";\r
+       content+="<p class=\"paragraph\">";\r
+       content+="<form name=\"frmshutdown\" method=\"POST\">";\r
+       content+="<input type=\"hidden\" name=\"formaction\" value=\"shutdown\">";\r
+       content+="<input type=\"submit\" value=\"Shutdown FMS\">";\r
+       content+="</form>";\r
+       content+="</p>";\r
        return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content);\r
 }\r
 \r
index e926b2f..84c28b3 100644 (file)
@@ -1,5 +1,6 @@
 #include "../../../include/http/pages/localidentitiespage.h"\r
 #include "../../../include/stringfunctions.h"\r
+#include "../../../include/http/identityexportxml.h"\r
 \r
 #ifdef XMEM\r
        #include <xmem.h>\r
@@ -33,7 +34,6 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c
        std::string countstr;\r
        std::string content="";\r
 \r
-\r
        if(queryvars.find("formaction")!=queryvars.end())\r
        {\r
                int id;\r
@@ -75,9 +75,111 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c
                                }\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 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
+\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
+\r
+                               xml.AddIdentity(name,publickey,privatekey,singleuse,publishtrustlist,publishboardlist);\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) 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
+                                               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
+       content+="<tr><td>";\r
+       content+="<form name=\"frmexport\" method=\"POST\">";\r
+       content+="<input type=\"hidden\" name=\"formaction\" value=\"export\">";\r
+       content+="<input type=\"submit\" value=\"Export Identities\">";\r
+       content+="</form>";\r
+       content+="</td><td>";\r
+       content+="<form name=\"frmimport\" method=\"POST\" enctype=\"multipart/form-data\">";\r
+       content+="<input type=\"hidden\" name=\"formaction\" value=\"import\">";\r
+       content+="<input type=\"file\" name=\"file\">";\r
+       content+="<input type=\"submit\" value=\"Import Identities\">";\r
+       content+="</form>";\r
+       content+="</td></tr></table>";\r
+\r
        content+="<form name=\"frmlocalidentity\" method=\"POST\">";\r
        content+="<input type=\"hidden\" name=\"formaction\" value=\"update\">";\r
        content+="<table><tr><td></td><th>Name</th><th>Single Use</th><th>Publish Trust List</th><th>Announced? *</th></tr>";\r
diff --git a/src/http/pages/peerdetailspage.cpp b/src/http/pages/peerdetailspage.cpp
new file mode 100644 (file)
index 0000000..83b1b34
--- /dev/null
@@ -0,0 +1,139 @@
+#include "../../../include/http/pages/peerdetailspage.h"\r
+#include "../../../include/stringfunctions.h"\r
+\r
+#ifdef XMEM\r
+       #include <xmem.h>\r
+#endif\r
+\r
+const std::string PeerDetailsPage::GeneratePage(const std::string &method, const std::map<std::string,std::string> &queryvars)\r
+{\r
+       std::string content="";\r
+       int identityid=0;\r
+       std::string name;\r
+       std::string publickey;\r
+       std::string messagetrust;\r
+       std::string trustlisttrust;\r
+       std::string keypart="";\r
+       std::string lastseen="";\r
+\r
+       if(queryvars.find("identityid")!=queryvars.end() && (*queryvars.find("identityid")).second!="")\r
+       {\r
+               StringFunctions::Convert((*queryvars.find("identityid")).second,identityid);\r
+       }\r
+\r
+       SQLite3DB::Statement st=m_db->Prepare("SELECT Name,PublicKey,LastSeen FROM tblIdentity WHERE IdentityID=?;");\r
+       st.Bind(0,identityid);\r
+       st.Step();\r
+\r
+       if(st.RowReturned())\r
+       {\r
+               st.ResultText(0,name);\r
+               st.ResultText(1,publickey);\r
+               st.ResultText(2,lastseen);\r
+\r
+               content+="<table>";\r
+               content+="<tr><td>Name</td><td>"+SanitizeOutput(name)+"</td></tr>";\r
+               content+="<tr><td>Public Key</td><td>"+SanitizeOutput(publickey)+"</td></tr>";\r
+               content+="<tr><td>Last Seen</td><td>"+lastseen+"</td></tr>";\r
+               content+="</table>";\r
+       }\r
+\r
+       st=m_db->Prepare("SELECT Name,PublicKey,MessageTrust,TrustListTrust,tblIdentity.IdentityID FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.TargetIdentityID=tblIdentity.IdentityID WHERE tblPeerTrust.IdentityID=? ORDER BY Name COLLATE NOCASE;");\r
+       st.Bind(0,identityid);\r
+       st.Step();\r
+\r
+       content+="<table>";\r
+       content+="<tr><th colspan=\"3\">";\r
+       content+="Trust List of this identity";\r
+       content+="</th></tr>";\r
+       content+="<tr><td></td><th>Message Trust</th><th>Trust List Trust</th></tr>";\r
+       while(st.RowReturned())\r
+       {\r
+               std::string thisid="";\r
+\r
+               st.ResultText(0,name);\r
+               st.ResultText(1,publickey);\r
+               st.ResultText(2,messagetrust);\r
+               st.ResultText(3,trustlisttrust);\r
+               st.ResultText(4,thisid);\r
+\r
+               if(publickey.size()>8)\r
+               {\r
+                       keypart=publickey.substr(3,5);\r
+               }\r
+\r
+               content+="<tr>";\r
+               content+="<td><a href=\"peerdetails.htm?identityid="+thisid+"\">"+SanitizeOutput(name+keypart)+"...</a></td>";\r
+               content+="<td "+GetClassString(messagetrust)+">"+messagetrust+"</td>";\r
+               content+="<td "+GetClassString(trustlisttrust)+">"+trustlisttrust+"</td>";\r
+               content+="</tr>\r\n";\r
+\r
+               st.Step();\r
+       }\r
+\r
+       st=m_db->Prepare("SELECT Name,PublicKey,MessageTrust,TrustListTrust,tblIdentity.IdentityID FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID WHERE tblPeerTrust.TargetIdentityID=? ORDER BY Name COLLATE NOCASE;");\r
+       st.Bind(0,identityid);\r
+       st.Step();\r
+\r
+       content+="<tr><th colspan=\"3\">";\r
+       content+="Trust of this identity from other identities";\r
+       content+="</th></tr>";\r
+       content+="<tr><td></td><th>Message Trust</th><th>Trust List Trust</th></tr>";\r
+       while(st.RowReturned())\r
+       {\r
+               std::string thisid="";\r
+\r
+               st.ResultText(0,name);\r
+               st.ResultText(1,publickey);\r
+               st.ResultText(2,messagetrust);\r
+               st.ResultText(3,trustlisttrust);\r
+               st.ResultText(4,thisid);\r
+               \r
+               if(publickey.size()>8)\r
+               {\r
+                       keypart=publickey.substr(3,5);\r
+               }\r
+\r
+               content+="<tr>";\r
+               content+="<td><a href=\"peerdetails.htm?identityid="+thisid+"\">"+SanitizeOutput(name+keypart)+"...</a></td>";\r
+               content+="<td "+GetClassString(messagetrust)+">"+messagetrust+"</td>";\r
+               content+="<td "+GetClassString(trustlisttrust)+">"+trustlisttrust+"</td>";\r
+               content+="</tr>";\r
+\r
+               st.Step();\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
+}\r
+\r
+const std::string PeerDetailsPage::GetClassString(const std::string &trustlevel)\r
+{\r
+       int tempint=0;\r
+       std::string tempstr;\r
+\r
+       StringFunctions::Convert(trustlevel,tempint);\r
+       tempint/=10;\r
+       StringFunctions::Convert(tempint,tempstr);\r
+\r
+       if(trustlevel!="")\r
+       {\r
+               return "class=\"trust"+tempstr+"\"";\r
+       }\r
+       else\r
+       {\r
+               return "";\r
+       }\r
+}\r
+\r
+const bool PeerDetailsPage::WillHandleURI(const std::string &uri)\r
+{\r
+       if(uri.find("peerdetails.")!=std::string::npos)\r
+       {\r
+               return true;\r
+       }\r
+       else\r
+       {\r
+               return false;\r
+       }\r
+}\r
index b353243..38bddbf 100644 (file)
@@ -15,6 +15,8 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
        std::string rowsperpagestr;\r
        int startrow=0;\r
        std::string startrowstr="0";\r
+       std::string namesearch="";\r
+       std::string sql;\r
 \r
        StringFunctions::Convert(rowsperpage,rowsperpagestr);\r
 \r
@@ -68,20 +70,53 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
                StringFunctions::Convert(startrow,startrowstr);\r
        }\r
 \r
+       // if we are searching by name\r
+       if(queryvars.find("namesearch")!=queryvars.end())\r
+       {\r
+               namesearch=(*queryvars.find("namesearch")).second;\r
+       }\r
+\r
        content+="<h2>Peer Trust</h2>";\r
        content+="Message Trust is how much you trust the identity to post good messages. Trust List Trust is how much weight you want the trust list of that identity to have when calculating the total. The local trust levels are set by you, and the peer trust levels are calculated by a weighted average using other identities trust lists.";\r
+       content+="<div style=\"text-align:center;\">";\r
+       content+="<form name=\"frmsearch\" method=\"POST\" action=\"peertrust.htm\">";\r
+       content+="<input type=\"text\" name=\"namesearch\">";\r
+       content+="<input type=\"submit\" value=\"Search\">";\r
+       content+="</form>";\r
+       content+="</div>";\r
        content+="<form name=\"frmtrust\" method=\"POST\">";\r
        content+="<input type=\"hidden\" name=\"formaction\" value=\"update\">";\r
        content+="<input type=\"hidden\" name=\"startrow\" value=\""+startrowstr+"\">";\r
        content+="<table>";\r
        content+="<tr><th>Name</th><th>Local Message Trust</th><th>Peer Message Trust</th><th>Local Trust List Trust</th><th>Peer Trust List Trust</th></tr>";\r
        \r
-       SQLite3DB::Statement st=m_db->Prepare("SELECT COUNT(*) FROM tblIdentity;");\r
+       // get count of identities we are showing\r
+       sql="SELECT COUNT(*) FROM tblIdentity";\r
+       if(namesearch!="")\r
+       {\r
+               sql+=" WHERE Name LIKE '%' || ? || '%'";\r
+       }\r
+       sql+=";";\r
+       SQLite3DB::Statement st=m_db->Prepare(sql);\r
+       if(namesearch!="")\r
+       {\r
+               st.Bind(0,namesearch);\r
+       }\r
        st.Step();\r
        st.ResultInt(0,identitycount);\r
        st.Finalize();\r
 \r
-       st=m_db->Prepare("SELECT IdentityID,Name,LocalMessageTrust,PeerMessageTrust,LocalTrustListTrust,PeerTrustListTrust,PublicKey FROM tblIdentity ORDER BY Name COLLATE NOCASE LIMIT "+startrowstr+","+rowsperpagestr+";");\r
+       sql="SELECT IdentityID,Name,LocalMessageTrust,PeerMessageTrust,LocalTrustListTrust,PeerTrustListTrust,PublicKey FROM tblIdentity";\r
+       if(namesearch!="")\r
+       {\r
+               sql+=" WHERE Name LIKE  '%' || ? || '%'";\r
+       }\r
+       sql+=" ORDER BY Name COLLATE NOCASE LIMIT "+startrowstr+","+rowsperpagestr+";";\r
+       st=m_db->Prepare(sql);\r
+       if(namesearch!="")\r
+       {\r
+               st.Bind(0,namesearch);\r
+       }\r
        st.Step();\r
 \r
        while(st.RowReturned())\r
@@ -113,6 +148,7 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
                content+="<tr>";\r
                content+="<td title=\""+publickey+"\">";\r
                content+="<input type=\"hidden\" name=\"identityid["+countstr+"]\" value=\""+identityid+"\">";\r
+               content+="<a href=\"peerdetails.htm?identityid="+identityid+"\">";\r
                if(name!="")\r
                {\r
                        content+=SanitizeOutput(name+keypart)+"...";\r
@@ -121,6 +157,7 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
                {\r
                        content+="[Unknown Name]";\r
                }\r
+               content+="</a>";\r
                content+="</td>";\r
                content+="<td "+GetClassString(localmessagetrust)+">";\r
                content+="<input type=\"hidden\" name=\"oldlocalmessagetrust["+countstr+"]\" value=\""+localmessagetrust+"\">";\r
@@ -146,7 +183,7 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
                if(startrow>0)\r
                {\r
                        StringFunctions::Convert(startrow-rowsperpage,tempstr);\r
-                       content+="<td colspan=\"2\" align=\"left\"><a href=\"peertrust.htm?startrow="+tempstr+"\"><-- Previous Page</a></td>";\r
+                       content+="<td colspan=\"2\" align=\"left\"><a href=\"peertrust.htm?startrow="+tempstr+"&namesearch="+namesearch+"\"><-- Previous Page</a></td>";\r
                        cols+=2;\r
                }\r
                if(startrow+rowsperpage<identitycount)\r
@@ -157,7 +194,7 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s
                                content+="<td></td>";\r
                                cols++;\r
                        }\r
-                       content+="<td colspan=\"2\" align=\"right\"><a href=\"peertrust.htm?startrow="+tempstr+"\">Next Page --></a></td>";\r
+                       content+="<td colspan=\"2\" align=\"right\"><a href=\"peertrust.htm?startrow="+tempstr+"&namesearch="+namesearch+"\">Next Page --></a></td>";\r
                }\r
                content+="</tr>";\r
        }\r
index abd65b3..46a4d3d 100644 (file)
@@ -11,7 +11,7 @@ const std::string ShowCaptchaPage::GeneratePage(const std::string &method, const
        std::string content="HTTP/1.1 200 OK\r\n";\r
        if(queryvars.find("UUID")!=queryvars.end())\r
        {\r
-               SQLite3DB::Statement st=m_db->Prepare("SELECT MimeType,PuzzleData FROM tblIntroductionPuzzleRequests WHERE UUID=?;");\r
+               SQLite3DB::Statement st=m_db->Prepare("SELECT MimeType,PuzzleData FROM tblIntroductionPuzzleRequests WHERE Type='captcha' AND UUID=?;");\r
                st.Bind(0,(*queryvars.find("UUID")).second);\r
                st.Step();\r
 \r
@@ -27,9 +27,13 @@ const std::string ShowCaptchaPage::GeneratePage(const std::string &method, const
                        Base64::Decode(b64data,data);\r
                        StringFunctions::Convert(data.size(),lenstr);\r
 \r
-                       content+="Content-Type: "+mime+"\r\n";\r
-                       content+="Content-Length: "+lenstr+"\r\n\r\n";\r
-                       content+=std::string(data.begin(),data.end());\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
+                               content+=std::string(data.begin(),data.end());\r
+                       }\r
                }\r
        }\r
        return content;\r
index 8746da2..17d6b67 100644 (file)
 #include "../include/global.h"\r
 #include "../include/commandthread.h"\r
+#include "../include/threadcontroller.h"\r
 \r
 #include <ctime>\r
+#include <csignal>\r
+#include <iostream>\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()\r
+int main(int argc, char *argv[])\r
 {\r
 \r
        #ifdef XMEM\r
                xmem_disable_print();\r
        #endif\r
 \r
-       std::vector<PThread::Thread *> threads;\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
+               }\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
+       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
+       MainFunction();\r
+\r
+       return 0;\r
+}\r
 \r
+void MainFunction()\r
+{\r
        srand(time(NULL));\r
 \r
        SetupDB();\r
@@ -27,21 +119,12 @@ int main()
 \r
        LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS startup v"FMS_VERSION);\r
 \r
+       ThreadController::Instance()->StartThreads();\r
 \r
-       StartThreads(threads);\r
-\r
-\r
-       //ZThread::Thread commandthread(new CommandThread());\r
-       PThread::Thread commandthread(new CommandThread());\r
-       commandthread.Join();\r
-\r
+       do\r
+       {\r
+               PThread::Sleep(1000);\r
+       }while(!wantshutdown);\r
 \r
-       ShutdownThreads(threads);\r
-\r
-       ShutdownNetwork();\r
-\r
-       LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");\r
-       LogFile::Instance()->WriteNewLine();\r
-\r
-       return 0;\r
+       Shutdown();\r
 }\r
index 5861ef0..123d370 100644 (file)
@@ -509,7 +509,7 @@ const bool Message::ParseNNTPMessage(const std::string &nntpmessage)
 \r
 void Message::StartFreenetInsert()\r
 {\r
-       //TODO if message was posted to one of the special administration boards - don't really insert it, but perform the action\r
+\r
        MessageXML xml;\r
        int localidentityid=-1;\r
 \r
index 0bf826d..89de9f1 100644 (file)
@@ -362,7 +362,7 @@ void CMimeHeader::SetBoundary(const char* pszBoundary/*=NULL*/)
        char buf[80];\r
        if (!pszBoundary)                               // generate a new boundary delimeter\r
        {\r
-               ::srand(((unsigned)::time(NULL)) ^ reinterpret_cast<unsigned>(this));\r
+               ::srand(((unsigned)::time(NULL)));// ^ reinterpret_cast<unsigned>(this));\r
                ::sprintf(buf, "__=_Part_Boundary_%03d_%06d.%06d", ++s_nPartNumber, rand(), rand());\r
                if (s_nPartNumber >= 9)\r
                        s_nPartNumber = 0;\r
@@ -475,7 +475,11 @@ list<CMimeField>::iterator CMimeHeader::FindField(const char* pszFieldName)
        #include <io.h>\r
 #else\r
        #if !defined(__APPLE__) && !defined(__DARWIN__)\r
-               #include <sys/io.h>\r
+               #ifndef __FreeBSD__\r
+                       #include <sys/io.h>\r
+               #else\r
+                       #include <stdio.h>\r
+               #endif\r
        #endif\r
 #endif\r
 \r
index 7a4e972..d08cf33 100644 (file)
@@ -9,6 +9,26 @@
 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
+\r
 Thread::Thread()\r
 {\r
        m_running=false;\r
index 8bfb7b5..48984e8 100644 (file)
@@ -39,7 +39,7 @@ void ThreadController::ReadConfig()
        }\r
 \r
        tempval="";\r
-       Option::Instance()->Get("StartHHTP",tempval);\r
+       Option::Instance()->Get("StartHTTP",tempval);\r
        if(tempval=="true")\r
        {\r
                m_starthttp=true;\r
@@ -53,6 +53,7 @@ void ThreadController::ReadConfig()
 \r
 void ThreadController::RestartThreads()\r
 {\r
+       m_log->WriteLog(LogFile::LOGLEVEL_INFO,"ThreadController::RestartThreads restarting threads.");\r
        ShutdownThreads();\r
        StartThreads();\r
 }\r
@@ -61,6 +62,7 @@ void ThreadController::ShutdownFreenetThread()
 {\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
@@ -72,6 +74,7 @@ void ThreadController::ShutdownHTTPThread()
 {\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
@@ -83,6 +86,7 @@ void ThreadController::ShutdownNNTPThread()
 {\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
@@ -99,16 +103,19 @@ void ThreadController::ShutdownThreads()
 \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