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
26 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
28 db->Open("fms.db3");
\r
29 db->SetBusyTimeout(10000); // set timeout to 10 seconds
\r
30 db->Execute("VACUUM;");
\r
32 db->Execute("CREATE TABLE IF NOT EXISTS tblDBVersion(\
\r
37 SQLite3DB::Statement st=db->Prepare("SELECT Major,Minor FROM tblDBVersion;");
\r
39 if(st.RowReturned())
\r
43 st.ResultInt(0,major);
\r
44 st.ResultInt(1,minor);
\r
46 if(major==1 && minor==0)
\r
48 ConvertDB0100To0101();
\r
52 if(major==1 && (minor==1 || minor==2))
\r
54 ConvertDB0101To0103();
\r
58 if(major==1 && minor==3)
\r
60 ConvertDB0103To0104();
\r
64 if(major==1 && minor==4)
\r
66 ConvertDB0104To0105();
\r
70 if(major==1 && minor==5)
\r
72 ConvertDB0105To0106();
\r
79 db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,6);");
\r
82 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");
\r
84 db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\
\r
85 Option TEXT UNIQUE,\
\r
86 OptionValue TEXT NOT NULL,\
\r
87 OptionDescription TEXT\
\r
90 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
91 LocalIdentityID INTEGER PRIMARY KEY,\
\r
93 PublicKey TEXT UNIQUE,\
\r
94 PrivateKey TEXT UNIQUE,\
\r
95 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
96 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
97 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
98 PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\
\r
99 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
100 LastInsertedIdentity DATETIME,\
\r
101 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
102 LastInsertedPuzzle DATETIME,\
\r
103 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
104 LastInsertedTrustList DATETIME,\
\r
105 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
106 LastInsertedBoardList DATETIME,\
\r
107 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
108 LastInsertedMessageList DATETIME,\
\r
109 LastInsertedFreesite DATETIME,\
\r
110 DateCreated DATETIME\
\r
113 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\
\r
114 LocalIdentityID INTEGER,\
\r
116 InsertIndex INTEGER\
\r
119 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\
\r
120 LocalIdentityID INTEGER,\
\r
122 InsertIndex INTEGER\
\r
125 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\
\r
126 IdentityID INTEGER,\
\r
128 RequestIndex INTEGER,\
\r
129 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
132 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\
\r
134 LocalIdentityID INTEGER,\
\r
136 InsertIndex INTEGER,\
\r
140 PuzzleSolution TEXT,\
\r
141 FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\
\r
144 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
145 IdentityID INTEGER PRIMARY KEY,\
\r
146 PublicKey TEXT UNIQUE,\
\r
148 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
149 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
150 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
151 DateAdded DATETIME,\
\r
152 LastSeen DATETIME,\
\r
153 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
154 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
155 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
156 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
158 MessageTrustComment TEXT,\
\r
159 TrustListTrustComment TEXT\
\r
162 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\
\r
163 IdentityID INTEGER,\
\r
165 RequestIndex INTEGER,\
\r
166 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
169 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\
\r
170 IdentityID INTEGER,\
\r
172 RequestIndex INTEGER,\
\r
173 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\
\r
180 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\
\r
181 LocalIdentityID INTEGER,\
\r
185 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
188 db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\
\r
189 IdentityID INTEGER,\
\r
190 TargetIdentityID INTEGER,\
\r
191 MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\
\r
192 TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100),\
\r
193 MessageTrustComment TEXT,\
\r
194 TrustListTrustComment TEXT\
\r
197 db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_IdentityID ON tblPeerTrust (IdentityID);");
\r
198 db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_TargetIdentityID ON tblPeerTrust (TargetIdentityID);");
\r
200 db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\
\r
201 BoardID INTEGER PRIMARY KEY,\
\r
202 BoardName TEXT UNIQUE,\
\r
203 BoardDescription TEXT,\
\r
204 DateAdded DATETIME,\
\r
205 SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true'\
\r
208 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01 12:00:00');");
\r
209 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00');");
\r
210 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01 12:00:00');");
\r
211 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01 12:00:00');");
\r
213 db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\
\r
214 MessageID INTEGER PRIMARY KEY,\
\r
215 IdentityID INTEGER,\
\r
220 MessageUUID TEXT UNIQUE,\
\r
221 ReplyBoardID INTEGER,\
\r
223 MessageIndex INTEGER\
\r
226 db->Execute("CREATE INDEX IF NOT EXISTS idxMessage_IdentityID ON tblMessage (IdentityID);");
\r
228 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\
\r
229 MessageID INTEGER,\
\r
230 ReplyToMessageUUID TEXT,\
\r
231 ReplyOrder INTEGER\
\r
234 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\
\r
235 MessageID INTEGER,\
\r
239 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_BoardID ON tblMessageBoard (BoardID);");
\r
241 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\
\r
242 IdentityID INTEGER,\
\r
244 RequestIndex INTEGER,\
\r
245 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
248 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\
\r
249 IdentityID INTEGER,\
\r
251 RequestIndex INTEGER,\
\r
252 FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\
\r
253 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
256 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
258 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\
\r
259 LocalIdentityID INTEGER,\
\r
261 InsertIndex INTEGER,\
\r
262 MessageUUID TEXT UNIQUE,\
\r
264 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
267 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\
\r
268 LocalIdentityID INTEGER,\
\r
270 InsertIndex INTEGER,\
\r
271 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
274 db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\
\r
275 BoardID INTEGER UNIQUE,\
\r
276 ModifyLocalMessageTrust INTEGER,\
\r
277 ModifyLocalTrustListTrust INTEGER\
\r
280 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\
\r
281 LocalIdentityID INTEGER,\
\r
283 InsertIndex INTEGER,\
\r
284 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
287 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\
\r
288 IdentityID INTEGER,\
\r
290 RequestIndex INTEGER,\
\r
291 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
294 // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed
\r
295 db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\
\r
296 LocalIdentityID INTEGER,\
\r
300 // low / high / message count for each board
\r
301 db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \
\r
302 SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \
\r
303 FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \
\r
304 WHERE MessageID>=0 OR MessageID IS NULL \
\r
305 GROUP BY tblBoard.BoardID;");
\r
307 // calculates peer trust
\r
308 // 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
309 // need the +1 so that when the values are 0 the result is not 0
\r
310 db->Execute("DROP VIEW IF EXISTS vwCalculatedPeerTrust;");
\r
311 db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \
\r
312 SELECT TargetIdentityID, \
\r
313 ROUND(SUM(MessageTrust*(LocalTrustListTrust/100.0))/SUM(((MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1))/100.0),0) AS 'PeerMessageTrust', \
\r
314 ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(((TrustListTrust+1)*LocalTrustListTrust/(TrustListTrust+1))/100.0),0) AS 'PeerTrustListTrust' \
\r
315 FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \
\r
316 WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \
\r
317 AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \
\r
318 GROUP BY TargetIdentityID;");
\r
321 These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed
\r
322 All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class
\r
324 // drop existing triggers
\r
325 db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");
\r
326 db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");
\r
327 db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");
\r
328 db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");
\r
330 // update PeerTrustLevel when deleting a record from tblPeerTrust
\r
331 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \
\r
334 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
337 // update PeerTrustLevel when inserting a record into tblPeerTrust
\r
338 db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \
\r
341 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
344 // update PeerTrustLevel when updating a record in tblPeerTrust
\r
345 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \
\r
348 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
349 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
352 // 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
353 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \
\r
356 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\
\r
360 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \
\r
363 DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\
\r
364 DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\
\r
367 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \
\r
370 DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\
\r
371 DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\
\r
372 DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\
\r
373 DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\
\r
374 DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\
\r
375 DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\
\r
378 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \
\r
381 DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
382 DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
383 DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
384 DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
385 DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
386 DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
389 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \
\r
392 DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\
\r
395 // delete introduction puzzles that were half-way inserted
\r
396 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");
\r
398 // delete stale introduction puzzles (2 or more days old)
\r
399 date.SetToGMTime();
\r
400 date.Add(0,0,0,-2);
\r
401 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
402 db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
404 date.SetToGMTime();
\r
405 // insert SomeDude's public key
\r
406 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,LocalTrustListTrust) VALUES('SSK@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw,iXez4j3qCpd596TxXiJgZyTq9o-CElEuJxm~jNNZAuA,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"',50);");
\r
407 // insert Shadow Panther's public key
\r
408 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");
\r
409 // insert garfield's public key
\r
410 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");
\r
412 // TODO remove sometime after 0.1.17
\r
413 FixCapitalBoardNames();
\r
417 void ConvertDB0100To0101()
\r
419 // added unique constraint to public and private key
\r
420 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
421 db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");
\r
422 db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");
\r
423 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
424 LocalIdentityID INTEGER PRIMARY KEY,\
\r
426 PublicKey TEXT UNIQUE,\
\r
427 PrivateKey TEXT UNIQUE,\
\r
428 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
429 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
430 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
431 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
432 LastInsertedIdentity DATETIME,\
\r
433 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
434 LastInsertedPuzzle DATETIME,\
\r
435 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
436 LastInsertedTrustList DATETIME,\
\r
437 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
438 LastInsertedBoardList DATETIME,\
\r
439 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
440 LastInsertedMessageList DATETIME\
\r
442 db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");
\r
443 db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");
\r
444 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");
\r
447 void ConvertDB0101To0103()
\r
449 // remove default 50 from trust fields and set default to NULL
\r
450 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
451 db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");
\r
452 db->Execute("DROP TABLE IF EXISTS tblIdentity;");
\r
453 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
454 IdentityID INTEGER PRIMARY KEY,\
\r
455 PublicKey TEXT UNIQUE,\
\r
457 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
458 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
459 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
460 DateAdded DATETIME,\
\r
461 LastSeen DATETIME,\
\r
462 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
463 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
464 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
465 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\
\r
467 db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");
\r
468 db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");
\r
470 // add SaveReceivedMessages field to tblBoard
\r
471 db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");
\r
473 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");
\r
476 void ConvertDB0103To0104()
\r
478 // add MessageIndex to tblMessage
\r
480 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
481 db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;");
\r
482 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
483 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");
\r
484 date.SetToGMTime();
\r
485 db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");
\r
486 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");
\r
489 void ConvertDB0104To0105()
\r
491 // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity
\r
492 // add MessageTrustComment,TrustListTrustComment to tblPeerTrust
\r
493 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
494 db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;");
\r
495 db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;");
\r
496 db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;");
\r
497 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;");
\r
498 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;");
\r
499 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;");
\r
502 void ConvertDB0105To0106()
\r
504 // add Publish Freesite
\r
505 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
506 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';");
\r
507 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;");
\r
508 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");
\r
511 void SetupDefaultOptions()
\r
513 // 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
515 std::ostringstream tempstr; // must set tempstr to "" between db inserts
\r
516 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
517 SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");
\r
521 tempstr << LogFile::LOGLEVEL_DEBUG;
\r
522 st.Bind(0,"LogLevel");
\r
523 st.Bind(1,tempstr.str());
\r
524 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
529 st.Bind(0,"NNTPListenPort");
\r
531 st.Bind(2,"The port that the NNTP service will listen for incoming connections.");
\r
535 // NNTPBindAddresses
\r
536 st.Bind(0,"NNTPBindAddresses");
\r
537 st.Bind(1,"localhost");
\r
538 st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");
\r
542 st.Bind(0,"NNTPAllowPost");
\r
544 st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");
\r
549 st.Bind(0,"StartNNTP");
\r
551 st.Bind(2,"Start NNTP server.");
\r
555 st.Bind(0,"StartHTTP");
\r
557 st.Bind(2,"Start HTTP server. WARNING: If you turn this off, you won't be able to access the administration pages.");
\r
561 st.Bind(0,"HTTPListenPort");
\r
563 st.Bind(2,"Port HTTP server will listen on.");
\r
567 st.Bind(0,"HTTPAccessControl");
\r
568 st.Bind(1,"-0.0.0.0/0,+127.0.0.1");
\r
569 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
573 // StartFreenetUpdater
\r
574 st.Bind(0,"StartFreenetUpdater");
\r
576 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
581 st.Bind(0,"FCPHost");
\r
582 st.Bind(1,"127.0.0.1");
\r
583 st.Bind(2,"Host name or address of Freenet node.");
\r
588 st.Bind(0,"FCPPort");
\r
590 st.Bind(2,"The port that Freenet is listening for FCP connections on.");
\r
594 st.Bind(0,"MessageBase");
\r
596 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
600 st.Bind(0,"MaxIdentityRequests");
\r
602 st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");
\r
606 st.Bind(0,"MaxIdentityIntroductionRequests");
\r
608 st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");
\r
612 st.Bind(0,"MaxIntroductionPuzzleRequests");
\r
614 st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");
\r
618 st.Bind(0,"MaxTrustListRequests");
\r
620 st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");
\r
624 st.Bind(0,"MaxMessageListRequests");
\r
626 st.Bind(2,"Maximum number of concurrent requests for new Message Lists");
\r
630 st.Bind(0,"MaxMessageRequests");
\r
632 st.Bind(2,"Maximum number of concurrent requests for new Messages");
\r
636 st.Bind(0,"MinLocalMessageTrust");
\r
638 st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");
\r
642 st.Bind(0,"MinPeerMessageTrust");
\r
644 st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");
\r
648 st.Bind(0,"MinLocalTrustListTrust");
\r
650 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
654 st.Bind(0,"MinPeerTrustListTrust");
\r
656 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
660 st.Bind(0,"MessageDownloadMaxDaysBackward");
\r
662 st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");
\r
666 st.Bind(0,"MessageListDaysBackward");
\r
668 st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");
\r
672 st.Bind(0,"MaxPeerMessagesPerDay");
\r
674 st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");
\r
678 st.Bind(0,"MaxBoardListRequests");
\r
680 st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");
\r
684 st.Bind(0,"MaxBoardsPerMessage");
\r
686 st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");
\r
690 st.Bind(0,"SaveMessagesFromNewBoards");
\r
692 st.Bind(2,"Set to true to automatically save messages posted to new boards. Set to false to ignore messages to new boards.");
\r
696 st.Bind(0,"ChangeMessageTrustOnReply");
\r
698 st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");
\r
702 st.Bind(0,"AddNewPostFromIdentities");
\r
703 st.Bind(1,"false");
\r
704 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
708 st.Bind(0,"DeleteMessagesOlderThan");
\r
710 st.Bind(2,"Automatically delete messages older than this many days.");
\r
716 void SetupLogFile()
\r
719 std::string configval;
\r
722 date.SetToGMTime();
\r
724 LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");
\r
725 LogFile::Instance()->OpenFile();
\r
726 LogFile::Instance()->SetWriteNewLine(true);
\r
727 LogFile::Instance()->SetWriteDate(true);
\r
728 LogFile::Instance()->SetWriteLogLevel(true);
\r
730 if(Option::Instance()->Get("LogLevel",configval)==false)
\r
733 Option::Instance()->Set("LogLevel",configval);
\r
735 if(StringFunctions::Convert(configval,loglevel)==false)
\r
737 loglevel=LogFile::LOGLEVEL_DEBUG;
\r
738 Option::Instance()->Set("LogLevel",loglevel);
\r
740 LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);
\r
743 void SetupNetwork()
\r
747 WSAStartup(MAKEWORD(2,2),&wsadata);
\r
753 ThreadController::Instance()->ShutdownThreads();
\r
757 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");
\r
758 LogFile::Instance()->WriteNewLine();
\r
761 void ShutdownNetwork()
\r
768 void SigHandler(int signum)
\r
774 void FixCapitalBoardNames()
\r
776 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
778 SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);");
\r
779 SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");
\r
780 SQLite3DB::Statement del=db->Prepare("DELTE FROM tblBoard WHERE BoardID=?;");
\r
781 SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;");
\r
782 SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;");
\r
783 SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;");
\r
786 while(st.RowReturned())
\r
790 std::string name="";
\r
791 std::string lowername="";
\r
793 st.ResultInt(0,boardid);
\r
794 st.ResultText(1,name);
\r
797 StringFunctions::LowerCase(lowername,lowername);
\r
799 if(name!=lowername)
\r
801 st2.Bind(0,lowername);
\r
804 if(st2.RowReturned())
\r
806 st2.ResultInt(0,newboardid);
\r
808 upd2.Bind(0,newboardid);
\r
809 upd2.Bind(1,boardid);
\r
813 upd3.Bind(0,newboardid);
\r
814 upd3.Bind(1,boardid);
\r
818 del.Bind(0,boardid);
\r
824 upd.Bind(0,lowername);
\r
825 upd.Bind(1,boardid);
\r