1 #include "../include/global.h"
\r
2 #include "../include/datetime.h"
\r
3 #include "../include/logfile.h"
\r
4 #include "../include/option.h"
\r
5 #include "../include/stringfunctions.h"
\r
6 #include "../include/db/sqlite3db.h"
\r
7 #include "../include/freenet/freenetmasterthread.h"
\r
8 #include "../include/nntp/nntplistener.h"
\r
9 #include "../include/http/httpthread.h"
\r
10 #include "../include/threadcontroller.h"
\r
13 #include <winsock2.h>
\r
20 bool wantshutdown=false;
\r
22 std::string CreateShortIdentityName(const std::string &name, const std::string &publickey)
\r
24 std::string result="";
\r
25 std::vector<std::string> keyparts;
\r
27 StringFunctions::SplitMultiple(publickey,"@,",keyparts);
\r
30 if(keyparts.size()>1 && keyparts[1].size()>8)
\r
32 result+="@"+keyparts[1].substr(0,4)+"...";
\r
42 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
44 db->Open("fms.db3");
\r
45 db->SetBusyTimeout(10000); // set timeout to 10 seconds
\r
46 //db->Execute("VACUUM;"); // not needed every startup
\r
48 db->Execute("CREATE TABLE IF NOT EXISTS tblDBVersion(\
\r
53 SQLite3DB::Statement st=db->Prepare("SELECT Major,Minor FROM tblDBVersion;");
\r
55 if(st.RowReturned())
\r
59 st.ResultInt(0,major);
\r
60 st.ResultInt(1,minor);
\r
62 if(major==1 && minor==0)
\r
64 ConvertDB0100To0101();
\r
68 if(major==1 && (minor==1 || minor==2))
\r
70 ConvertDB0101To0103();
\r
74 if(major==1 && minor==3)
\r
76 ConvertDB0103To0104();
\r
80 if(major==1 && minor==4)
\r
82 ConvertDB0104To0105();
\r
86 if(major==1 && minor==5)
\r
88 ConvertDB0105To0106();
\r
92 if(major==1 && minor==6)
\r
94 ConvertDB0106To0107();
\r
101 db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,7);");
\r
104 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=7;");
\r
106 db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\
\r
107 Option TEXT UNIQUE,\
\r
108 OptionValue TEXT NOT NULL,\
\r
109 OptionDescription TEXT\
\r
112 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
113 LocalIdentityID INTEGER PRIMARY KEY,\
\r
115 PublicKey TEXT UNIQUE,\
\r
116 PrivateKey TEXT UNIQUE,\
\r
117 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
118 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
119 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
120 PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\
\r
121 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
122 LastInsertedIdentity DATETIME,\
\r
123 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
124 LastInsertedPuzzle DATETIME,\
\r
125 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
126 LastInsertedTrustList DATETIME,\
\r
127 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
128 LastInsertedBoardList DATETIME,\
\r
129 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
130 LastInsertedMessageList DATETIME,\
\r
131 LastInsertedFreesite DATETIME,\
\r
132 DateCreated DATETIME\
\r
135 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\
\r
136 LocalIdentityID INTEGER,\
\r
138 InsertIndex INTEGER\
\r
141 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\
\r
142 LocalIdentityID INTEGER,\
\r
144 InsertIndex INTEGER\
\r
147 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\
\r
148 IdentityID INTEGER,\
\r
150 RequestIndex INTEGER,\
\r
151 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
154 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\
\r
156 LocalIdentityID INTEGER,\
\r
158 InsertIndex INTEGER,\
\r
162 PuzzleSolution TEXT,\
\r
163 FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\
\r
166 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
167 IdentityID INTEGER PRIMARY KEY,\
\r
168 PublicKey TEXT UNIQUE,\
\r
170 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
171 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
172 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
173 DateAdded DATETIME,\
\r
174 LastSeen DATETIME,\
\r
175 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
176 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
177 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
178 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
180 MessageTrustComment TEXT,\
\r
181 TrustListTrustComment TEXT,\
\r
182 Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false'\
\r
185 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\
\r
186 IdentityID INTEGER,\
\r
188 RequestIndex INTEGER,\
\r
189 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
192 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\
\r
193 IdentityID INTEGER,\
\r
195 RequestIndex INTEGER,\
\r
196 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\
\r
203 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\
\r
204 LocalIdentityID INTEGER,\
\r
208 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
211 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityTrust(\
\r
212 LocalIdentityID INTEGER,\
\r
213 IdentityID INTEGER,\
\r
214 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
215 MessageTrustComment TEXT,\
\r
216 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
217 TrustListTrustComment TEXT\
\r
220 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxIdentityTrust_IDs ON tblIdentityTrust(LocalIdentityID,IdentityID);");
\r
222 db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOnIdentityTrust AFTER INSERT ON tblIdentityTrust \
\r
225 UPDATE tblIdentity SET LocalMessageTrust=(SELECT MAX(LocalMessageTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID), LocalTrustListTrust=(SELECT MAX(LocalTrustListTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID) WHERE tblIdentity.IdentityID=new.IdentityID; \
\r
228 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOnIdentityTrust AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentityTrust \
\r
231 UPDATE tblIdentity SET LocalMessageTrust=(SELECT MAX(LocalMessageTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID), LocalTrustListTrust=(SELECT MAX(LocalTrustListTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=new.IdentityID GROUP BY tblIdentityTrust.IdentityID) WHERE tblIdentity.IdentityID=new.IdentityID; \
\r
234 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOnIdentityTrust AFTER DELETE ON tblIdentityTrust \
\r
237 UPDATE tblIdentity SET LocalMessageTrust=(SELECT MAX(LocalMessageTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=old.IdentityID GROUP BY tblIdentityTrust.IdentityID), LocalTrustListTrust=(SELECT MAX(LocalTrustListTrust) FROM tblIdentityTrust WHERE tblIdentityTrust.IdentityID=old.IdentityID GROUP BY tblIdentityTrust.IdentityID) WHERE tblIdentity.IdentityID=old.IdentityID; \
\r
240 db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\
\r
241 IdentityID INTEGER,\
\r
242 TargetIdentityID INTEGER,\
\r
243 MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\
\r
244 TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100),\
\r
245 MessageTrustComment TEXT,\
\r
246 TrustListTrustComment TEXT\
\r
249 db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_IdentityID ON tblPeerTrust (IdentityID);");
\r
250 db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_TargetIdentityID ON tblPeerTrust (TargetIdentityID);");
\r
252 db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\
\r
253 BoardID INTEGER PRIMARY KEY,\
\r
254 BoardName TEXT UNIQUE,\
\r
255 BoardDescription TEXT,\
\r
256 DateAdded DATETIME,\
\r
257 SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true',\
\r
261 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('fms','Freenet Message System','2007-12-01 12:00:00','Initial Board');");
\r
262 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00','Initialt Board');");
\r
263 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('public','Public discussion','2007-12-01 12:00:00','Initial Board');");
\r
264 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('test','Test board','2007-12-01 12:00:00','Initial Board');");
\r
266 db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\
\r
267 MessageID INTEGER PRIMARY KEY,\
\r
268 IdentityID INTEGER,\
\r
273 MessageUUID TEXT UNIQUE,\
\r
274 ReplyBoardID INTEGER,\
\r
276 MessageIndex INTEGER\
\r
279 db->Execute("CREATE INDEX IF NOT EXISTS idxMessage_IdentityID ON tblMessage (IdentityID);");
\r
281 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\
\r
282 MessageID INTEGER,\
\r
283 ReplyToMessageUUID TEXT,\
\r
284 ReplyOrder INTEGER\
\r
287 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageReplyTo_MessageID ON tblMessageReplyTo (MessageID);");
\r
289 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\
\r
290 MessageID INTEGER,\
\r
294 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_MessageID ON tblMessageBoard (MessageID);");
\r
295 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_BoardID ON tblMessageBoard (BoardID);");
\r
297 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\
\r
298 IdentityID INTEGER,\
\r
300 RequestIndex INTEGER,\
\r
301 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
304 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\
\r
305 IdentityID INTEGER,\
\r
307 RequestIndex INTEGER,\
\r
308 FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\
\r
309 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
312 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
314 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\
\r
315 LocalIdentityID INTEGER,\
\r
317 InsertIndex INTEGER,\
\r
318 MessageUUID TEXT UNIQUE,\
\r
320 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
323 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\
\r
324 LocalIdentityID INTEGER,\
\r
326 InsertIndex INTEGER,\
\r
327 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
330 db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\
\r
331 BoardID INTEGER UNIQUE,\
\r
332 ModifyLocalMessageTrust INTEGER,\
\r
333 ModifyLocalTrustListTrust INTEGER\
\r
336 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\
\r
337 LocalIdentityID INTEGER,\
\r
339 InsertIndex INTEGER,\
\r
340 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
343 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\
\r
344 IdentityID INTEGER,\
\r
346 RequestIndex INTEGER,\
\r
347 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
350 // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed
\r
351 db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\
\r
352 LocalIdentityID INTEGER,\
\r
356 // low / high / message count for each board
\r
357 db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \
\r
358 SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \
\r
359 FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \
\r
360 WHERE MessageID>=0 OR MessageID IS NULL \
\r
361 GROUP BY tblBoard.BoardID;");
\r
363 // calculates peer trust
\r
364 // do the (MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1)/100.0 - so if MessageTrust or TrustListTrust is NULL, the calc will be NULL and it won't be included at all in the average
\r
365 // need the +1 so that when the values are 0 the result is not 0
\r
366 db->Execute("DROP VIEW IF EXISTS vwCalculatedPeerTrust;");
\r
367 db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \
\r
368 SELECT TargetIdentityID, \
\r
369 ROUND(SUM(MessageTrust*(LocalTrustListTrust/100.0))/SUM(((MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1))/100.0),0) AS 'PeerMessageTrust', \
\r
370 ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(((TrustListTrust+1)*LocalTrustListTrust/(TrustListTrust+1))/100.0),0) AS 'PeerTrustListTrust' \
\r
371 FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \
\r
372 WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \
\r
373 AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \
\r
374 GROUP BY TargetIdentityID;");
\r
377 These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed
\r
378 All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class
\r
380 // drop existing triggers
\r
381 db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");
\r
382 db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");
\r
383 db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");
\r
384 db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");
\r
386 // update PeerTrustLevel when deleting a record from tblPeerTrust
\r
387 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \
\r
390 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID) WHERE IdentityID=old.TargetIdentityID;\
\r
393 // update PeerTrustLevel when inserting a record into tblPeerTrust
\r
394 db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \
\r
397 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID) WHERE IdentityID=new.TargetIdentityID;\
\r
400 // update PeerTrustLevel when updating a record in tblPeerTrust
\r
401 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \
\r
404 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID) WHERE IdentityID=old.TargetIdentityID;\
\r
405 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID) WHERE IdentityID=new.TargetIdentityID;\
\r
408 // recalculate all Peer TrustLevels when updating Local TrustLevels on tblIdentity - doesn't really need to be all, but rather all identities the updated identity has a trust level for. It's easier to update everyone for now.
\r
409 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \
\r
412 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\
\r
416 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \
\r
419 DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\
\r
420 DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\
\r
423 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \
\r
426 DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\
\r
427 DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\
\r
428 DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\
\r
429 DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\
\r
430 DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\
\r
431 DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\
\r
434 db->Execute("DROP TRIGGER IF EXISTS trgDeleteLocalIdentity;");
\r
435 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \
\r
438 DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
439 DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
440 DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
441 DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
442 DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
443 DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
444 DELETE FROM tblIdentityTrust WHERE LocalIdentityID=old.LocalIdentityID;\
\r
447 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \
\r
450 DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\
\r
453 // delete introduction puzzles that were half-way inserted
\r
454 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");
\r
456 // delete stale introduction puzzles (2 or more days old)
\r
457 date.SetToGMTime();
\r
458 date.Add(0,0,0,-2);
\r
459 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
460 db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
462 date.SetToGMTime();
\r
463 // insert SomeDude's public key
\r
464 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,LocalTrustListTrust,AddedMethod) VALUES('SSK@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw,iXez4j3qCpd596TxXiJgZyTq9o-CElEuJxm~jNNZAuA,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"',50,'Initial Identity');");
\r
465 // insert Shadow Panther's public key
\r
466 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");
\r
467 // insert garfield's public key
\r
468 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");
\r
470 // TODO remove sometime after 0.1.17
\r
471 FixCapitalBoardNames();
\r
475 void ConvertDB0100To0101()
\r
477 // added unique constraint to public and private key
\r
478 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
479 db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");
\r
480 db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");
\r
481 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
482 LocalIdentityID INTEGER PRIMARY KEY,\
\r
484 PublicKey TEXT UNIQUE,\
\r
485 PrivateKey TEXT UNIQUE,\
\r
486 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
487 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
488 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
489 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
490 LastInsertedIdentity DATETIME,\
\r
491 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
492 LastInsertedPuzzle DATETIME,\
\r
493 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
494 LastInsertedTrustList DATETIME,\
\r
495 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
496 LastInsertedBoardList DATETIME,\
\r
497 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
498 LastInsertedMessageList DATETIME\
\r
500 db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");
\r
501 db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");
\r
502 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");
\r
505 void ConvertDB0101To0103()
\r
507 // remove default 50 from trust fields and set default to NULL
\r
508 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
509 db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");
\r
510 db->Execute("DROP TABLE IF EXISTS tblIdentity;");
\r
511 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
512 IdentityID INTEGER PRIMARY KEY,\
\r
513 PublicKey TEXT UNIQUE,\
\r
515 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
516 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
517 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
518 DateAdded DATETIME,\
\r
519 LastSeen DATETIME,\
\r
520 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
521 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
522 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
523 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\
\r
525 db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");
\r
526 db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");
\r
528 // add SaveReceivedMessages field to tblBoard
\r
529 db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");
\r
531 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");
\r
534 void ConvertDB0103To0104()
\r
536 // add MessageIndex to tblMessage
\r
538 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
539 db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;");
\r
540 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
541 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");
\r
542 date.SetToGMTime();
\r
543 db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");
\r
544 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");
\r
547 void ConvertDB0104To0105()
\r
549 // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity
\r
550 // add MessageTrustComment,TrustListTrustComment to tblPeerTrust
\r
551 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
552 db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;");
\r
553 db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;");
\r
554 db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;");
\r
555 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;");
\r
556 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;");
\r
557 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;");
\r
560 void ConvertDB0105To0106()
\r
562 // add Publish Freesite
\r
563 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
564 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';");
\r
565 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;");
\r
566 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");
\r
569 void ConvertDB0106To0107()
\r
571 // add AddedMethod to tblBoard
\r
572 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
573 db->Execute("ALTER TABLE tblBoard ADD COLUMN AddedMethod TEXT;");
\r
574 db->Execute("ALTER TABLE tblIdentity ADD COLUMN Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false';");
\r
575 db->Execute("UPDATE tblIdentity SET Hidden='false' WHERE Hidden IS NULL;");
\r
576 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=7;");
\r
579 void SetupDefaultOptions()
\r
581 // 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
583 std::ostringstream tempstr; // must set tempstr to "" between db inserts
\r
584 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
585 SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");
\r
589 tempstr << LogFile::LOGLEVEL_DEBUG;
\r
590 st.Bind(0,"LogLevel");
\r
591 st.Bind(1,tempstr.str());
\r
592 st.Bind(2,"The maximum logging level that will be written to file. 0=Fatal Errors, 1=Errors, 2=Warnings, 3=Informational Messages, 4=Debug Messages. Higher levels will include all messages from the previous levels.");
\r
597 st.Bind(0,"NNTPListenPort");
\r
599 st.Bind(2,"The port that the NNTP service will listen for incoming connections.");
\r
603 // NNTPBindAddresses
\r
604 st.Bind(0,"NNTPBindAddresses");
\r
605 st.Bind(1,"localhost");
\r
606 st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");
\r
610 st.Bind(0,"NNTPAllowPost");
\r
612 st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");
\r
617 st.Bind(0,"StartNNTP");
\r
619 st.Bind(2,"Start NNTP server.");
\r
623 st.Bind(0,"StartHTTP");
\r
625 st.Bind(2,"Start HTTP server. WARNING: If you turn this off, you won't be able to access the administration pages.");
\r
629 st.Bind(0,"HTTPListenPort");
\r
631 st.Bind(2,"Port HTTP server will listen on.");
\r
635 st.Bind(0,"HTTPAccessControl");
\r
636 st.Bind(1,"-0.0.0.0/0,+127.0.0.1");
\r
637 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.");
\r
641 // StartFreenetUpdater
\r
642 st.Bind(0,"StartFreenetUpdater");
\r
644 st.Bind(2,"Set to true to start the Freenet Updater thread and connect to Freenet. Set to false to prevent communication with Freenet.");
\r
649 st.Bind(0,"FCPHost");
\r
650 st.Bind(1,"127.0.0.1");
\r
651 st.Bind(2,"Host name or address of Freenet node.");
\r
656 st.Bind(0,"FCPPort");
\r
658 st.Bind(2,"The port that Freenet is listening for FCP connections on.");
\r
662 st.Bind(0,"MessageBase");
\r
664 st.Bind(2,"A unique string shared by all clients who want to communicate with each other. This should not be changed unless you want to create your own separate communications network.");
\r
668 st.Bind(0,"MaxIdentityRequests");
\r
670 st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");
\r
674 st.Bind(0,"MaxIdentityIntroductionRequests");
\r
676 st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");
\r
680 st.Bind(0,"MaxIntroductionPuzzleRequests");
\r
682 st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");
\r
686 st.Bind(0,"MaxTrustListRequests");
\r
688 st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");
\r
692 st.Bind(0,"MaxMessageListRequests");
\r
694 st.Bind(2,"Maximum number of concurrent requests for new Message Lists");
\r
698 st.Bind(0,"MaxMessageRequests");
\r
700 st.Bind(2,"Maximum number of concurrent requests for new Messages");
\r
704 st.Bind(0,"MinLocalMessageTrust");
\r
706 st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");
\r
710 st.Bind(0,"MinPeerMessageTrust");
\r
712 st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");
\r
716 st.Bind(0,"MinLocalTrustListTrust");
\r
718 st.Bind(2,"Specifies a local trust list trust level that a peer must have before its trust list will be included in the weighted average. Any peers below this number will be excluded from the results.");
\r
722 st.Bind(0,"MinPeerTrustListTrust");
\r
724 st.Bind(2,"Specifies a peer trust list trust level that a peer must have before its trust list will be included in the weighted average. Any peers below this number will be excluded from the results.");
\r
728 st.Bind(0,"MessageDownloadMaxDaysBackward");
\r
730 st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");
\r
734 st.Bind(0,"MessageListDaysBackward");
\r
736 st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");
\r
740 st.Bind(0,"MaxPeerMessagesPerDay");
\r
742 st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");
\r
746 st.Bind(0,"MaxBoardListRequests");
\r
748 st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");
\r
752 st.Bind(0,"MaxBoardsPerMessage");
\r
754 st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");
\r
758 st.Bind(0,"SaveMessagesFromNewBoards");
\r
760 st.Bind(2,"Set to true to automatically save messages posted to new boards. Set to false to ignore messages to new boards.");
\r
764 st.Bind(0,"ChangeMessageTrustOnReply");
\r
766 st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");
\r
770 st.Bind(0,"AddNewPostFromIdentities");
\r
771 st.Bind(1,"false");
\r
772 st.Bind(2,"Set to true to automatically create new identities when you send a message using a new name. If you set this to false, posting messages will fail until you manually create the identity.");
\r
776 st.Bind(0,"DeleteMessagesOlderThan");
\r
778 st.Bind(2,"Automatically delete messages older than this many days.");
\r
784 void SetupLogFile()
\r
787 std::string configval;
\r
790 date.SetToGMTime();
\r
792 LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");
\r
793 LogFile::Instance()->OpenFile();
\r
794 LogFile::Instance()->SetWriteNewLine(true);
\r
795 LogFile::Instance()->SetWriteDate(true);
\r
796 LogFile::Instance()->SetWriteLogLevel(true);
\r
798 if(Option::Instance()->Get("LogLevel",configval)==false)
\r
801 Option::Instance()->Set("LogLevel",configval);
\r
803 if(StringFunctions::Convert(configval,loglevel)==false)
\r
805 loglevel=LogFile::LOGLEVEL_DEBUG;
\r
806 Option::Instance()->Set("LogLevel",loglevel);
\r
808 LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);
\r
811 void SetupNetwork()
\r
815 WSAStartup(MAKEWORD(2,2),&wsadata);
\r
821 ThreadController::Instance()->ShutdownThreads();
\r
825 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");
\r
826 LogFile::Instance()->WriteNewLine();
\r
829 void ShutdownNetwork()
\r
836 void SigHandler(int signum)
\r
842 void FixCapitalBoardNames()
\r
844 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
846 SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);");
\r
847 SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");
\r
848 SQLite3DB::Statement del=db->Prepare("DELETE FROM tblBoard WHERE BoardID=?;");
\r
849 SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;");
\r
850 SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;");
\r
851 SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;");
\r
854 while(st.RowReturned())
\r
858 std::string name="";
\r
859 std::string lowername="";
\r
861 st.ResultInt(0,boardid);
\r
862 st.ResultText(1,name);
\r
865 StringFunctions::LowerCase(lowername,lowername);
\r
867 if(name!=lowername)
\r
869 st2.Bind(0,lowername);
\r
872 if(st2.RowReturned())
\r
874 st2.ResultInt(0,newboardid);
\r
876 upd2.Bind(0,newboardid);
\r
877 upd2.Bind(1,boardid);
\r
881 upd3.Bind(0,newboardid);
\r
882 upd3.Bind(1,boardid);
\r
886 del.Bind(0,boardid);
\r
892 upd.Bind(0,lowername);
\r
893 upd.Bind(1,boardid);
\r