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
98 if(major==1 && minor==7)
\r
100 ConvertDB0107To0108();
\r
104 if(major==1 && minor==8)
\r
106 ConvertDB0108To0109();
\r
113 db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,9);");
\r
116 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;");
\r
118 db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\
\r
119 Option TEXT UNIQUE,\
\r
120 OptionValue TEXT NOT NULL,\
\r
121 OptionDescription TEXT\
\r
124 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
125 LocalIdentityID INTEGER PRIMARY KEY,\
\r
127 PublicKey TEXT UNIQUE,\
\r
128 PrivateKey TEXT UNIQUE,\
\r
129 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
130 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
131 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
132 PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\
\r
133 FreesiteEdition INTEGER,\
\r
134 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
135 LastInsertedIdentity DATETIME,\
\r
136 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
137 LastInsertedPuzzle DATETIME,\
\r
138 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
139 LastInsertedTrustList DATETIME,\
\r
140 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
141 LastInsertedBoardList DATETIME,\
\r
142 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
143 LastInsertedMessageList DATETIME,\
\r
144 LastInsertedFreesite DATETIME,\
\r
145 DateCreated DATETIME\
\r
148 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\
\r
149 LocalIdentityID INTEGER,\
\r
151 InsertIndex INTEGER\
\r
154 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\
\r
155 LocalIdentityID INTEGER,\
\r
157 InsertIndex INTEGER\
\r
160 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\
\r
161 IdentityID INTEGER,\
\r
163 RequestIndex INTEGER,\
\r
164 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
167 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\
\r
169 LocalIdentityID INTEGER,\
\r
171 InsertIndex INTEGER,\
\r
175 PuzzleSolution TEXT,\
\r
176 FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\
\r
179 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
180 IdentityID INTEGER PRIMARY KEY,\
\r
181 PublicKey TEXT UNIQUE,\
\r
183 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
184 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
185 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
186 FreesiteEdition INTEGER,\
\r
187 DateAdded DATETIME,\
\r
188 LastSeen DATETIME,\
\r
189 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
190 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
191 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
192 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
194 MessageTrustComment TEXT,\
\r
195 TrustListTrustComment TEXT,\
\r
196 Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false'\
\r
199 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\
\r
200 IdentityID INTEGER,\
\r
202 RequestIndex INTEGER,\
\r
203 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
206 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\
\r
207 IdentityID INTEGER,\
\r
209 RequestIndex INTEGER,\
\r
210 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\
\r
217 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\
\r
218 LocalIdentityID INTEGER,\
\r
222 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
225 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityTrust(\
\r
226 LocalIdentityID INTEGER,\
\r
227 IdentityID INTEGER,\
\r
228 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
229 MessageTrustComment TEXT,\
\r
230 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
231 TrustListTrustComment TEXT\
\r
234 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxIdentityTrust_IDs ON tblIdentityTrust(LocalIdentityID,IdentityID);");
\r
236 db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOnIdentityTrust AFTER INSERT ON tblIdentityTrust \
\r
239 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
242 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOnIdentityTrust AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentityTrust \
\r
245 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
248 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOnIdentityTrust AFTER DELETE ON tblIdentityTrust \
\r
251 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
254 db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\
\r
255 IdentityID INTEGER,\
\r
256 TargetIdentityID INTEGER,\
\r
257 MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\
\r
258 TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100),\
\r
259 MessageTrustComment TEXT,\
\r
260 TrustListTrustComment TEXT\
\r
263 db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_IdentityID ON tblPeerTrust (IdentityID);");
\r
264 db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_TargetIdentityID ON tblPeerTrust (TargetIdentityID);");
\r
266 db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\
\r
267 BoardID INTEGER PRIMARY KEY,\
\r
268 BoardName TEXT UNIQUE,\
\r
269 BoardDescription TEXT,\
\r
270 DateAdded DATETIME,\
\r
271 SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true',\
\r
275 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('fms','Freenet Message System','2007-12-01 12:00:00','Initial Board');");
\r
276 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00','Initialt Board');");
\r
277 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('public','Public discussion','2007-12-01 12:00:00','Initial Board');");
\r
278 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('test','Test board','2007-12-01 12:00:00','Initial Board');");
\r
280 db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\
\r
281 MessageID INTEGER PRIMARY KEY,\
\r
282 IdentityID INTEGER,\
\r
287 MessageUUID TEXT UNIQUE,\
\r
288 ReplyBoardID INTEGER,\
\r
290 MessageIndex INTEGER\
\r
293 db->Execute("CREATE INDEX IF NOT EXISTS idxMessage_IdentityID ON tblMessage (IdentityID);");
\r
295 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\
\r
296 MessageID INTEGER,\
\r
297 ReplyToMessageUUID TEXT,\
\r
298 ReplyOrder INTEGER\
\r
301 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageReplyTo_MessageID ON tblMessageReplyTo (MessageID);");
\r
303 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\
\r
304 MessageID INTEGER,\
\r
308 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_MessageID ON tblMessageBoard (MessageID);");
\r
309 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_BoardID ON tblMessageBoard (BoardID);");
\r
311 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\
\r
312 IdentityID INTEGER,\
\r
314 RequestIndex INTEGER,\
\r
315 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
318 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\
\r
319 IdentityID INTEGER,\
\r
321 RequestIndex INTEGER,\
\r
322 FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\
\r
323 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
326 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
328 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\
\r
329 LocalIdentityID INTEGER,\
\r
331 InsertIndex INTEGER,\
\r
332 MessageUUID TEXT UNIQUE,\
\r
334 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
337 db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\
\r
338 FileInsertID INTEGER PRIMARY KEY,\
\r
346 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\
\r
347 LocalIdentityID INTEGER,\
\r
349 InsertIndex INTEGER,\
\r
350 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
353 db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\
\r
354 BoardID INTEGER UNIQUE,\
\r
355 ModifyLocalMessageTrust INTEGER,\
\r
356 ModifyLocalTrustListTrust INTEGER\
\r
359 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\
\r
360 LocalIdentityID INTEGER,\
\r
362 InsertIndex INTEGER,\
\r
363 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
366 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\
\r
367 IdentityID INTEGER,\
\r
369 RequestIndex INTEGER,\
\r
370 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
373 // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed
\r
374 db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\
\r
375 LocalIdentityID INTEGER,\
\r
379 // low / high / message count for each board
\r
380 db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \
\r
381 SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \
\r
382 FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \
\r
383 WHERE MessageID>=0 OR MessageID IS NULL \
\r
384 GROUP BY tblBoard.BoardID;");
\r
386 // calculates peer trust
\r
387 // 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
388 // need the +1 so that when the values are 0 the result is not 0
\r
389 db->Execute("DROP VIEW IF EXISTS vwCalculatedPeerTrust;");
\r
390 db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \
\r
391 SELECT TargetIdentityID, \
\r
392 ROUND(SUM(MessageTrust*(LocalTrustListTrust/100.0))/SUM(((MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1))/100.0),0) AS 'PeerMessageTrust', \
\r
393 ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(((TrustListTrust+1)*LocalTrustListTrust/(TrustListTrust+1))/100.0),0) AS 'PeerTrustListTrust' \
\r
394 FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \
\r
395 WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \
\r
396 AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \
\r
397 GROUP BY TargetIdentityID;");
\r
400 These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed
\r
401 All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class
\r
403 // drop existing triggers
\r
404 db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");
\r
405 db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");
\r
406 db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");
\r
407 db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");
\r
409 // update PeerTrustLevel when deleting a record from tblPeerTrust
\r
410 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \
\r
413 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
416 // update PeerTrustLevel when inserting a record into tblPeerTrust
\r
417 db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \
\r
420 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
423 // update PeerTrustLevel when updating a record in tblPeerTrust
\r
424 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \
\r
427 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
428 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
431 // 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
432 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \
\r
435 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\
\r
439 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \
\r
442 DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\
\r
443 DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\
\r
446 db->Execute("DROP TRIGGER IF EXISTS trgDeleteIdentity;");
\r
447 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \
\r
450 DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\
\r
451 DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\
\r
452 DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\
\r
453 DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\
\r
454 DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\
\r
455 DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\
\r
456 DELETE FROM tblIdentityTrust WHERE IdentityID=old.IdentityID;\
\r
459 db->Execute("DROP TRIGGER IF EXISTS trgDeleteLocalIdentity;");
\r
460 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \
\r
463 DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
464 DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
465 DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
466 DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
467 DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
468 DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
469 DELETE FROM tblIdentityTrust WHERE LocalIdentityID=old.LocalIdentityID;\
\r
472 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \
\r
475 DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\
\r
478 // delete introduction puzzles that were half-way inserted
\r
479 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");
\r
481 // delete stale introduction puzzles (2 or more days old)
\r
482 date.SetToGMTime();
\r
483 date.Add(0,0,0,-2);
\r
484 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
485 db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
487 date.SetToGMTime();
\r
488 // insert SomeDude's public key
\r
489 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
490 // insert Shadow Panther's public key
\r
491 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
492 // insert garfield's public key
\r
493 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
495 // TODO remove sometime after 0.1.17
\r
496 FixCapitalBoardNames();
\r
498 // run analyze - may speed up some queries
\r
499 db->Execute("ANALYZE;");
\r
503 void ConvertDB0100To0101()
\r
505 // added unique constraint to public and private key
\r
506 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
507 db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");
\r
508 db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");
\r
509 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
510 LocalIdentityID INTEGER PRIMARY KEY,\
\r
512 PublicKey TEXT UNIQUE,\
\r
513 PrivateKey TEXT UNIQUE,\
\r
514 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
515 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
516 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
517 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
518 LastInsertedIdentity DATETIME,\
\r
519 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
520 LastInsertedPuzzle DATETIME,\
\r
521 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
522 LastInsertedTrustList DATETIME,\
\r
523 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
524 LastInsertedBoardList DATETIME,\
\r
525 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
526 LastInsertedMessageList DATETIME\
\r
528 db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");
\r
529 db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");
\r
530 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");
\r
533 void ConvertDB0101To0103()
\r
535 // remove default 50 from trust fields and set default to NULL
\r
536 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
537 db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");
\r
538 db->Execute("DROP TABLE IF EXISTS tblIdentity;");
\r
539 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
540 IdentityID INTEGER PRIMARY KEY,\
\r
541 PublicKey TEXT UNIQUE,\
\r
543 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
544 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
545 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
546 DateAdded DATETIME,\
\r
547 LastSeen DATETIME,\
\r
548 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
549 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
550 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
551 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\
\r
553 db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");
\r
554 db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");
\r
556 // add SaveReceivedMessages field to tblBoard
\r
557 db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");
\r
559 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");
\r
562 void ConvertDB0103To0104()
\r
564 // add MessageIndex to tblMessage
\r
566 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
567 db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;");
\r
568 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
569 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");
\r
570 date.SetToGMTime();
\r
571 db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");
\r
572 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");
\r
575 void ConvertDB0104To0105()
\r
577 // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity
\r
578 // add MessageTrustComment,TrustListTrustComment to tblPeerTrust
\r
579 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
580 db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;");
\r
581 db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;");
\r
582 db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;");
\r
583 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;");
\r
584 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;");
\r
585 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;");
\r
588 void ConvertDB0105To0106()
\r
590 // add Publish Freesite
\r
591 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
592 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';");
\r
593 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;");
\r
594 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");
\r
597 void ConvertDB0106To0107()
\r
599 // add AddedMethod to tblBoard
\r
600 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
601 db->Execute("ALTER TABLE tblBoard ADD COLUMN AddedMethod TEXT;");
\r
602 db->Execute("ALTER TABLE tblIdentity ADD COLUMN Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false';");
\r
603 db->Execute("UPDATE tblIdentity SET Hidden='false' WHERE Hidden IS NULL;");
\r
604 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=7;");
\r
607 void ConvertDB0107To0108()
\r
609 // add FreesiteEdition to tblLocalIdentity and tblIdentity
\r
610 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
611 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN FreesiteEdition INTEGER;");
\r
612 db->Execute("ALTER TABLE tblIdentity ADD COLUMN FreesiteEdition INTEGER;");
\r
613 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=8;");
\r
616 void ConvertDB0108To0109()
\r
618 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
619 db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\
\r
620 FileInsertID INTEGER PRIMARY KEY,\
\r
627 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;");
\r
630 void SetupDefaultOptions()
\r
632 // 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
634 std::ostringstream tempstr; // must set tempstr to "" between db inserts
\r
635 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
636 SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");
\r
640 tempstr << LogFile::LOGLEVEL_DEBUG;
\r
641 st.Bind(0,"LogLevel");
\r
642 st.Bind(1,tempstr.str());
\r
643 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
648 st.Bind(0,"NNTPListenPort");
\r
650 st.Bind(2,"The port that the NNTP service will listen for incoming connections.");
\r
654 // NNTPBindAddresses
\r
655 st.Bind(0,"NNTPBindAddresses");
\r
656 st.Bind(1,"localhost");
\r
657 st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");
\r
661 st.Bind(0,"NNTPAllowPost");
\r
663 st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");
\r
668 st.Bind(0,"StartNNTP");
\r
670 st.Bind(2,"Start NNTP server.");
\r
674 st.Bind(0,"StartHTTP");
\r
676 st.Bind(2,"Start HTTP server. WARNING: If you turn this off, you won't be able to access the administration pages.");
\r
680 st.Bind(0,"HTTPListenPort");
\r
682 st.Bind(2,"Port HTTP server will listen on.");
\r
686 st.Bind(0,"HTTPAccessControl");
\r
687 st.Bind(1,"-0.0.0.0/0,+127.0.0.1");
\r
688 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
692 // StartFreenetUpdater
\r
693 st.Bind(0,"StartFreenetUpdater");
\r
695 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
700 st.Bind(0,"FCPHost");
\r
701 st.Bind(1,"127.0.0.1");
\r
702 st.Bind(2,"Host name or address of Freenet node.");
\r
707 st.Bind(0,"FCPPort");
\r
709 st.Bind(2,"The port that Freenet is listening for FCP connections on.");
\r
713 st.Bind(0,"MessageBase");
\r
715 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
719 st.Bind(0,"MaxIdentityRequests");
\r
721 st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");
\r
725 st.Bind(0,"MaxIdentityIntroductionRequests");
\r
727 st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");
\r
731 st.Bind(0,"MaxIntroductionPuzzleRequests");
\r
733 st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");
\r
737 st.Bind(0,"MaxTrustListRequests");
\r
739 st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");
\r
743 st.Bind(0,"MaxMessageListRequests");
\r
745 st.Bind(2,"Maximum number of concurrent requests for new Message Lists");
\r
749 st.Bind(0,"MaxMessageRequests");
\r
751 st.Bind(2,"Maximum number of concurrent requests for new Messages");
\r
755 st.Bind(0,"MinLocalMessageTrust");
\r
757 st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");
\r
761 st.Bind(0,"MinPeerMessageTrust");
\r
763 st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");
\r
767 st.Bind(0,"MinLocalTrustListTrust");
\r
769 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
773 st.Bind(0,"MinPeerTrustListTrust");
\r
775 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
779 st.Bind(0,"MessageDownloadMaxDaysBackward");
\r
781 st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");
\r
785 st.Bind(0,"MessageListDaysBackward");
\r
787 st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");
\r
791 st.Bind(0,"MaxPeerMessagesPerDay");
\r
793 st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");
\r
797 st.Bind(0,"MaxBoardListRequests");
\r
799 st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");
\r
803 st.Bind(0,"MaxBoardsPerMessage");
\r
805 st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");
\r
809 st.Bind(0,"SaveMessagesFromNewBoards");
\r
811 st.Bind(2,"Set to true to automatically save messages posted to new boards. Set to false to ignore messages to new boards.");
\r
815 st.Bind(0,"ChangeMessageTrustOnReply");
\r
817 st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");
\r
821 st.Bind(0,"AddNewPostFromIdentities");
\r
822 st.Bind(1,"false");
\r
823 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
827 st.Bind(0,"DeleteMessagesOlderThan");
\r
829 st.Bind(2,"Automatically delete messages older than this many days.");
\r
835 void SetupLogFile()
\r
838 std::string configval;
\r
841 date.SetToGMTime();
\r
843 LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");
\r
844 LogFile::Instance()->OpenFile();
\r
845 LogFile::Instance()->SetWriteNewLine(true);
\r
846 LogFile::Instance()->SetWriteDate(true);
\r
847 LogFile::Instance()->SetWriteLogLevel(true);
\r
849 if(Option::Instance()->Get("LogLevel",configval)==false)
\r
852 Option::Instance()->Set("LogLevel",configval);
\r
854 if(StringFunctions::Convert(configval,loglevel)==false)
\r
856 loglevel=LogFile::LOGLEVEL_DEBUG;
\r
857 Option::Instance()->Set("LogLevel",loglevel);
\r
859 LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);
\r
862 void SetupNetwork()
\r
866 WSAStartup(MAKEWORD(2,2),&wsadata);
\r
872 ThreadController::Instance()->ShutdownThreads();
\r
876 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");
\r
877 LogFile::Instance()->WriteNewLine();
\r
880 void ShutdownNetwork()
\r
887 void SigHandler(int signum)
\r
893 void FixCapitalBoardNames()
\r
895 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
897 SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);");
\r
898 SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");
\r
899 SQLite3DB::Statement del=db->Prepare("DELETE FROM tblBoard WHERE BoardID=?;");
\r
900 SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;");
\r
901 SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;");
\r
902 SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;");
\r
905 while(st.RowReturned())
\r
909 std::string name="";
\r
910 std::string lowername="";
\r
912 st.ResultInt(0,boardid);
\r
913 st.ResultText(1,name);
\r
916 StringFunctions::LowerCase(lowername,lowername);
\r
918 if(name!=lowername)
\r
920 st2.Bind(0,lowername);
\r
923 if(st2.RowReturned())
\r
925 st2.ResultInt(0,newboardid);
\r
927 upd2.Bind(0,newboardid);
\r
928 upd2.Bind(1,boardid);
\r
932 upd3.Bind(0,newboardid);
\r
933 upd3.Bind(1,boardid);
\r
937 del.Bind(0,boardid);
\r
943 upd.Bind(0,lowername);
\r
944 upd.Bind(1,boardid);
\r