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 // TODO remove this - temp fix for problem in 0.1.8
\r
33 db->Execute("DELETE FROM tblMessageBoard WHERE MessageID NOT IN (SELECT MessageID FROM tblMessage);");
\r
35 db->Execute("CREATE TABLE IF NOT EXISTS tblDBVersion(\
\r
40 SQLite3DB::Statement st=db->Prepare("SELECT Major,Minor FROM tblDBVersion;");
\r
42 if(st.RowReturned())
\r
46 st.ResultInt(0,major);
\r
47 st.ResultInt(1,minor);
\r
49 if(major==1 && minor==0)
\r
51 ConvertDB0100To0101();
\r
55 if(major==1 && (minor==1 || minor==2))
\r
57 ConvertDB0101To0103();
\r
61 if(major==1 && minor==3)
\r
63 ConvertDB0103To0104();
\r
70 db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,4);");
\r
73 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");
\r
75 db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\
\r
76 Option TEXT UNIQUE,\
\r
77 OptionValue TEXT NOT NULL,\
\r
78 OptionDescription TEXT\
\r
81 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
82 LocalIdentityID INTEGER PRIMARY KEY,\
\r
84 PublicKey TEXT UNIQUE,\
\r
85 PrivateKey TEXT UNIQUE,\
\r
86 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
87 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
88 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
89 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
90 LastInsertedIdentity DATETIME,\
\r
91 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
92 LastInsertedPuzzle DATETIME,\
\r
93 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
94 LastInsertedTrustList DATETIME,\
\r
95 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
96 LastInsertedBoardList DATETIME,\
\r
97 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
98 LastInsertedMessageList DATETIME,\
\r
99 DateCreated DATETIME\
\r
102 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\
\r
103 LocalIdentityID INTEGER,\
\r
105 InsertIndex INTEGER\
\r
108 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\
\r
109 LocalIdentityID INTEGER,\
\r
111 InsertIndex INTEGER\
\r
114 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\
\r
115 IdentityID INTEGER,\
\r
117 RequestIndex INTEGER,\
\r
118 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
121 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\
\r
123 LocalIdentityID INTEGER,\
\r
125 InsertIndex INTEGER,\
\r
129 PuzzleSolution TEXT,\
\r
130 FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\
\r
133 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
134 IdentityID INTEGER PRIMARY KEY,\
\r
135 PublicKey TEXT UNIQUE,\
\r
137 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
138 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
139 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
140 DateAdded DATETIME,\
\r
141 LastSeen DATETIME,\
\r
142 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
143 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
144 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
145 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\
\r
148 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\
\r
149 IdentityID INTEGER,\
\r
151 RequestIndex INTEGER,\
\r
152 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
155 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\
\r
156 IdentityID INTEGER,\
\r
158 RequestIndex INTEGER,\
\r
159 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\
\r
166 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\
\r
167 LocalIdentityID INTEGER,\
\r
171 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
174 db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\
\r
175 IdentityID INTEGER,\
\r
176 TargetIdentityID INTEGER,\
\r
177 MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\
\r
178 TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100)\
\r
181 db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\
\r
182 BoardID INTEGER PRIMARY KEY,\
\r
183 BoardName TEXT UNIQUE,\
\r
184 BoardDescription TEXT,\
\r
185 DateAdded DATETIME,\
\r
186 SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true'\
\r
189 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01 12:00:00');");
\r
190 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00');");
\r
191 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01 12:00:00');");
\r
192 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01 12:00:00');");
\r
194 db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\
\r
195 MessageID INTEGER PRIMARY KEY,\
\r
196 IdentityID INTEGER,\
\r
201 MessageUUID TEXT UNIQUE,\
\r
202 ReplyBoardID INTEGER,\
\r
204 MessageIndex INTEGER\
\r
207 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\
\r
208 MessageID INTEGER,\
\r
209 ReplyToMessageUUID TEXT,\
\r
210 ReplyOrder INTEGER\
\r
213 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\
\r
214 MessageID INTEGER,\
\r
218 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\
\r
219 IdentityID INTEGER,\
\r
221 RequestIndex INTEGER,\
\r
222 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
225 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\
\r
226 IdentityID INTEGER,\
\r
228 RequestIndex INTEGER,\
\r
229 FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\
\r
230 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
233 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
235 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\
\r
236 LocalIdentityID INTEGER,\
\r
238 InsertIndex INTEGER,\
\r
239 MessageUUID TEXT UNIQUE,\
\r
241 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
244 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\
\r
245 LocalIdentityID INTEGER,\
\r
247 InsertIndex INTEGER,\
\r
248 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
251 db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\
\r
252 BoardID INTEGER UNIQUE,\
\r
253 ModifyLocalMessageTrust INTEGER,\
\r
254 ModifyLocalTrustListTrust INTEGER\
\r
257 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\
\r
258 LocalIdentityID INTEGER,\
\r
260 InsertIndex INTEGER,\
\r
261 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
264 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\
\r
265 IdentityID INTEGER,\
\r
267 RequestIndex INTEGER,\
\r
268 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
271 // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed
\r
272 db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\
\r
273 LocalIdentityID INTEGER,\
\r
277 // low / high / message count for each board
\r
278 db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \
\r
279 SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \
\r
280 FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \
\r
281 WHERE MessageID>=0 OR MessageID IS NULL \
\r
282 GROUP BY tblBoard.BoardID;");
\r
284 // calculates peer trust
\r
285 // do the (MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1)/100.0 - so it MessageTrust or TrustListTrust is NULL, the calc will be NULL and it won't be included at all in the average
\r
286 // need the +1 so that when the values are 0 the result is not 0
\r
287 db->Execute("DROP VIEW IF EXISTS vwCalculatedPeerTrust;");
\r
288 db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \
\r
289 SELECT TargetIdentityID, \
\r
290 ROUND(SUM(MessageTrust*(LocalTrustListTrust/100.0))/SUM(((MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1))/100.0),0) AS 'PeerMessageTrust', \
\r
291 ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(((TrustListTrust+1)*LocalTrustListTrust/(TrustListTrust+1))/100.0),0) AS 'PeerTrustListTrust' \
\r
292 FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \
\r
293 WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \
\r
294 AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \
\r
295 GROUP BY TargetIdentityID;");
\r
298 These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed
\r
299 All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class
\r
301 // drop existing triggers
\r
302 db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");
\r
303 db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");
\r
304 db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");
\r
305 db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");
\r
307 // update PeerTrustLevel when deleting a record from tblPeerTrust
\r
308 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \
\r
311 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
314 // update PeerTrustLevel when inserting a record into tblPeerTrust
\r
315 db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \
\r
318 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
321 // update PeerTrustLevel when updating a record in tblPeerTrust
\r
322 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \
\r
325 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
326 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
329 // 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
330 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \
\r
333 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\
\r
337 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \
\r
340 DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\
\r
341 DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\
\r
344 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \
\r
347 DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\
\r
348 DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\
\r
349 DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\
\r
350 DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\
\r
351 DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\
\r
352 DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\
\r
355 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \
\r
358 DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
359 DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
360 DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
361 DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
362 DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
363 DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
366 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \
\r
369 DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\
\r
372 // delete introduction puzzles that were half-way inserted
\r
373 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");
\r
375 // delete stale introduction puzzles (2 or more days old)
\r
376 date.SetToGMTime();
\r
377 date.Add(0,0,0,-2);
\r
378 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
379 db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
381 date.SetToGMTime();
\r
382 // insert SomeDude's public key
\r
383 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,LocalTrustListTrust) VALUES('SSK@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw,iXez4j3qCpd596TxXiJgZyTq9o-CElEuJxm~jNNZAuA,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"',51);");
\r
384 // insert Shadow Panther's public key
\r
385 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");
\r
386 // insert garfield's public key
\r
387 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");
\r
391 void ConvertDB0100To0101()
\r
393 // added unique constraint to public and private key
\r
394 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
395 db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");
\r
396 db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");
\r
397 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
398 LocalIdentityID INTEGER PRIMARY KEY,\
\r
400 PublicKey TEXT UNIQUE,\
\r
401 PrivateKey TEXT UNIQUE,\
\r
402 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
403 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
404 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
405 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
406 LastInsertedIdentity DATETIME,\
\r
407 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
408 LastInsertedPuzzle DATETIME,\
\r
409 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
410 LastInsertedTrustList DATETIME,\
\r
411 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
412 LastInsertedBoardList DATETIME,\
\r
413 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
414 LastInsertedMessageList DATETIME\
\r
416 db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");
\r
417 db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");
\r
418 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");
\r
421 void ConvertDB0101To0103()
\r
423 // remove default 50 from trust fields and set default to NULL
\r
424 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
425 db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");
\r
426 db->Execute("DROP TABLE IF EXISTS tblIdentity;");
\r
427 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
428 IdentityID INTEGER PRIMARY KEY,\
\r
429 PublicKey TEXT UNIQUE,\
\r
431 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
432 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
433 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
434 DateAdded DATETIME,\
\r
435 LastSeen DATETIME,\
\r
436 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
437 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
438 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
439 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\
\r
441 db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");
\r
442 db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");
\r
444 // add SaveReceivedMessages field to tblBoard
\r
445 db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");
\r
447 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");
\r
450 void ConvertDB0103To0104()
\r
452 // add MessageIndex to tblMessage
\r
454 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
455 db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;");
\r
456 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
457 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");
\r
458 date.SetToGMTime();
\r
459 db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");
\r
460 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");
\r
463 void SetupDefaultOptions()
\r
465 // 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
467 std::ostringstream tempstr; // must set tempstr to "" between db inserts
\r
468 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
469 SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");
\r
473 tempstr << LogFile::LOGLEVEL_DEBUG;
\r
474 st.Bind(0,"LogLevel");
\r
475 st.Bind(1,tempstr.str());
\r
476 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
481 st.Bind(0,"NNTPListenPort");
\r
483 st.Bind(2,"The port that the NNTP service will listen for incoming connections.");
\r
487 // NNTPBindAddresses
\r
488 st.Bind(0,"NNTPBindAddresses");
\r
489 st.Bind(1,"localhost");
\r
490 st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");
\r
494 st.Bind(0,"NNTPAllowPost");
\r
496 st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");
\r
501 st.Bind(0,"StartNNTP");
\r
503 st.Bind(2,"Start NNTP server.");
\r
507 st.Bind(0,"StartHTTP");
\r
509 st.Bind(2,"Start HTTP server.");
\r
513 st.Bind(0,"HTTPListenPort");
\r
515 st.Bind(2,"Port HTTP server will listen on.");
\r
519 // StartFreenetUpdater
\r
520 st.Bind(0,"StartFreenetUpdater");
\r
522 st.Bind(2,"Start Freenet Updater thread.");
\r
527 st.Bind(0,"FCPHost");
\r
528 st.Bind(1,"127.0.0.1");
\r
529 st.Bind(2,"Host name or address of Freenet node.");
\r
534 st.Bind(0,"FCPPort");
\r
536 st.Bind(2,"The port that Freenet is listening for FCP connections on.");
\r
540 st.Bind(0,"MessageBase");
\r
542 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
546 st.Bind(0,"MaxIdentityRequests");
\r
548 st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");
\r
552 st.Bind(0,"MaxIdentityIntroductionRequests");
\r
554 st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");
\r
558 st.Bind(0,"MaxIntroductionPuzzleRequests");
\r
560 st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");
\r
564 st.Bind(0,"MaxTrustListRequests");
\r
566 st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");
\r
570 st.Bind(0,"MaxMessageListRequests");
\r
572 st.Bind(2,"Maximum number of concurrent requests for new Message Lists");
\r
576 st.Bind(0,"MaxMessageRequests");
\r
578 st.Bind(2,"Maximum number of concurrent requests for new Messages");
\r
582 st.Bind(0,"MinLocalMessageTrust");
\r
584 st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");
\r
588 st.Bind(0,"MinPeerMessageTrust");
\r
590 st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");
\r
594 st.Bind(0,"MinLocalTrustListTrust");
\r
596 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
600 st.Bind(0,"MinPeerTrustListTrust");
\r
602 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
606 st.Bind(0,"MessageDownloadMaxDaysBackward");
\r
608 st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");
\r
612 st.Bind(0,"MessageListDaysBackward");
\r
614 st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");
\r
618 st.Bind(0,"MaxPeerMessagesPerDay");
\r
620 st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");
\r
624 st.Bind(0,"MaxBoardListRequests");
\r
626 st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");
\r
630 st.Bind(0,"MaxBoardsPerMessage");
\r
632 st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");
\r
636 st.Bind(0,"ChangeMessageTrustOnReply");
\r
638 st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");
\r
642 st.Bind(0,"AddNewPostFromIdentities");
\r
643 st.Bind(1,"false");
\r
644 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
650 void SetupLogFile()
\r
653 std::string configval;
\r
656 date.SetToGMTime();
\r
658 LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");
\r
659 LogFile::Instance()->OpenFile();
\r
660 LogFile::Instance()->SetWriteNewLine(true);
\r
661 LogFile::Instance()->SetWriteDate(true);
\r
662 LogFile::Instance()->SetWriteLogLevel(true);
\r
664 if(Option::Instance()->Get("LogLevel",configval)==false)
\r
667 Option::Instance()->Set("LogLevel",configval);
\r
669 if(StringFunctions::Convert(configval,loglevel)==false)
\r
671 loglevel=LogFile::LOGLEVEL_DEBUG;
\r
672 Option::Instance()->Set("LogLevel",loglevel);
\r
674 LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);
\r
677 void SetupNetwork()
\r
681 WSAStartup(MAKEWORD(2,2),&wsadata);
\r
687 ThreadController::Instance()->ShutdownThreads();
\r
691 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");
\r
692 LogFile::Instance()->WriteNewLine();
\r
695 void ShutdownNetwork()
\r
702 void SigHandler(int signum)
\r
709 void ShutdownThreads(std::vector<PThread::Thread *> &threads)
\r
711 std::vector<PThread::Thread *>::iterator i;
\r
712 for(i=threads.begin(); i!=threads.end(); i++)
\r
717 for(i=threads.begin(); i!=threads.end(); i++)
\r
719 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ShutdownThreads waiting for thread to exit.");
\r
729 void StartThreads(std::vector<PThread::Thread *> &threads)
\r
731 std::string startfreenet;
\r
732 std::string startnntp;
\r
733 std::string starthttp;
\r
735 if(Option::Instance()->Get("StartFreenetUpdater",startfreenet)==false)
\r
737 startfreenet="true";
\r
738 Option::Instance()->Set("StartFreenetUpdater","true");
\r
741 if(Option::Instance()->Get("StartNNTP",startnntp)==false)
\r
744 Option::Instance()->Set("StartNNTP","true");
\r
747 if(Option::Instance()->Get("StartHTTP",starthttp)==false)
\r
750 Option::Instance()->Set("StartHTTP","true");
\r
753 if(startfreenet=="true")
\r
755 PThread::Thread *t=new PThread::Thread(new FreenetMasterThread());
\r
756 threads.push_back(t);
\r
759 if(startnntp=="true")
\r
761 PThread::Thread *t=new PThread::Thread(new NNTPListener());
\r
762 threads.push_back(t);
\r
765 if(starthttp=="true")
\r
767 PThread::Thread *t=new PThread::Thread(new HTTPThread());
\r
768 threads.push_back(t);
\r