X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fglobal.cpp;h=7e6d8424847d78071c1e8b131e2df86733064a8e;hb=63376b2a82c3f6cdf2df56b1f134bd7df0aaab3a;hp=cf531de12b95b11430bcaeced84728a7cdf9f22b;hpb=6b896a9e1dc143bba86795be1e9336549db9b85f;p=fms.git diff --git a/src/global.cpp b/src/global.cpp index cf531de..7e6d842 100644 --- a/src/global.cpp +++ b/src/global.cpp @@ -6,6 +6,8 @@ #include "../include/db/sqlite3db.h" #include "../include/freenet/freenetmasterthread.h" #include "../include/nntp/nntplistener.h" +#include "../include/http/httpthread.h" +#include "../include/threadcontroller.h" #ifdef _WIN32 #include @@ -15,14 +17,103 @@ #include #endif +bool wantshutdown=false; + +std::string CreateShortIdentityName(const std::string &name, const std::string &publickey) +{ + std::string result=""; + std::vector keyparts; + + StringFunctions::SplitMultiple(publickey,"@,",keyparts); + + result+=name; + if(keyparts.size()>1 && keyparts[1].size()>8) + { + result+="@"+keyparts[1].substr(0,4)+"..."; + } + + return result; +} + void SetupDB() { - SQLite3DB::DB *db=SQLite3DB::DB::instance(); + DateTime date; + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); db->Open("fms.db3"); db->SetBusyTimeout(10000); // set timeout to 10 seconds - db->Execute("VACUUM;"); + //db->Execute("VACUUM;"); // not needed every startup + + db->Execute("CREATE TABLE IF NOT EXISTS tblDBVersion(\ + Major INTEGER,\ + Minor INTEGER\ + );"); + + SQLite3DB::Statement st=db->Prepare("SELECT Major,Minor FROM tblDBVersion;"); + st.Step(); + if(st.RowReturned()) + { + int major; + int minor; + st.ResultInt(0,major); + st.ResultInt(1,minor); + st.Finalize(); + if(major==1 && minor==0) + { + ConvertDB0100To0101(); + major=1; + minor=1; + } + if(major==1 && (minor==1 || minor==2)) + { + ConvertDB0101To0103(); + major=1; + minor=3; + } + if(major==1 && minor==3) + { + ConvertDB0103To0104(); + major=1; + minor=4; + } + if(major==1 && minor==4) + { + ConvertDB0104To0105(); + major=1; + minor=5; + } + if(major==1 && minor==5) + { + ConvertDB0105To0106(); + major=1; + minor=6; + } + if(major==1 && minor==6) + { + ConvertDB0106To0107(); + major=1; + minor=7; + } + if(major==1 && minor==7) + { + ConvertDB0107To0108(); + major=1; + minor=8; + } + if(major==1 && minor==8) + { + ConvertDB0108To0109(); + major=1; + minor=9; + } + } + else + { + db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,9);"); + } + + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;"); db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\ Option TEXT UNIQUE,\ @@ -33,11 +124,13 @@ void SetupDB() db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\ LocalIdentityID INTEGER PRIMARY KEY,\ Name TEXT,\ - PublicKey TEXT,\ - PrivateKey TEXT,\ + PublicKey TEXT UNIQUE,\ + PrivateKey TEXT UNIQUE,\ SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\ PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\ PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\ + PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\ + FreesiteEdition INTEGER,\ InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\ LastInsertedIdentity DATETIME,\ InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\ @@ -47,7 +140,9 @@ void SetupDB() InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\ LastInsertedBoardList DATETIME,\ InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\ - LastInsertedMessageList DATETIME\ + LastInsertedMessageList DATETIME,\ + LastInsertedFreesite DATETIME,\ + DateCreated DATETIME\ );"); db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\ @@ -82,18 +177,23 @@ void SetupDB() );"); db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\ - IdentityID INTEGER PRIMARY KEY,\ - PublicKey TEXT,\ - Name TEXT,\ - SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\ - PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\ - PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\ - DateAdded DATETIME,\ - LastSeen DATETIME,\ - LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT 50,\ - PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT 50,\ - LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT 50,\ - PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT 50\ + IdentityID INTEGER PRIMARY KEY,\ + PublicKey TEXT UNIQUE,\ + Name TEXT,\ + SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\ + PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\ + PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\ + FreesiteEdition INTEGER,\ + DateAdded DATETIME,\ + LastSeen DATETIME,\ + LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + AddedMethod TEXT,\ + MessageTrustComment TEXT,\ + TrustListTrustComment TEXT,\ + Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false'\ );"); db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\ @@ -122,24 +222,60 @@ void SetupDB() Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\ );"); + db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityTrust(\ + LocalIdentityID INTEGER,\ + IdentityID INTEGER,\ + LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + MessageTrustComment TEXT,\ + LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + TrustListTrustComment TEXT\ + );"); + + db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxIdentityTrust_IDs ON tblIdentityTrust(LocalIdentityID,IdentityID);"); + + db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOnIdentityTrust AFTER INSERT ON tblIdentityTrust \ + FOR EACH ROW \ + BEGIN \ + 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; \ + END;"); + + db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOnIdentityTrust AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentityTrust \ + FOR EACH ROW \ + BEGIN \ + 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; \ + END;"); + + db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOnIdentityTrust AFTER DELETE ON tblIdentityTrust \ + FOR EACH ROW \ + BEGIN \ + 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; \ + END;"); + db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\ - IdentityID INTEGER,\ - TargetIdentityID INTEGER,\ - MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\ - TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100)\ + IdentityID INTEGER,\ + TargetIdentityID INTEGER,\ + MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\ + TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100),\ + MessageTrustComment TEXT,\ + TrustListTrustComment TEXT\ );"); + db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_IdentityID ON tblPeerTrust (IdentityID);"); + db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_TargetIdentityID ON tblPeerTrust (TargetIdentityID);"); + db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\ - BoardID INTEGER PRIMARY KEY,\ - BoardName TEXT UNIQUE,\ - BoardDescription TEXT,\ - DateAdded DATETIME\ + BoardID INTEGER PRIMARY KEY,\ + BoardName TEXT UNIQUE,\ + BoardDescription TEXT,\ + DateAdded DATETIME,\ + SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true',\ + AddedMethod TEXT\ );"); - db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01');"); - db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01');"); - db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01');"); - db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01');"); + db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('fms','Freenet Message System','2007-12-01 12:00:00','Initial Board');"); + db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00','Initialt Board');"); + db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('public','Public discussion','2007-12-01 12:00:00','Initial Board');"); + db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('test','Test board','2007-12-01 12:00:00','Initial Board');"); db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\ MessageID INTEGER PRIMARY KEY,\ @@ -150,20 +286,28 @@ void SetupDB() Subject TEXT,\ MessageUUID TEXT UNIQUE,\ ReplyBoardID INTEGER,\ - Body TEXT\ + Body TEXT,\ + MessageIndex INTEGER\ );"); + db->Execute("CREATE INDEX IF NOT EXISTS idxMessage_IdentityID ON tblMessage (IdentityID);"); + db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\ MessageID INTEGER,\ - ReplyToMessageUUID INTEGER,\ + ReplyToMessageUUID TEXT,\ ReplyOrder INTEGER\ );"); + db->Execute("CREATE INDEX IF NOT EXISTS idxMessageReplyTo_MessageID ON tblMessageReplyTo (MessageID);"); + db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\ MessageID INTEGER,\ BoardID INTEGER\ );"); + db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_MessageID ON tblMessageBoard (MessageID);"); + db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_BoardID ON tblMessageBoard (BoardID);"); + db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\ IdentityID INTEGER,\ Day DATE,\ @@ -179,6 +323,8 @@ void SetupDB() Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\ );"); + db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);"); + db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\ LocalIdentityID INTEGER,\ Day DATE,\ @@ -188,6 +334,15 @@ void SetupDB() Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\ );"); + db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\ + FileInsertID INTEGER PRIMARY KEY,\ + MessageUUID TEXT,\ + FileName TEXT,\ + Key TEXT,\ + Size INTEGER,\ + Data BLOB\ + );"); + db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\ LocalIdentityID INTEGER,\ Day DATE,\ @@ -195,38 +350,78 @@ void SetupDB() Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\ );"); + db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\ + BoardID INTEGER UNIQUE,\ + ModifyLocalMessageTrust INTEGER,\ + ModifyLocalTrustListTrust INTEGER\ + );"); + + db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\ + LocalIdentityID INTEGER,\ + Day DATE,\ + InsertIndex INTEGER,\ + Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\ + );"); + + db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\ + IdentityID INTEGER,\ + Day DATE,\ + RequestIndex INTEGER,\ + Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\ + );"); + + // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed + db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\ + LocalIdentityID INTEGER,\ + Date DATETIME\ + );"); + // low / high / message count for each board db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \ SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \ FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \ - WHERE MessageID>=0 \ + WHERE MessageID>=0 OR MessageID IS NULL \ GROUP BY tblBoard.BoardID;"); // calculates peer trust + // 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 + // need the +1 so that when the values are 0 the result is not 0 + db->Execute("DROP VIEW IF EXISTS vwCalculatedPeerTrust;"); db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \ SELECT TargetIdentityID, \ - ROUND(SUM(MessageTrust*(LocalMessageTrust/100.0))/SUM(LocalMessageTrust/100.0),0) AS 'PeerMessageTrust', \ - ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(LocalTrustListTrust/100.0),0) AS 'PeerTrustListTrust' \ + ROUND(SUM(MessageTrust*(LocalTrustListTrust/100.0))/SUM(((MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1))/100.0),0) AS 'PeerMessageTrust', \ + ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(((TrustListTrust+1)*LocalTrustListTrust/(TrustListTrust+1))/100.0),0) AS 'PeerTrustListTrust' \ FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \ WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \ + AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \ GROUP BY TargetIdentityID;"); + /* + These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed + All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class + */ + // drop existing triggers + db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;"); + db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;"); + db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;"); + db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;"); +/* // update PeerTrustLevel when deleting a record from tblPeerTrust - db->Execute("CREATE TRIGGER trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \ + db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \ FOR EACH ROW \ BEGIN \ 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;\ END;"); // update PeerTrustLevel when inserting a record into tblPeerTrust - db->Execute("CREATE TRIGGER trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \ + db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \ FOR EACH ROW \ BEGIN \ 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;\ END;"); // update PeerTrustLevel when updating a record in tblPeerTrust - db->Execute("CREATE TRIGGER trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \ + db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \ FOR EACH ROW \ BEGIN \ 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;\ @@ -234,15 +429,202 @@ void SetupDB() END;"); // 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. - db->Execute("CREATE TRIGGER trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \ + db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \ FOR EACH ROW \ BEGIN \ UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\ END;"); +*/ + + db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \ + FOR EACH ROW \ + BEGIN \ + DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\ + DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\ + END;"); + + db->Execute("DROP TRIGGER IF EXISTS trgDeleteIdentity;"); + db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \ + FOR EACH ROW \ + BEGIN \ + DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\ + DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\ + DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\ + DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\ + DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\ + DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\ + DELETE FROM tblIdentityTrust WHERE IdentityID=old.IdentityID;\ + END;"); + + db->Execute("DROP TRIGGER IF EXISTS trgDeleteLocalIdentity;"); + db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \ + FOR EACH ROW \ + BEGIN \ + DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\ + DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\ + DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\ + DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\ + DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\ + DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\ + DELETE FROM tblIdentityTrust WHERE LocalIdentityID=old.LocalIdentityID;\ + END;"); + + db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \ + FOR EACH ROW \ + BEGIN \ + DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\ + END;"); // delete introduction puzzles that were half-way inserted db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;"); + // delete stale introduction puzzles (2 or more days old) + date.SetToGMTime(); + date.Add(0,0,0,-2); + db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';"); + db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';"); + + date.SetToGMTime(); + // insert SomeDude's public key + 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');"); + // insert Shadow Panther's public key + 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');"); + // insert garfield's public key + db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');"); + + // TODO remove sometime after 0.1.17 + FixCapitalBoardNames(); + + // run analyze - may speed up some queries + db->Execute("ANALYZE;"); + +} + +void ConvertDB0100To0101() +{ + // added unique constraint to public and private key + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;"); + db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;"); + db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\ + LocalIdentityID INTEGER PRIMARY KEY,\ + Name TEXT,\ + PublicKey TEXT UNIQUE,\ + PrivateKey TEXT UNIQUE,\ + SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\ + PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\ + PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\ + InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\ + LastInsertedIdentity DATETIME,\ + InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\ + LastInsertedPuzzle DATETIME,\ + InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\ + LastInsertedTrustList DATETIME,\ + InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\ + LastInsertedBoardList DATETIME,\ + InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\ + LastInsertedMessageList DATETIME\ + );"); + db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;"); + db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;"); +} + +void ConvertDB0101To0103() +{ + // remove default 50 from trust fields and set default to NULL + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;"); + db->Execute("DROP TABLE IF EXISTS tblIdentity;"); + db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\ + IdentityID INTEGER PRIMARY KEY,\ + PublicKey TEXT UNIQUE,\ + Name TEXT,\ + SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\ + PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\ + PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\ + DateAdded DATETIME,\ + LastSeen DATETIME,\ + LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\ + );"); + db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;"); + db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;"); + + // add SaveReceivedMessages field to tblBoard + db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';"); + + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;"); +} + +void ConvertDB0103To0104() +{ + // add MessageIndex to tblMessage + DateTime date; + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;"); + db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);"); + db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;"); + date.SetToGMTime(); + db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;"); +} + +void ConvertDB0104To0105() +{ + // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity + // add MessageTrustComment,TrustListTrustComment to tblPeerTrust + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;"); + db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;"); + db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;"); + db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;"); + db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;"); +} + +void ConvertDB0105To0106() +{ + // add Publish Freesite + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';"); + db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;"); +} + +void ConvertDB0106To0107() +{ + // add AddedMethod to tblBoard + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + db->Execute("ALTER TABLE tblBoard ADD COLUMN AddedMethod TEXT;"); + db->Execute("ALTER TABLE tblIdentity ADD COLUMN Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false';"); + db->Execute("UPDATE tblIdentity SET Hidden='false' WHERE Hidden IS NULL;"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=7;"); +} + +void ConvertDB0107To0108() +{ + // add FreesiteEdition to tblLocalIdentity and tblIdentity + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN FreesiteEdition INTEGER;"); + db->Execute("ALTER TABLE tblIdentity ADD COLUMN FreesiteEdition INTEGER;"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=8;"); +} + +void ConvertDB0108To0109() +{ + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\ + FileInsertID INTEGER PRIMARY KEY,\ + MessageUUID TEXT,\ + FileName TEXT,\ + Key TEXT,\ + Size INTEGER,\ + Data BLOB\ + );"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;"); } void SetupDefaultOptions() @@ -250,7 +632,7 @@ void SetupDefaultOptions() // 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 std::ostringstream tempstr; // must set tempstr to "" between db inserts - SQLite3DB::DB *db=SQLite3DB::DB::instance(); + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);"); // LogLevel @@ -285,20 +667,38 @@ void SetupDefaultOptions() // StartNNTP st.Bind(0,"StartNNTP"); st.Bind(1,"true"); - st.Bind(2,"Start NNTP service."); + st.Bind(2,"Start NNTP server."); + st.Step(); + st.Reset(); + + st.Bind(0,"StartHTTP"); + st.Bind(1,"true"); + st.Bind(2,"Start HTTP server. WARNING: If you turn this off, you won't be able to access the administration pages."); + st.Step(); + st.Reset(); + + st.Bind(0,"HTTPListenPort"); + st.Bind(1,"8080"); + st.Bind(2,"Port HTTP server will listen on."); + st.Step(); + st.Reset(); + + st.Bind(0,"HTTPAccessControl"); + st.Bind(1,"-0.0.0.0/0,+127.0.0.1"); + 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 as host."); st.Step(); st.Reset(); // StartFreenetUpdater st.Bind(0,"StartFreenetUpdater"); st.Bind(1,"true"); - st.Bind(2,"Start Freenet Updater thread."); + st.Bind(2,"Set to true to start the Freenet Updater thread and connect to Freenet. Set to false to prevent communication with Freenet."); st.Step(); st.Reset(); // FCPHost st.Bind(0,"FCPHost"); - st.Bind(1,"localhost"); + st.Bind(1,"127.0.0.1"); st.Bind(2,"Host name or address of Freenet node."); st.Step(); st.Reset(); @@ -358,24 +758,78 @@ void SetupDefaultOptions() st.Step(); st.Reset(); + st.Bind(0,"MinPeerMessageTrust"); + st.Bind(1,"30"); + st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded."); + st.Step(); + st.Reset(); + st.Bind(0,"MinLocalTrustListTrust"); st.Bind(1,"50"); 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."); st.Step(); st.Reset(); + st.Bind(0,"MinPeerTrustListTrust"); + st.Bind(1,"30"); + 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."); + st.Step(); + st.Reset(); + st.Bind(0,"MessageDownloadMaxDaysBackward"); - st.Bind(1,"3"); + st.Bind(1,"5"); st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity"); st.Step(); st.Reset(); st.Bind(0,"MessageListDaysBackward"); - st.Bind(1,"3"); + st.Bind(1,"5"); st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists"); st.Step(); st.Reset(); + st.Bind(0,"MaxPeerMessagesPerDay"); + st.Bind(1,"200"); + st.Bind(2,"The maximum number of messages you will download from each peer on a given day."); + st.Step(); + st.Reset(); + + st.Bind(0,"MaxBoardListRequests"); + st.Bind(1,"5"); + st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable."); + st.Step(); + st.Reset(); + + st.Bind(0,"MaxBoardsPerMessage"); + st.Bind(1,"8"); + st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored."); + st.Step(); + st.Reset(); + + st.Bind(0,"SaveMessagesFromNewBoards"); + st.Bind(1,"true"); + st.Bind(2,"Set to true to automatically save messages posted to new boards. Set to false to ignore messages to new boards."); + st.Step(); + st.Reset(); + + st.Bind(0,"ChangeMessageTrustOnReply"); + st.Bind(1,"0"); + st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages."); + st.Step(); + st.Reset(); + + st.Bind(0,"AddNewPostFromIdentities"); + st.Bind(1,"false"); + 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."); + st.Step(); + st.Reset(); + + st.Bind(0,"DeleteMessagesOlderThan"); + st.Bind(1,"180"); + st.Bind(2,"Automatically delete messages older than this many days."); + st.Step(); + st.Reset(); + } void SetupLogFile() @@ -386,23 +840,23 @@ void SetupLogFile() date.SetToGMTime(); - LogFile::instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log"); - LogFile::instance()->OpenFile(); - LogFile::instance()->SetWriteNewLine(true); - LogFile::instance()->SetWriteDate(true); - LogFile::instance()->SetWriteLogLevel(true); + LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log"); + LogFile::Instance()->OpenFile(); + LogFile::Instance()->SetWriteNewLine(true); + LogFile::Instance()->SetWriteDate(true); + LogFile::Instance()->SetWriteLogLevel(true); - if(Option::instance()->Get("LogLevel",configval)==false) + if(Option::Instance()->Get("LogLevel",configval)==false) { configval="4"; - Option::instance()->Set("LogLevel",configval); + Option::Instance()->Set("LogLevel",configval); } if(StringFunctions::Convert(configval,loglevel)==false) { loglevel=LogFile::LOGLEVEL_DEBUG; - Option::instance()->Set("LogLevel",loglevel); + Option::Instance()->Set("LogLevel",loglevel); } - LogFile::instance()->SetLogLevel((LogFile::LogLevel)loglevel); + LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel); } void SetupNetwork() @@ -413,6 +867,16 @@ void SetupNetwork() #endif } +void Shutdown() +{ + ThreadController::Instance()->ShutdownThreads(); + + ShutdownNetwork(); + + LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown"); + LogFile::Instance()->WriteNewLine(); +} + void ShutdownNetwork() { #ifdef _WIN32 @@ -420,60 +884,72 @@ void ShutdownNetwork() #endif } -void ShutdownThreads(std::vector &threads) +void SigHandler(int signum) { - std::vector::iterator i; - for(i=threads.begin(); i!=threads.end(); i++) - { - if((*i)->wait(1)==false) - { - try - { - (*i)->interrupt(); - } - catch(...) - { - } - } - } - - for(i=threads.begin(); i!=threads.end(); i++) - { - (*i)->wait(); - delete (*i); - } - - threads.clear(); - + Shutdown(); + exit(0); } -void StartThreads(std::vector &threads) +void FixCapitalBoardNames() { - std::string startfreenet; - std::string startnntp; + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); - if(Option::instance()->Get("StartFreenetUpdater",startfreenet)==false) - { - startfreenet="true"; - Option::instance()->Set("StartFreenetUpdater","true"); - } + SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);"); + SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;"); + SQLite3DB::Statement del=db->Prepare("DELETE FROM tblBoard WHERE BoardID=?;"); + SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;"); + SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;"); + SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;"); - if(Option::instance()->Get("StartNNTP",startnntp)==false) + st.Step(); + while(st.RowReturned()) { - startnntp="true"; - Option::instance()->Set("StartNNTP","true"); - } + int boardid=0; + int newboardid=0; + std::string name=""; + std::string lowername=""; + + st.ResultInt(0,boardid); + st.ResultText(1,name); + + lowername=name; + StringFunctions::LowerCase(lowername,lowername); + + if(name!=lowername) + { + st2.Bind(0,lowername); + st2.Step(); - if(startfreenet=="true") - { - ZThread::Thread *t=new ZThread::Thread(new FreenetMasterThread()); - threads.push_back(t); - } + if(st2.RowReturned()) + { + st2.ResultInt(0,newboardid); - if(startnntp=="true") - { - ZThread::Thread *t=new ZThread::Thread(new NNTPListener()); - threads.push_back(t); + upd2.Bind(0,newboardid); + upd2.Bind(1,boardid); + upd2.Step(); + upd2.Reset(); + + upd3.Bind(0,newboardid); + upd3.Bind(1,boardid); + upd3.Step(); + upd3.Reset(); + + del.Bind(0,boardid); + del.Step(); + del.Reset(); + } + else + { + upd.Bind(0,lowername); + upd.Bind(1,boardid); + upd.Step(); + upd.Reset(); + } + + st2.Reset(); + } + + st.Step(); } }