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
477 void ConvertDB0100To0101()
\r
479 // added unique constraint to public and private key
\r
480 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
481 db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");
\r
482 db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");
\r
483 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
484 LocalIdentityID INTEGER PRIMARY KEY,\
\r
486 PublicKey TEXT UNIQUE,\
\r
487 PrivateKey TEXT UNIQUE,\
\r
488 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
489 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
490 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
491 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
492 LastInsertedIdentity DATETIME,\
\r
493 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
494 LastInsertedPuzzle DATETIME,\
\r
495 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
496 LastInsertedTrustList DATETIME,\
\r
497 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
498 LastInsertedBoardList DATETIME,\
\r
499 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
500 LastInsertedMessageList DATETIME\
\r
502 db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");
\r
503 db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");
\r
504 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");
\r
507 void ConvertDB0101To0103()
\r
509 // remove default 50 from trust fields and set default to NULL
\r
510 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
511 db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");
\r
512 db->Execute("DROP TABLE IF EXISTS tblIdentity;");
\r
513 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
514 IdentityID INTEGER PRIMARY KEY,\
\r
515 PublicKey TEXT UNIQUE,\
\r
517 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
518 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
519 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
520 DateAdded DATETIME,\
\r
521 LastSeen DATETIME,\
\r
522 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
523 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
524 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
525 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\
\r
527 db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");
\r
528 db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");
\r
530 // add SaveReceivedMessages field to tblBoard
\r
531 db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");
\r
533 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");
\r
536 void ConvertDB0103To0104()
\r
538 // add MessageIndex to tblMessage
\r
540 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
541 db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;");
\r
542 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
543 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");
\r
544 date.SetToGMTime();
\r
545 db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");
\r
546 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");
\r
549 void ConvertDB0104To0105()
\r
551 // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity
\r
552 // add MessageTrustComment,TrustListTrustComment to tblPeerTrust
\r
553 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
554 db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;");
\r
555 db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;");
\r
556 db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;");
\r
557 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;");
\r
558 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;");
\r
559 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;");
\r
562 void ConvertDB0105To0106()
\r
564 // add Publish Freesite
\r
565 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
566 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';");
\r
567 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;");
\r
568 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");
\r
571 void ConvertDB0106To0107()
\r
573 // add AddedMethod to tblBoard
\r
574 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
575 db->Execute("ALTER TABLE tblBoard ADD COLUMN AddedMethod TEXT;");
\r
576 db->Execute("ALTER TABLE tblIdentity ADD COLUMN Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false';");
\r
577 db->Execute("UPDATE tblIdentity SET Hidden='false' WHERE Hidden IS NULL;");
\r
578 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=7;");
\r
581 void SetupDefaultOptions()
\r
583 // 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
585 std::ostringstream tempstr; // must set tempstr to "" between db inserts
\r
586 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
587 SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");
\r
591 tempstr << LogFile::LOGLEVEL_DEBUG;
\r
592 st.Bind(0,"LogLevel");
\r
593 st.Bind(1,tempstr.str());
\r
594 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
599 st.Bind(0,"NNTPListenPort");
\r
601 st.Bind(2,"The port that the NNTP service will listen for incoming connections.");
\r
605 // NNTPBindAddresses
\r
606 st.Bind(0,"NNTPBindAddresses");
\r
607 st.Bind(1,"localhost");
\r
608 st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");
\r
612 st.Bind(0,"NNTPAllowPost");
\r
614 st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");
\r
619 st.Bind(0,"StartNNTP");
\r
621 st.Bind(2,"Start NNTP server.");
\r
625 st.Bind(0,"StartHTTP");
\r
627 st.Bind(2,"Start HTTP server. WARNING: If you turn this off, you won't be able to access the administration pages.");
\r
631 st.Bind(0,"HTTPListenPort");
\r
633 st.Bind(2,"Port HTTP server will listen on.");
\r
637 st.Bind(0,"HTTPAccessControl");
\r
638 st.Bind(1,"-0.0.0.0/0,+127.0.0.1");
\r
639 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
643 // StartFreenetUpdater
\r
644 st.Bind(0,"StartFreenetUpdater");
\r
646 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
651 st.Bind(0,"FCPHost");
\r
652 st.Bind(1,"127.0.0.1");
\r
653 st.Bind(2,"Host name or address of Freenet node.");
\r
658 st.Bind(0,"FCPPort");
\r
660 st.Bind(2,"The port that Freenet is listening for FCP connections on.");
\r
664 st.Bind(0,"MessageBase");
\r
666 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
670 st.Bind(0,"MaxIdentityRequests");
\r
672 st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");
\r
676 st.Bind(0,"MaxIdentityIntroductionRequests");
\r
678 st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");
\r
682 st.Bind(0,"MaxIntroductionPuzzleRequests");
\r
684 st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");
\r
688 st.Bind(0,"MaxTrustListRequests");
\r
690 st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");
\r
694 st.Bind(0,"MaxMessageListRequests");
\r
696 st.Bind(2,"Maximum number of concurrent requests for new Message Lists");
\r
700 st.Bind(0,"MaxMessageRequests");
\r
702 st.Bind(2,"Maximum number of concurrent requests for new Messages");
\r
706 st.Bind(0,"MinLocalMessageTrust");
\r
708 st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");
\r
712 st.Bind(0,"MinPeerMessageTrust");
\r
714 st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");
\r
718 st.Bind(0,"MinLocalTrustListTrust");
\r
720 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
724 st.Bind(0,"MinPeerTrustListTrust");
\r
726 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
730 st.Bind(0,"MessageDownloadMaxDaysBackward");
\r
732 st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");
\r
736 st.Bind(0,"MessageListDaysBackward");
\r
738 st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");
\r
742 st.Bind(0,"MaxPeerMessagesPerDay");
\r
744 st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");
\r
748 st.Bind(0,"MaxBoardListRequests");
\r
750 st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");
\r
754 st.Bind(0,"MaxBoardsPerMessage");
\r
756 st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");
\r
760 st.Bind(0,"SaveMessagesFromNewBoards");
\r
762 st.Bind(2,"Set to true to automatically save messages posted to new boards. Set to false to ignore messages to new boards.");
\r
766 st.Bind(0,"ChangeMessageTrustOnReply");
\r
768 st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");
\r
772 st.Bind(0,"AddNewPostFromIdentities");
\r
773 st.Bind(1,"false");
\r
774 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
778 st.Bind(0,"DeleteMessagesOlderThan");
\r
780 st.Bind(2,"Automatically delete messages older than this many days.");
\r
786 void SetupLogFile()
\r
789 std::string configval;
\r
792 date.SetToGMTime();
\r
794 LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");
\r
795 LogFile::Instance()->OpenFile();
\r
796 LogFile::Instance()->SetWriteNewLine(true);
\r
797 LogFile::Instance()->SetWriteDate(true);
\r
798 LogFile::Instance()->SetWriteLogLevel(true);
\r
800 if(Option::Instance()->Get("LogLevel",configval)==false)
\r
803 Option::Instance()->Set("LogLevel",configval);
\r
805 if(StringFunctions::Convert(configval,loglevel)==false)
\r
807 loglevel=LogFile::LOGLEVEL_DEBUG;
\r
808 Option::Instance()->Set("LogLevel",loglevel);
\r
810 LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);
\r
813 void SetupNetwork()
\r
817 WSAStartup(MAKEWORD(2,2),&wsadata);
\r
823 ThreadController::Instance()->ShutdownThreads();
\r
827 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");
\r
828 LogFile::Instance()->WriteNewLine();
\r
831 void ShutdownNetwork()
\r
838 void SigHandler(int signum)
\r
844 void FixCapitalBoardNames()
\r
846 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
848 SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);");
\r
849 SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");
\r
850 SQLite3DB::Statement del=db->Prepare("DELETE FROM tblBoard WHERE BoardID=?;");
\r
851 SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;");
\r
852 SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;");
\r
853 SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;");
\r
856 while(st.RowReturned())
\r
860 std::string name="";
\r
861 std::string lowername="";
\r
863 st.ResultInt(0,boardid);
\r
864 st.ResultText(1,name);
\r
867 StringFunctions::LowerCase(lowername,lowername);
\r
869 if(name!=lowername)
\r
871 st2.Bind(0,lowername);
\r
874 if(st2.RowReturned())
\r
876 st2.ResultInt(0,newboardid);
\r
878 upd2.Bind(0,newboardid);
\r
879 upd2.Bind(1,boardid);
\r
883 upd3.Bind(0,newboardid);
\r
884 upd3.Bind(1,boardid);
\r
888 del.Bind(0,boardid);
\r
894 upd.Bind(0,lowername);
\r
895 upd.Bind(1,boardid);
\r