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
110 if(major==1 && minor==9)
\r
112 ConvertDB0109To0110();
\r
119 db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,10);");
\r
122 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=10;");
\r
124 db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\
\r
125 Option TEXT UNIQUE,\
\r
126 OptionValue TEXT NOT NULL,\
\r
127 OptionDescription TEXT\
\r
130 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
131 LocalIdentityID INTEGER PRIMARY KEY,\
\r
133 PublicKey TEXT UNIQUE,\
\r
134 PrivateKey TEXT UNIQUE,\
\r
135 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
136 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
137 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
138 PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\
\r
139 FreesiteEdition INTEGER,\
\r
140 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
141 LastInsertedIdentity DATETIME,\
\r
142 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
143 LastInsertedPuzzle DATETIME,\
\r
144 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
145 LastInsertedTrustList DATETIME,\
\r
146 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
147 LastInsertedBoardList DATETIME,\
\r
148 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
149 LastInsertedMessageList DATETIME,\
\r
150 LastInsertedFreesite DATETIME,\
\r
151 DateCreated DATETIME\
\r
154 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\
\r
155 LocalIdentityID INTEGER,\
\r
157 InsertIndex INTEGER\
\r
160 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\
\r
161 LocalIdentityID INTEGER,\
\r
163 InsertIndex INTEGER\
\r
166 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\
\r
167 IdentityID INTEGER,\
\r
169 RequestIndex INTEGER,\
\r
170 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
173 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\
\r
175 LocalIdentityID INTEGER,\
\r
177 InsertIndex INTEGER,\
\r
181 PuzzleSolution TEXT,\
\r
182 FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\
\r
185 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
186 IdentityID INTEGER PRIMARY KEY,\
\r
187 PublicKey TEXT UNIQUE,\
\r
189 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
190 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
191 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
192 FreesiteEdition INTEGER,\
\r
193 DateAdded DATETIME,\
\r
194 LastSeen DATETIME,\
\r
195 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
196 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
197 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
198 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
200 MessageTrustComment TEXT,\
\r
201 TrustListTrustComment TEXT,\
\r
202 Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false'\
\r
205 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\
\r
206 IdentityID INTEGER,\
\r
208 RequestIndex INTEGER,\
\r
209 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
212 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\
\r
213 IdentityID INTEGER,\
\r
215 RequestIndex INTEGER,\
\r
216 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\
\r
223 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\
\r
224 LocalIdentityID INTEGER,\
\r
228 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
231 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityTrust(\
\r
232 LocalIdentityID INTEGER,\
\r
233 IdentityID INTEGER,\
\r
234 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
235 MessageTrustComment TEXT,\
\r
236 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
237 TrustListTrustComment TEXT\
\r
240 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxIdentityTrust_IDs ON tblIdentityTrust(LocalIdentityID,IdentityID);");
\r
242 db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOnIdentityTrust AFTER INSERT 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 trgUpdateOnIdentityTrust AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentityTrust \
\r
251 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
254 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOnIdentityTrust AFTER DELETE ON tblIdentityTrust \
\r
257 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
260 db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\
\r
261 IdentityID INTEGER,\
\r
262 TargetIdentityID INTEGER,\
\r
263 MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\
\r
264 TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100),\
\r
265 MessageTrustComment TEXT,\
\r
266 TrustListTrustComment TEXT\
\r
269 db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_IdentityID ON tblPeerTrust (IdentityID);");
\r
270 db->Execute("CREATE INDEX IF NOT EXISTS idxPeerTrust_TargetIdentityID ON tblPeerTrust (TargetIdentityID);");
\r
272 db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\
\r
273 BoardID INTEGER PRIMARY KEY,\
\r
274 BoardName TEXT UNIQUE,\
\r
275 BoardDescription TEXT,\
\r
276 DateAdded DATETIME,\
\r
277 SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true',\
\r
281 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('fms','Freenet Message System','2007-12-01 12:00:00','Initial Board');");
\r
282 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00','Initialt Board');");
\r
283 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('public','Public discussion','2007-12-01 12:00:00','Initial Board');");
\r
284 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded,AddedMethod) VALUES('test','Test board','2007-12-01 12:00:00','Initial Board');");
\r
286 db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\
\r
287 MessageID INTEGER PRIMARY KEY,\
\r
288 IdentityID INTEGER,\
\r
293 MessageUUID TEXT UNIQUE,\
\r
294 ReplyBoardID INTEGER,\
\r
296 MessageIndex INTEGER\
\r
299 db->Execute("CREATE INDEX IF NOT EXISTS idxMessage_IdentityID ON tblMessage (IdentityID);");
\r
301 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\
\r
302 MessageID INTEGER,\
\r
303 ReplyToMessageUUID TEXT,\
\r
304 ReplyOrder INTEGER\
\r
307 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageReplyTo_MessageID ON tblMessageReplyTo (MessageID);");
\r
309 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\
\r
310 MessageID INTEGER,\
\r
314 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_MessageID ON tblMessageBoard (MessageID);");
\r
315 db->Execute("CREATE INDEX IF NOT EXISTS idxMessageBoard_BoardID ON tblMessageBoard (BoardID);");
\r
317 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\
\r
318 IdentityID INTEGER,\
\r
320 RequestIndex INTEGER,\
\r
321 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
324 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\
\r
325 IdentityID INTEGER,\
\r
327 RequestIndex INTEGER,\
\r
328 FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\
\r
329 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
332 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
334 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\
\r
335 LocalIdentityID INTEGER,\
\r
337 InsertIndex INTEGER,\
\r
338 MessageUUID TEXT UNIQUE,\
\r
340 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
343 db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\
\r
344 FileInsertID INTEGER PRIMARY KEY,\
\r
353 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\
\r
354 LocalIdentityID INTEGER,\
\r
356 InsertIndex INTEGER,\
\r
357 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
360 db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\
\r
361 BoardID INTEGER UNIQUE,\
\r
362 ModifyLocalMessageTrust INTEGER,\
\r
363 ModifyLocalTrustListTrust INTEGER\
\r
366 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\
\r
367 LocalIdentityID INTEGER,\
\r
369 InsertIndex INTEGER,\
\r
370 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
373 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\
\r
374 IdentityID INTEGER,\
\r
376 RequestIndex INTEGER,\
\r
377 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
380 // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed
\r
381 db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\
\r
382 LocalIdentityID INTEGER,\
\r
386 // low / high / message count for each board
\r
387 db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \
\r
388 SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \
\r
389 FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \
\r
390 WHERE MessageID>=0 OR MessageID IS NULL \
\r
391 GROUP BY tblBoard.BoardID;");
\r
393 // calculates peer trust
\r
394 // 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
395 // need the +1 so that when the values are 0 the result is not 0
\r
396 db->Execute("DROP VIEW IF EXISTS vwCalculatedPeerTrust;");
\r
397 db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \
\r
398 SELECT TargetIdentityID, \
\r
399 ROUND(SUM(MessageTrust*(LocalTrustListTrust/100.0))/SUM(((MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1))/100.0),0) AS 'PeerMessageTrust', \
\r
400 ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(((TrustListTrust+1)*LocalTrustListTrust/(TrustListTrust+1))/100.0),0) AS 'PeerTrustListTrust' \
\r
401 FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \
\r
402 WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \
\r
403 AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \
\r
404 GROUP BY TargetIdentityID;");
\r
407 These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed
\r
408 All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class
\r
410 // drop existing triggers
\r
411 db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");
\r
412 db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");
\r
413 db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");
\r
414 db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");
\r
416 // update PeerTrustLevel when deleting a record from tblPeerTrust
\r
417 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \
\r
420 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
423 // update PeerTrustLevel when inserting a record into tblPeerTrust
\r
424 db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \
\r
427 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
430 // update PeerTrustLevel when updating a record in tblPeerTrust
\r
431 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \
\r
434 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
435 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
438 // 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
439 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \
\r
442 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\
\r
446 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \
\r
449 DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\
\r
450 DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\
\r
453 db->Execute("DROP TRIGGER IF EXISTS trgDeleteIdentity;");
\r
454 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \
\r
457 DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\
\r
458 DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\
\r
459 DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\
\r
460 DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\
\r
461 DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\
\r
462 DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\
\r
463 DELETE FROM tblIdentityTrust WHERE IdentityID=old.IdentityID;\
\r
466 db->Execute("DROP TRIGGER IF EXISTS trgDeleteLocalIdentity;");
\r
467 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \
\r
470 DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
471 DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
472 DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
473 DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
474 DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
475 DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
476 DELETE FROM tblIdentityTrust WHERE LocalIdentityID=old.LocalIdentityID;\
\r
479 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \
\r
482 DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\
\r
485 // delete introduction puzzles that were half-way inserted
\r
486 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");
\r
488 // delete stale introduction puzzles (2 or more days old)
\r
489 date.SetToGMTime();
\r
490 date.Add(0,0,0,-2);
\r
491 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
492 db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
494 date.SetToGMTime();
\r
495 // insert SomeDude's public key
\r
496 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
497 // insert Shadow Panther's public key
\r
498 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
499 // insert garfield's public key
\r
500 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
501 // insert alek's public key
\r
502 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@lTjeI6V0lQsktXqaqJ6Iwk4TdsHduQI54rdUpHfhGbg,0oTYfrxxx8OmdU1~60gqpf3781qzEicM4Sz97mJsBM4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");
\r
503 // insert Luke771's public key
\r
504 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@mdXK~ZVlfTZhF1SLBrvZ--i0vOsOpa~w9wv~~psQ-04,gXonsXKc7aexKSO8Gt8Fwre4Qgmmbt2WueO7VzxNKkk,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");
\r
505 // insert falafel's public key
\r
506 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@IxVqeqM0LyYdTmYAf5z49SJZUxr7NtQkOqVYG0hvITw,RM2wnMn5zAufCMt5upkkgq25B1elfBAxc7htapIWg1c,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");
\r
507 // insert cptn_insano's public key
\r
508 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@bloE1LJ~qzSYUkU2nt7sB9kq060D4HTQC66pk5Q8NpA,DOOASUnp0kj6tOdhZJ-h5Tk7Ka50FSrUgsH7tCG1usU,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");
\r
509 // insert Flink's public key
\r
510 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded,AddedMethod) VALUES('SSK@q2TtkNBOuuniyJ56~8NSopCs3ttwe5KlB31ugZtWmXA,6~PzIupS8YK7L6oFNpXGKJmHT2kBMDfwTg73nHdNur8,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"','Initial Identity');");
\r
512 // TODO remove sometime after 0.1.17
\r
513 FixCapitalBoardNames();
\r
515 // run analyze - may speed up some queries
\r
516 db->Execute("ANALYZE;");
\r
520 void ConvertDB0100To0101()
\r
522 // added unique constraint to public and private key
\r
523 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
524 db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");
\r
525 db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");
\r
526 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
527 LocalIdentityID INTEGER PRIMARY KEY,\
\r
529 PublicKey TEXT UNIQUE,\
\r
530 PrivateKey TEXT UNIQUE,\
\r
531 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
532 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
533 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
534 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
535 LastInsertedIdentity DATETIME,\
\r
536 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
537 LastInsertedPuzzle DATETIME,\
\r
538 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
539 LastInsertedTrustList DATETIME,\
\r
540 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
541 LastInsertedBoardList DATETIME,\
\r
542 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
543 LastInsertedMessageList DATETIME\
\r
545 db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");
\r
546 db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");
\r
547 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");
\r
550 void ConvertDB0101To0103()
\r
552 // remove default 50 from trust fields and set default to NULL
\r
553 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
554 db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");
\r
555 db->Execute("DROP TABLE IF EXISTS tblIdentity;");
\r
556 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
557 IdentityID INTEGER PRIMARY KEY,\
\r
558 PublicKey TEXT UNIQUE,\
\r
560 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
561 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
562 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
563 DateAdded DATETIME,\
\r
564 LastSeen DATETIME,\
\r
565 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
566 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
567 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\
\r
568 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\
\r
570 db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");
\r
571 db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");
\r
573 // add SaveReceivedMessages field to tblBoard
\r
574 db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");
\r
576 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");
\r
579 void ConvertDB0103To0104()
\r
581 // add MessageIndex to tblMessage
\r
583 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
584 db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex INTEGER;");
\r
585 db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");
\r
586 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");
\r
587 date.SetToGMTime();
\r
588 db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");
\r
589 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");
\r
592 void ConvertDB0104To0105()
\r
594 // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity
\r
595 // add MessageTrustComment,TrustListTrustComment to tblPeerTrust
\r
596 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
597 db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;");
\r
598 db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;");
\r
599 db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;");
\r
600 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;");
\r
601 db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;");
\r
602 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;");
\r
605 void ConvertDB0105To0106()
\r
607 // add Publish Freesite
\r
608 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
609 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';");
\r
610 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;");
\r
611 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");
\r
614 void ConvertDB0106To0107()
\r
616 // add AddedMethod to tblBoard
\r
617 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
618 db->Execute("ALTER TABLE tblBoard ADD COLUMN AddedMethod TEXT;");
\r
619 db->Execute("ALTER TABLE tblIdentity ADD COLUMN Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false';");
\r
620 db->Execute("UPDATE tblIdentity SET Hidden='false' WHERE Hidden IS NULL;");
\r
621 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=7;");
\r
624 void ConvertDB0107To0108()
\r
626 // add FreesiteEdition to tblLocalIdentity and tblIdentity
\r
627 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
628 db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN FreesiteEdition INTEGER;");
\r
629 db->Execute("ALTER TABLE tblIdentity ADD COLUMN FreesiteEdition INTEGER;");
\r
630 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=8;");
\r
633 void ConvertDB0108To0109()
\r
635 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
636 db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\
\r
637 FileInsertID INTEGER PRIMARY KEY,\
\r
644 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=9;");
\r
647 void ConvertDB0109To0110()
\r
649 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
650 db->Execute("ALTER TABLE tblFileInserts ADD COLUMN MimeType TEXT;");
\r
651 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=10;");
\r
654 void SetupDefaultOptions()
\r
656 // 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
658 std::ostringstream tempstr; // must set tempstr to "" between db inserts
\r
659 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
660 SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");
\r
664 tempstr << LogFile::LOGLEVEL_DEBUG;
\r
665 st.Bind(0,"LogLevel");
\r
666 st.Bind(1,tempstr.str());
\r
667 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
672 st.Bind(0,"NNTPListenPort");
\r
674 st.Bind(2,"The port that the NNTP service will listen for incoming connections.");
\r
678 // NNTPBindAddresses
\r
679 st.Bind(0,"NNTPBindAddresses");
\r
680 st.Bind(1,"localhost");
\r
681 st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");
\r
685 st.Bind(0,"NNTPAllowPost");
\r
687 st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");
\r
692 st.Bind(0,"StartNNTP");
\r
694 st.Bind(2,"Start NNTP server.");
\r
698 st.Bind(0,"StartHTTP");
\r
700 st.Bind(2,"Start HTTP server. WARNING: If you turn this off, you won't be able to access the administration pages.");
\r
704 st.Bind(0,"HTTPListenPort");
\r
706 st.Bind(2,"Port HTTP server will listen on.");
\r
710 st.Bind(0,"HTTPAccessControl");
\r
711 st.Bind(1,"-0.0.0.0/0,+127.0.0.1");
\r
712 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 a host.");
\r
716 // StartFreenetUpdater
\r
717 st.Bind(0,"StartFreenetUpdater");
\r
719 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
724 st.Bind(0,"FCPHost");
\r
725 st.Bind(1,"127.0.0.1");
\r
726 st.Bind(2,"Host name or address of Freenet node.");
\r
731 st.Bind(0,"FCPPort");
\r
733 st.Bind(2,"The port that Freenet is listening for FCP connections on.");
\r
737 st.Bind(0,"FProxyPort");
\r
739 st.Bind(2,"The port that Freenet is listening for http connections on.");
\r
743 st.Bind(0,"MessageBase");
\r
745 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
749 st.Bind(0,"MaxIdentityRequests");
\r
751 st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");
\r
755 st.Bind(0,"MaxIdentityIntroductionRequests");
\r
757 st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");
\r
761 st.Bind(0,"MaxIntroductionPuzzleRequests");
\r
763 st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");
\r
767 st.Bind(0,"MaxTrustListRequests");
\r
769 st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");
\r
773 st.Bind(0,"MaxMessageListRequests");
\r
775 st.Bind(2,"Maximum number of concurrent requests for new Message Lists");
\r
779 st.Bind(0,"MaxMessageRequests");
\r
781 st.Bind(2,"Maximum number of concurrent requests for new Messages");
\r
785 st.Bind(0,"MinLocalMessageTrust");
\r
787 st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");
\r
791 st.Bind(0,"MinPeerMessageTrust");
\r
793 st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");
\r
797 st.Bind(0,"MinLocalTrustListTrust");
\r
799 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
803 st.Bind(0,"MinPeerTrustListTrust");
\r
805 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
809 st.Bind(0,"MessageDownloadMaxDaysBackward");
\r
811 st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");
\r
815 st.Bind(0,"MessageListDaysBackward");
\r
817 st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");
\r
821 st.Bind(0,"MaxPeerMessagesPerDay");
\r
823 st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");
\r
827 st.Bind(0,"MaxBoardListRequests");
\r
829 st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");
\r
833 st.Bind(0,"MaxBoardsPerMessage");
\r
835 st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");
\r
839 st.Bind(0,"SaveMessagesFromNewBoards");
\r
841 st.Bind(2,"Set to true to automatically save messages posted to new boards. Set to false to ignore messages to new boards.");
\r
845 st.Bind(0,"ChangeMessageTrustOnReply");
\r
847 st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");
\r
851 st.Bind(0,"AddNewPostFromIdentities");
\r
852 st.Bind(1,"false");
\r
853 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
857 st.Bind(0,"DeleteMessagesOlderThan");
\r
859 st.Bind(2,"Automatically delete messages older than this many days.");
\r
865 void SetupLogFile()
\r
868 std::string configval;
\r
871 date.SetToGMTime();
\r
873 LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");
\r
874 LogFile::Instance()->OpenFile();
\r
875 LogFile::Instance()->SetWriteNewLine(true);
\r
876 LogFile::Instance()->SetWriteDate(true);
\r
877 LogFile::Instance()->SetWriteLogLevel(true);
\r
879 if(Option::Instance()->Get("LogLevel",configval)==false)
\r
882 Option::Instance()->Set("LogLevel",configval);
\r
884 if(StringFunctions::Convert(configval,loglevel)==false)
\r
886 loglevel=LogFile::LOGLEVEL_DEBUG;
\r
887 Option::Instance()->Set("LogLevel",loglevel);
\r
889 LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);
\r
892 void SetupNetwork()
\r
896 WSAStartup(MAKEWORD(2,2),&wsadata);
\r
902 ThreadController::Instance()->ShutdownThreads();
\r
906 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");
\r
907 LogFile::Instance()->WriteNewLine();
\r
910 void ShutdownNetwork()
\r
917 void SigHandler(int signum)
\r
923 void FixCapitalBoardNames()
\r
925 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
927 SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);");
\r
928 SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");
\r
929 SQLite3DB::Statement del=db->Prepare("DELETE FROM tblBoard WHERE BoardID=?;");
\r
930 SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;");
\r
931 SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;");
\r
932 SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;");
\r
935 while(st.RowReturned())
\r
939 std::string name="";
\r
940 std::string lowername="";
\r
942 st.ResultInt(0,boardid);
\r
943 st.ResultText(1,name);
\r
946 StringFunctions::LowerCase(lowername,lowername);
\r
948 if(name!=lowername)
\r
950 st2.Bind(0,lowername);
\r
953 if(st2.RowReturned())
\r
955 st2.ResultInt(0,newboardid);
\r
957 upd2.Bind(0,newboardid);
\r
958 upd2.Bind(1,boardid);
\r
962 upd3.Bind(0,newboardid);
\r
963 upd3.Bind(1,boardid);
\r
967 del.Bind(0,boardid);
\r
973 upd.Bind(0,lowername);
\r
974 upd.Bind(1,boardid);
\r