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("DROP TRIGGER IF EXISTS trgDeleteIdentity;");
\r
424 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \
\r
427 DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\
\r
428 DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\
\r
429 DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\
\r
430 DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\
\r
431 DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\
\r
432 DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\
\r
433 DELETE FROM tblIdentityTrust WHERE IdentityID=old.IdentityID;\
\r
436 db->Execute("DROP TRIGGER IF EXISTS trgDeleteLocalIdentity;");
\r
437 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \
\r
440 DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
441 DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
442 DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
443 DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
444 DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
445 DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
446 DELETE FROM tblIdentityTrust WHERE LocalIdentityID=old.LocalIdentityID;\
\r
449 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \
\r
452 DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\
\r
455 // delete introduction puzzles that were half-way inserted
\r
456 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");
\r
458 // delete stale introduction puzzles (2 or more days old)
\r
459 date.SetToGMTime();
\r
460 date.Add(0,0,0,-2);
\r
461 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
462 db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
464 date.SetToGMTime();
\r
465 // insert SomeDude's public key
\r
466 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
467 // insert Shadow Panther's public key
\r
468 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
469 // insert garfield's public key
\r
470 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
472 // TODO remove sometime after 0.1.17
\r
473 FixCapitalBoardNames();
\r
475 // run analyze - may speed up some queries
\r
476 db->Execute("ANALYZE;");
\r
480 void ConvertDB0100To0101()
\r
482 // added unique constraint to public and private key
\r
483 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
484 db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");
\r
485 db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");
\r
486 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
487 LocalIdentityID INTEGER PRIMARY KEY,\
\r
489 PublicKey TEXT UNIQUE,\
\r
490 PrivateKey TEXT UNIQUE,\
\r
491 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
492 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
493 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
494 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
495 LastInsertedIdentity DATETIME,\
\r
496 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
497 LastInsertedPuzzle DATETIME,\
\r
498 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
499 LastInsertedTrustList DATETIME,\
\r
500 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
501 LastInsertedBoardList DATETIME,\
\r
502 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
503 LastInsertedMessageList DATETIME\
\r
505 db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");
\r
506 db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");
\r
507 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");
\r
510 void ConvertDB0101To0103()
\r
512 // remove default 50 from trust fields and set default to NULL
\r
513 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
514 db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");
\r
515 db->Execute("DROP TABLE IF EXISTS tblIdentity;");
\r
516 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
517 IdentityID INTEGER PRIMARY KEY,\
\r
518 PublicKey TEXT UNIQUE,\
\r
520 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
521 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
522 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
523 DateAdded DATETIME,\
\r
524 LastSeen DATETIME,\
\r
525 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
526 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
527 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
528 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\
\r
530 db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");
\r
531 db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");
\r
533 // add SaveReceivedMessages field to tblBoard
\r
534 db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");
\r
536 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");
\r
539 void ConvertDB0103To0104()
\r
541 // add MessageIndex to tblMessage
\r
543 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
544 db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;");
\r
545 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
546 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");
\r
547 date.SetToGMTime();
\r
548 db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");
\r
549 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");
\r
552 void ConvertDB0104To0105()
\r
554 // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity
\r
555 // add MessageTrustComment,TrustListTrustComment to tblPeerTrust
\r
556 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
557 db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;");
\r
558 db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;");
\r
559 db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;");
\r
560 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;");
\r
561 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;");
\r
562 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;");
\r
565 void ConvertDB0105To0106()
\r
567 // add Publish Freesite
\r
568 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
569 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';");
\r
570 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;");
\r
571 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");
\r
574 void ConvertDB0106To0107()
\r
576 // add AddedMethod to tblBoard
\r
577 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
578 db->Execute("ALTER TABLE tblBoard ADD COLUMN AddedMethod TEXT;");
\r
579 db->Execute("ALTER TABLE tblIdentity ADD COLUMN Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false';");
\r
580 db->Execute("UPDATE tblIdentity SET Hidden='false' WHERE Hidden IS NULL;");
\r
581 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=7;");
\r
584 void SetupDefaultOptions()
\r
586 // 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
588 std::ostringstream tempstr; // must set tempstr to "" between db inserts
\r
589 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
590 SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");
\r
594 tempstr << LogFile::LOGLEVEL_DEBUG;
\r
595 st.Bind(0,"LogLevel");
\r
596 st.Bind(1,tempstr.str());
\r
597 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
602 st.Bind(0,"NNTPListenPort");
\r
604 st.Bind(2,"The port that the NNTP service will listen for incoming connections.");
\r
608 // NNTPBindAddresses
\r
609 st.Bind(0,"NNTPBindAddresses");
\r
610 st.Bind(1,"localhost");
\r
611 st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");
\r
615 st.Bind(0,"NNTPAllowPost");
\r
617 st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");
\r
622 st.Bind(0,"StartNNTP");
\r
624 st.Bind(2,"Start NNTP server.");
\r
628 st.Bind(0,"StartHTTP");
\r
630 st.Bind(2,"Start HTTP server. WARNING: If you turn this off, you won't be able to access the administration pages.");
\r
634 st.Bind(0,"HTTPListenPort");
\r
636 st.Bind(2,"Port HTTP server will listen on.");
\r
640 st.Bind(0,"HTTPAccessControl");
\r
641 st.Bind(1,"-0.0.0.0/0,+127.0.0.1");
\r
642 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
646 // StartFreenetUpdater
\r
647 st.Bind(0,"StartFreenetUpdater");
\r
649 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
654 st.Bind(0,"FCPHost");
\r
655 st.Bind(1,"127.0.0.1");
\r
656 st.Bind(2,"Host name or address of Freenet node.");
\r
661 st.Bind(0,"FCPPort");
\r
663 st.Bind(2,"The port that Freenet is listening for FCP connections on.");
\r
667 st.Bind(0,"MessageBase");
\r
669 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
673 st.Bind(0,"MaxIdentityRequests");
\r
675 st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");
\r
679 st.Bind(0,"MaxIdentityIntroductionRequests");
\r
681 st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");
\r
685 st.Bind(0,"MaxIntroductionPuzzleRequests");
\r
687 st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");
\r
691 st.Bind(0,"MaxTrustListRequests");
\r
693 st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");
\r
697 st.Bind(0,"MaxMessageListRequests");
\r
699 st.Bind(2,"Maximum number of concurrent requests for new Message Lists");
\r
703 st.Bind(0,"MaxMessageRequests");
\r
705 st.Bind(2,"Maximum number of concurrent requests for new Messages");
\r
709 st.Bind(0,"MinLocalMessageTrust");
\r
711 st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");
\r
715 st.Bind(0,"MinPeerMessageTrust");
\r
717 st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");
\r
721 st.Bind(0,"MinLocalTrustListTrust");
\r
723 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
727 st.Bind(0,"MinPeerTrustListTrust");
\r
729 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
733 st.Bind(0,"MessageDownloadMaxDaysBackward");
\r
735 st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");
\r
739 st.Bind(0,"MessageListDaysBackward");
\r
741 st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");
\r
745 st.Bind(0,"MaxPeerMessagesPerDay");
\r
747 st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");
\r
751 st.Bind(0,"MaxBoardListRequests");
\r
753 st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");
\r
757 st.Bind(0,"MaxBoardsPerMessage");
\r
759 st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");
\r
763 st.Bind(0,"SaveMessagesFromNewBoards");
\r
765 st.Bind(2,"Set to true to automatically save messages posted to new boards. Set to false to ignore messages to new boards.");
\r
769 st.Bind(0,"ChangeMessageTrustOnReply");
\r
771 st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");
\r
775 st.Bind(0,"AddNewPostFromIdentities");
\r
776 st.Bind(1,"false");
\r
777 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
781 st.Bind(0,"DeleteMessagesOlderThan");
\r
783 st.Bind(2,"Automatically delete messages older than this many days.");
\r
789 void SetupLogFile()
\r
792 std::string configval;
\r
795 date.SetToGMTime();
\r
797 LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");
\r
798 LogFile::Instance()->OpenFile();
\r
799 LogFile::Instance()->SetWriteNewLine(true);
\r
800 LogFile::Instance()->SetWriteDate(true);
\r
801 LogFile::Instance()->SetWriteLogLevel(true);
\r
803 if(Option::Instance()->Get("LogLevel",configval)==false)
\r
806 Option::Instance()->Set("LogLevel",configval);
\r
808 if(StringFunctions::Convert(configval,loglevel)==false)
\r
810 loglevel=LogFile::LOGLEVEL_DEBUG;
\r
811 Option::Instance()->Set("LogLevel",loglevel);
\r
813 LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);
\r
816 void SetupNetwork()
\r
820 WSAStartup(MAKEWORD(2,2),&wsadata);
\r
826 ThreadController::Instance()->ShutdownThreads();
\r
830 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");
\r
831 LogFile::Instance()->WriteNewLine();
\r
834 void ShutdownNetwork()
\r
841 void SigHandler(int signum)
\r
847 void FixCapitalBoardNames()
\r
849 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
851 SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);");
\r
852 SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");
\r
853 SQLite3DB::Statement del=db->Prepare("DELETE FROM tblBoard WHERE BoardID=?;");
\r
854 SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;");
\r
855 SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;");
\r
856 SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;");
\r
859 while(st.RowReturned())
\r
863 std::string name="";
\r
864 std::string lowername="";
\r
866 st.ResultInt(0,boardid);
\r
867 st.ResultText(1,name);
\r
870 StringFunctions::LowerCase(lowername,lowername);
\r
872 if(name!=lowername)
\r
874 st2.Bind(0,lowername);
\r
877 if(st2.RowReturned())
\r
879 st2.ResultInt(0,newboardid);
\r
881 upd2.Bind(0,newboardid);
\r
882 upd2.Bind(1,boardid);
\r
886 upd3.Bind(0,newboardid);
\r
887 upd3.Bind(1,boardid);
\r
891 del.Bind(0,boardid);
\r
897 upd.Bind(0,lowername);
\r
898 upd.Bind(1,boardid);
\r