version 0.2.4
[fms.git] / src / global.cpp
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
11 \r
12 #ifdef _WIN32\r
13         #include <winsock2.h>\r
14 #endif\r
15 \r
16 #ifdef XMEM\r
17         #include <xmem.h>\r
18 #endif\r
19 \r
20 bool wantshutdown=false;\r
21 \r
22 void SetupDB()\r
23 {\r
24 \r
25         DateTime date;\r
26         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
27 \r
28         db->Open("fms.db3");\r
29         db->SetBusyTimeout(10000);              // set timeout to 10 seconds\r
30         db->Execute("VACUUM;");\r
31 \r
32         db->Execute("CREATE TABLE IF NOT EXISTS tblDBVersion(\\r
33                                 Major                           INTEGER,\\r
34                                 Minor                           INTEGER\\r
35                                 );");\r
36 \r
37         SQLite3DB::Statement st=db->Prepare("SELECT Major,Minor FROM tblDBVersion;");\r
38         st.Step();\r
39         if(st.RowReturned())\r
40         {\r
41                 int major;\r
42                 int minor;\r
43                 st.ResultInt(0,major);\r
44                 st.ResultInt(1,minor);\r
45                 st.Finalize();\r
46                 if(major==1 && minor==0)\r
47                 {\r
48                         ConvertDB0100To0101();\r
49                         major=1;\r
50                         minor=1;\r
51                 }\r
52                 if(major==1 && (minor==1 || minor==2))\r
53                 {\r
54                         ConvertDB0101To0103();\r
55                         major=1;\r
56                         minor=3;\r
57                 }\r
58                 if(major==1 && minor==3)\r
59                 {\r
60                         ConvertDB0103To0104();\r
61                         major=1;\r
62                         minor=4;\r
63                 }\r
64                 if(major==1 && minor==4)\r
65                 {\r
66                         ConvertDB0104To0105();\r
67                         major=1;\r
68                         minor=5;\r
69                 }\r
70                 if(major==1 && minor==5)\r
71                 {\r
72                         ConvertDB0105To0106();\r
73                         major=1;\r
74                         minor=6;\r
75                 }\r
76         }\r
77         else\r
78         {\r
79                 db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,6);");\r
80         }\r
81 \r
82         db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");\r
83 \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
88                                 );");\r
89 \r
90         db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
91                                 LocalIdentityID                 INTEGER PRIMARY KEY,\\r
92                                 Name                                    TEXT,\\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
111                                 );");\r
112 \r
113         db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\\r
114                                 LocalIdentityID         INTEGER,\\r
115                                 Day                                     DATE,\\r
116                                 InsertIndex                     INTEGER\\r
117                                 );");\r
118 \r
119         db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\\r
120                                 LocalIdentityID         INTEGER,\\r
121                                 Day                                     DATE,\\r
122                                 InsertIndex                     INTEGER\\r
123                                 );");\r
124 \r
125         db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\\r
126                                 IdentityID                      INTEGER,\\r
127                                 Day                                     DATE,\\r
128                                 RequestIndex            INTEGER,\\r
129                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
130                                 );");\r
131 \r
132         db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\\r
133                                 UUID                            TEXT UNIQUE,\\r
134                                 LocalIdentityID         INTEGER,\\r
135                                 Day                                     DATE,\\r
136                                 InsertIndex                     INTEGER,\\r
137                                 Type                            TEXT,\\r
138                                 MimeType                        TEXT,\\r
139                                 PuzzleData                      TEXT,\\r
140                                 PuzzleSolution          TEXT,\\r
141                                 FoundSolution           BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\\r
142                                 );");\r
143 \r
144         db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
145                                 IdentityID                              INTEGER PRIMARY KEY,\\r
146                                 PublicKey                               TEXT UNIQUE,\\r
147                                 Name                                    TEXT,\\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
157                                 AddedMethod                             TEXT,\\r
158                                 MessageTrustComment             TEXT,\\r
159                                 TrustListTrustComment   TEXT\\r
160                                 );");\r
161 \r
162         db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\\r
163                                 IdentityID                      INTEGER,\\r
164                                 Day                                     DATE,\\r
165                                 RequestIndex            INTEGER,\\r
166                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
167                                 );");\r
168 \r
169         db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\\r
170                                 IdentityID                      INTEGER,\\r
171                                 Day                                     DATE,\\r
172                                 RequestIndex            INTEGER,\\r
173                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\\r
174                                 UUID                            TEXT UNIQUE,\\r
175                                 Type                            TEXT,\\r
176                                 MimeType                        TEXT,\\r
177                                 PuzzleData                      TEXT\\r
178                                 );");\r
179 \r
180         db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\\r
181                                 LocalIdentityID         INTEGER,\\r
182                                 Day                                     DATE,\\r
183                                 UUID                            TEXT UNIQUE,\\r
184                                 Solution                        TEXT,\\r
185                                 Inserted                        BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
186                                 );");\r
187 \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
195                                 );");\r
196 \r
197         db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\\r
198                                 BoardID                                 INTEGER PRIMARY KEY,\\r
199                                 BoardName                               TEXT UNIQUE,\\r
200                                 BoardDescription                TEXT,\\r
201                                 DateAdded                               DATETIME,\\r
202                                 SaveReceivedMessages    BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true'\\r
203                                 );");\r
204 \r
205         db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01 12:00:00');");\r
206         db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00');");\r
207         db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01 12:00:00');");\r
208         db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01 12:00:00');");\r
209 \r
210         db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\\r
211                                 MessageID                       INTEGER PRIMARY KEY,\\r
212                                 IdentityID                      INTEGER,\\r
213                                 FromName                        TEXT,\\r
214                                 MessageDate                     DATE,\\r
215                                 MessageTime                     TIME,\\r
216                                 Subject                         TEXT,\\r
217                                 MessageUUID                     TEXT UNIQUE,\\r
218                                 ReplyBoardID            INTEGER,\\r
219                                 Body                            TEXT,\\r
220                                 MessageIndex            INTEGER\\r
221                                 );");\r
222 \r
223         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\\r
224                                 MessageID                       INTEGER,\\r
225                                 ReplyToMessageUUID      TEXT,\\r
226                                 ReplyOrder                      INTEGER\\r
227                                 );");\r
228 \r
229         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\\r
230                                 MessageID                       INTEGER,\\r
231                                 BoardID                         INTEGER\\r
232                                 );");\r
233 \r
234         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\\r
235                                 IdentityID                      INTEGER,\\r
236                                 Day                                     DATE,\\r
237                                 RequestIndex            INTEGER,\\r
238                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
239                                 );");\r
240 \r
241         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\\r
242                                 IdentityID                      INTEGER,\\r
243                                 Day                                     DATE,\\r
244                                 RequestIndex            INTEGER,\\r
245                                 FromMessageList         BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\\r
246                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
247                                 );");\r
248 \r
249         db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");\r
250 \r
251         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\\r
252                                 LocalIdentityID         INTEGER,\\r
253                                 Day                                     DATE,\\r
254                                 InsertIndex                     INTEGER,\\r
255                                 MessageUUID                     TEXT UNIQUE,\\r
256                                 MessageXML                      TEXT,\\r
257                                 Inserted                        BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
258                                 );");\r
259 \r
260         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\\r
261                                 LocalIdentityID         INTEGER,\\r
262                                 Day                                     DATE,\\r
263                                 InsertIndex                     INTEGER,\\r
264                                 Inserted                        BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
265                                 );");\r
266 \r
267         db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\\r
268                                 BoardID                                         INTEGER UNIQUE,\\r
269                                 ModifyLocalMessageTrust         INTEGER,\\r
270                                 ModifyLocalTrustListTrust       INTEGER\\r
271                                 );");\r
272 \r
273         db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\\r
274                                 LocalIdentityID         INTEGER,\\r
275                                 Day                                     DATE,\\r
276                                 InsertIndex                     INTEGER,\\r
277                                 Inserted                        BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
278                                 );");\r
279 \r
280         db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\\r
281                                 IdentityID                      INTEGER,\\r
282                                 Day                                     DATE,\\r
283                                 RequestIndex            INTEGER,\\r
284                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
285                                 );");   \r
286 \r
287         // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed\r
288         db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\\r
289                                 LocalIdentityID         INTEGER,\\r
290                                 Date                            DATETIME\\r
291                                 );");\r
292 \r
293         // low / high / message count for each board\r
294         db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \\r
295                                 SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \\r
296                                 FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \\r
297                                 WHERE MessageID>=0 OR MessageID IS NULL \\r
298                                 GROUP BY tblBoard.BoardID;");\r
299 \r
300         // calculates peer trust\r
301         // 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
302         // need the +1 so that when the values are 0 the result is not 0\r
303         db->Execute("DROP VIEW IF EXISTS vwCalculatedPeerTrust;");\r
304         db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \\r
305                                 SELECT TargetIdentityID, \\r
306                                 ROUND(SUM(MessageTrust*(LocalTrustListTrust/100.0))/SUM(((MessageTrust+1)*LocalTrustListTrust/(MessageTrust+1))/100.0),0) AS 'PeerMessageTrust', \\r
307                                 ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(((TrustListTrust+1)*LocalTrustListTrust/(TrustListTrust+1))/100.0),0) AS 'PeerTrustListTrust' \\r
308                                 FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \\r
309                                 WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \\r
310                                 AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \\r
311                                 GROUP BY TargetIdentityID;");\r
312 \r
313         /*\r
314                 These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed\r
315                 All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class\r
316         */\r
317         // drop existing triggers\r
318         db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");\r
319         db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");\r
320         db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");\r
321         db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");\r
322 /*\r
323         // update PeerTrustLevel when deleting a record from tblPeerTrust\r
324         db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \\r
325                                 FOR EACH ROW \\r
326                                 BEGIN \\r
327                                         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
328                                 END;");\r
329 \r
330         // update PeerTrustLevel when inserting a record into tblPeerTrust\r
331         db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \\r
332                                 FOR EACH ROW \\r
333                                 BEGIN \\r
334                                         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
335                                 END;");\r
336 \r
337         // update PeerTrustLevel when updating a record in tblPeerTrust\r
338         db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \\r
339                                 FOR EACH ROW \\r
340                                 BEGIN \\r
341                                         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
342                                         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
343                                 END;");\r
344 \r
345         // 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
346         db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \\r
347                                 FOR EACH ROW \\r
348                                 BEGIN \\r
349                                         UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\\r
350                                 END;");\r
351 */\r
352 \r
353         db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \\r
354                                 FOR EACH ROW \\r
355                                 BEGIN \\r
356                                         DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\\r
357                                         DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\\r
358                                 END;");\r
359 \r
360         db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \\r
361                                 FOR EACH ROW \\r
362                                 BEGIN \\r
363                                         DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\\r
364                                         DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\\r
365                                         DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\\r
366                                         DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\\r
367                                         DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\\r
368                                         DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\\r
369                                 END;");\r
370 \r
371         db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \\r
372                                 FOR EACH ROW \\r
373                                 BEGIN \\r
374                                         DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
375                                         DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
376                                         DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
377                                         DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
378                                         DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
379                                         DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
380                                 END;");\r
381 \r
382         db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteBoard AFTER DELETE ON tblBoard \\r
383                                 FOR EACH ROW \\r
384                                 BEGIN \\r
385                                         DELETE FROM tblMessageBoard WHERE BoardID=old.BoardID;\\r
386                                 END;");\r
387 \r
388         // delete introduction puzzles that were half-way inserted\r
389         db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");\r
390 \r
391         // delete stale introduction puzzles (2 or more days old)\r
392         date.SetToGMTime();\r
393         date.Add(0,0,0,-2);\r
394         db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");\r
395         db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");\r
396 \r
397         date.SetToGMTime();\r
398         // insert SomeDude's public key\r
399         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
400         // insert Shadow Panther's public key\r
401         db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");\r
402         // insert garfield's public key\r
403         db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");\r
404 \r
405         // TODO remove sometime after 0.1.17\r
406         FixCapitalBoardNames();\r
407 \r
408 }\r
409 \r
410 void ConvertDB0100To0101()\r
411 {\r
412         // added unique constraint to public and private key\r
413         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
414         db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");\r
415         db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");\r
416         db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
417                                 LocalIdentityID                 INTEGER PRIMARY KEY,\\r
418                                 Name                                    TEXT,\\r
419                                 PublicKey                               TEXT UNIQUE,\\r
420                                 PrivateKey                              TEXT UNIQUE,\\r
421                                 SingleUse                               BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
422                                 PublishTrustList                BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
423                                 PublishBoardList                BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
424                                 InsertingIdentity               BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\\r
425                                 LastInsertedIdentity    DATETIME,\\r
426                                 InsertingPuzzle                 BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\\r
427                                 LastInsertedPuzzle              DATETIME,\\r
428                                 InsertingTrustList              BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\\r
429                                 LastInsertedTrustList   DATETIME,\\r
430                                 InsertingBoardList              BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\\r
431                                 LastInsertedBoardList   DATETIME,\\r
432                                 InsertingMessageList    BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\\r
433                                 LastInsertedMessageList DATETIME\\r
434                                 );");\r
435         db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");\r
436         db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");\r
437         db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");\r
438 }\r
439 \r
440 void ConvertDB0101To0103()\r
441 {\r
442         // remove default 50 from trust fields and set default to NULL\r
443         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
444         db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;");\r
445         db->Execute("DROP TABLE IF EXISTS tblIdentity;");\r
446         db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
447                                 IdentityID                      INTEGER PRIMARY KEY,\\r
448                                 PublicKey                       TEXT UNIQUE,\\r
449                                 Name                            TEXT,\\r
450                                 SingleUse                       BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
451                                 PublishTrustList        BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
452                                 PublishBoardList        BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
453                                 DateAdded                       DATETIME,\\r
454                                 LastSeen                        DATETIME,\\r
455                                 LocalMessageTrust       INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
456                                 PeerMessageTrust        INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
457                                 LocalTrustListTrust     INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\\r
458                                 PeerTrustListTrust      INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL\\r
459                                 );");\r
460         db->Execute("INSERT INTO tblIdentity SELECT * FROM tblIdentityTemp;");\r
461         db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;");\r
462 \r
463         // add SaveReceivedMessages field to tblBoard\r
464         db->Execute("ALTER TABLE tblBoard ADD COLUMN SaveReceivedMessages       BOOL CHECK(SaveReceivedMessages IN('true','false')) DEFAULT 'true';");\r
465 \r
466         db->Execute("UPDATE tblDBVersion SET Major=1, Minor=3;");\r
467 }\r
468 \r
469 void ConvertDB0103To0104()\r
470 {\r
471         // add MessageIndex to tblMessage\r
472         DateTime date;\r
473         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
474         db->Execute("ALTER TABLE tblMessage ADD COLUMN MessageIndex     INTEGER;");\r
475         db->Execute("CREATE UNIQUE INDEX IF NOT EXISTS idxMessageRequest ON tblMessageRequests(IdentityID,Day,RequestIndex);");\r
476         db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN DateCreated DATETIME;");\r
477         date.SetToGMTime();\r
478         db->Execute("UPDATE tblLocalIdentity SET DateCreated='"+date.Format("%Y-%m-%d %H:%M:%S")+"' WHERE DateCreated IS NULL;");\r
479         db->Execute("UPDATE tblDBVersion SET Major=1, Minor=4;");\r
480 }\r
481 \r
482 void ConvertDB0104To0105()\r
483 {\r
484         // add AddedMethod, MessageTrustComment, TrustListTrustComment to tblIdentity\r
485         // add MessageTrustComment,TrustListTrustComment to tblPeerTrust\r
486         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
487         db->Execute("ALTER TABLE tblIdentity ADD COLUMN AddedMethod TEXT;");\r
488         db->Execute("ALTER TABLE tblIdentity ADD COLUMN MessageTrustComment TEXT;");\r
489         db->Execute("ALTER TABLE tblIdentity ADD COLUMN TrustListTrustComment TEXT;");\r
490         db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN MessageTrustComment TEXT;");\r
491         db->Execute("ALTER TABLE tblPeerTrust ADD COLUMN TrustListTrustComment TEXT;");\r
492         db->Execute("UPDATE tblDBVersion SET Major=1, Minor=5;");\r
493 }\r
494 \r
495 void ConvertDB0105To0106()\r
496 {\r
497         // add Publish Freesite\r
498         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
499         db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false';");\r
500         db->Execute("ALTER TABLE tblLocalIdentity ADD COLUMN LastInsertedFreesite DATETIME;");\r
501         db->Execute("UPDATE tblDBVersion SET Major=1, Minor=6;");\r
502 }\r
503 \r
504 void SetupDefaultOptions()\r
505 {\r
506         // 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
507 \r
508         std::ostringstream tempstr;     // must set tempstr to "" between db inserts\r
509         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
510         SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");\r
511 \r
512         // LogLevel\r
513         tempstr.str("");\r
514         tempstr << LogFile::LOGLEVEL_DEBUG;\r
515         st.Bind(0,"LogLevel");\r
516         st.Bind(1,tempstr.str());\r
517         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
518         st.Step();\r
519         st.Reset();\r
520 \r
521         // NNTPListenPort\r
522         st.Bind(0,"NNTPListenPort");\r
523         st.Bind(1,"1119");\r
524         st.Bind(2,"The port that the NNTP service will listen for incoming connections.");\r
525         st.Step();\r
526         st.Reset();\r
527 \r
528         // NNTPBindAddresses\r
529         st.Bind(0,"NNTPBindAddresses");\r
530         st.Bind(1,"localhost");\r
531         st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");\r
532         st.Step();\r
533         st.Reset();\r
534 \r
535         st.Bind(0,"NNTPAllowPost");\r
536         st.Bind(1,"true");\r
537         st.Bind(2,"Allow posting messages from NNTP.  Setting to false will make the newsgroups read only.");\r
538         st.Step();\r
539         st.Reset();\r
540 \r
541         // StartNNTP\r
542         st.Bind(0,"StartNNTP");\r
543         st.Bind(1,"true");\r
544         st.Bind(2,"Start NNTP server.");\r
545         st.Step();\r
546         st.Reset();\r
547 \r
548         st.Bind(0,"StartHTTP");\r
549         st.Bind(1,"true");\r
550         st.Bind(2,"Start HTTP server.  WARNING: If you turn this off, you won't be able to access the administration pages.");\r
551         st.Step();\r
552         st.Reset();\r
553 \r
554         st.Bind(0,"HTTPListenPort");\r
555         st.Bind(1,"8080");\r
556         st.Bind(2,"Port HTTP server will listen on.");\r
557         st.Step();\r
558         st.Reset();\r
559 \r
560         st.Bind(0,"HTTPAccessControl");\r
561         st.Bind(1,"-0.0.0.0/0,+127.0.0.1");\r
562         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
563         st.Step();\r
564         st.Reset();\r
565 \r
566         // StartFreenetUpdater\r
567         st.Bind(0,"StartFreenetUpdater");\r
568         st.Bind(1,"true");\r
569         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
570         st.Step();\r
571         st.Reset();\r
572 \r
573         // FCPHost\r
574         st.Bind(0,"FCPHost");\r
575         st.Bind(1,"127.0.0.1");\r
576         st.Bind(2,"Host name or address of Freenet node.");\r
577         st.Step();\r
578         st.Reset();\r
579 \r
580         // FCPPort\r
581         st.Bind(0,"FCPPort");\r
582         st.Bind(1,"9481");\r
583         st.Bind(2,"The port that Freenet is listening for FCP connections on.");\r
584         st.Step();\r
585         st.Reset();\r
586 \r
587         st.Bind(0,"MessageBase");\r
588         st.Bind(1,"fms");\r
589         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
590         st.Step();\r
591         st.Reset();\r
592 \r
593         st.Bind(0,"MaxIdentityRequests");\r
594         st.Bind(1,"5");\r
595         st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");\r
596         st.Step();\r
597         st.Reset();\r
598 \r
599         st.Bind(0,"MaxIdentityIntroductionRequests");\r
600         st.Bind(1,"5");\r
601         st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files.  Each identity may have multiple requests pending.");\r
602         st.Step();\r
603         st.Reset();\r
604 \r
605         st.Bind(0,"MaxIntroductionPuzzleRequests");\r
606         st.Bind(1,"5");\r
607         st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");\r
608         st.Step();\r
609         st.Reset();\r
610 \r
611         st.Bind(0,"MaxTrustListRequests");\r
612         st.Bind(1,"5");\r
613         st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");\r
614         st.Step();\r
615         st.Reset();\r
616 \r
617         st.Bind(0,"MaxMessageListRequests");\r
618         st.Bind(1,"5");\r
619         st.Bind(2,"Maximum number of concurrent requests for new Message Lists");\r
620         st.Step();\r
621         st.Reset();\r
622 \r
623         st.Bind(0,"MaxMessageRequests");\r
624         st.Bind(1,"20");\r
625         st.Bind(2,"Maximum number of concurrent requests for new Messages");\r
626         st.Step();\r
627         st.Reset();\r
628 \r
629         st.Bind(0,"MinLocalMessageTrust");\r
630         st.Bind(1,"50");\r
631         st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");\r
632         st.Step();\r
633         st.Reset();\r
634 \r
635         st.Bind(0,"MinPeerMessageTrust");\r
636         st.Bind(1,"30");\r
637         st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");\r
638         st.Step();\r
639         st.Reset();\r
640 \r
641         st.Bind(0,"MinLocalTrustListTrust");\r
642         st.Bind(1,"50");\r
643         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
644         st.Step();\r
645         st.Reset();\r
646 \r
647         st.Bind(0,"MinPeerTrustListTrust");\r
648         st.Bind(1,"30");\r
649         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
650         st.Step();\r
651         st.Reset();\r
652 \r
653         st.Bind(0,"MessageDownloadMaxDaysBackward");\r
654         st.Bind(1,"5");\r
655         st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");\r
656         st.Step();\r
657         st.Reset();\r
658 \r
659         st.Bind(0,"MessageListDaysBackward");\r
660         st.Bind(1,"5");\r
661         st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");\r
662         st.Step();\r
663         st.Reset();\r
664 \r
665         st.Bind(0,"MaxPeerMessagesPerDay");\r
666         st.Bind(1,"200");\r
667         st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");\r
668         st.Step();\r
669         st.Reset();\r
670 \r
671         st.Bind(0,"MaxBoardListRequests");\r
672         st.Bind(1,"5");\r
673         st.Bind(2,"The maximum number of concurrent requests for new Board Lists.  Set to 0 to disable.");\r
674         st.Step();\r
675         st.Reset();\r
676 \r
677         st.Bind(0,"MaxBoardsPerMessage");\r
678         st.Bind(1,"8");\r
679         st.Bind(2,"The maximum number of boards a received message may be sent to.  Boards over this limit will be ignored.");\r
680         st.Step();\r
681         st.Reset();\r
682 \r
683         st.Bind(0,"SaveMessagesFromNewBoards");\r
684         st.Bind(1,"true");\r
685         st.Bind(2,"Set to true to automatically save messages posted to new boards.  Set to false to ignore messages to new boards.");\r
686         st.Step();\r
687         st.Reset();\r
688 \r
689         st.Bind(0,"ChangeMessageTrustOnReply");\r
690         st.Bind(1,"0");\r
691         st.Bind(2,"How much the local message trust level of an identity should change when you reply to one of their messages.");\r
692         st.Step();\r
693         st.Reset();\r
694 \r
695         st.Bind(0,"AddNewPostFromIdentities");\r
696         st.Bind(1,"false");\r
697         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
698         st.Step();\r
699         st.Reset();\r
700 \r
701         st.Bind(0,"DeleteMessagesOlderThan");\r
702         st.Bind(1,"180");\r
703         st.Bind(2,"Automatically delete messages older than this many days.");\r
704         st.Step();\r
705         st.Reset();\r
706 \r
707 }\r
708 \r
709 void SetupLogFile()\r
710 {\r
711         DateTime date;\r
712         std::string configval;\r
713         int loglevel;\r
714 \r
715         date.SetToGMTime();\r
716 \r
717         LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");\r
718         LogFile::Instance()->OpenFile();\r
719         LogFile::Instance()->SetWriteNewLine(true);\r
720         LogFile::Instance()->SetWriteDate(true);\r
721         LogFile::Instance()->SetWriteLogLevel(true);\r
722 \r
723         if(Option::Instance()->Get("LogLevel",configval)==false)\r
724         {\r
725                 configval="4";\r
726                 Option::Instance()->Set("LogLevel",configval);\r
727         }\r
728         if(StringFunctions::Convert(configval,loglevel)==false)\r
729         {\r
730                 loglevel=LogFile::LOGLEVEL_DEBUG;\r
731                 Option::Instance()->Set("LogLevel",loglevel);\r
732         }\r
733         LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);\r
734 }\r
735 \r
736 void SetupNetwork()\r
737 {\r
738 #ifdef _WIN32\r
739         WSAData wsadata;\r
740         WSAStartup(MAKEWORD(2,2),&wsadata);\r
741 #endif\r
742 }\r
743 \r
744 void Shutdown()\r
745 {\r
746         ThreadController::Instance()->ShutdownThreads();\r
747 \r
748         ShutdownNetwork();\r
749 \r
750         LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");\r
751         LogFile::Instance()->WriteNewLine();\r
752 }\r
753 \r
754 void ShutdownNetwork()\r
755 {\r
756 #ifdef _WIN32\r
757         WSACleanup();\r
758 #endif\r
759 }\r
760 \r
761 void SigHandler(int signum)\r
762 {\r
763         Shutdown();\r
764         exit(0);\r
765 }\r
766 \r
767 void FixCapitalBoardNames()\r
768 {\r
769         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
770 \r
771         SQLite3DB::Statement st=db->Prepare("SELECT BoardID,BoardName FROM tblBoard WHERE BoardID NOT IN (SELECT BoardID FROM tblAdministrationBoard);");\r
772         SQLite3DB::Statement st2=db->Prepare("SELECT BoardID FROM tblBoard WHERE BoardName=?;");\r
773         SQLite3DB::Statement del=db->Prepare("DELTE FROM tblBoard WHERE BoardID=?;");\r
774         SQLite3DB::Statement upd=db->Prepare("UPDATE tblBoard SET BoardName=? WHERE BoardID=?;");\r
775         SQLite3DB::Statement upd2=db->Prepare("UPDATE tblMessage SET ReplyBoardID=? WHERE ReplyBoardID=?;");\r
776         SQLite3DB::Statement upd3=db->Prepare("UPDATE tblMessageBoard SET BoardID=? WHERE BoardID=?;");\r
777 \r
778         st.Step();\r
779         while(st.RowReturned())\r
780         {\r
781                 int boardid=0;\r
782                 int newboardid=0;\r
783                 std::string name="";\r
784                 std::string lowername="";\r
785 \r
786                 st.ResultInt(0,boardid);\r
787                 st.ResultText(1,name);\r
788 \r
789                 lowername=name;\r
790                 StringFunctions::LowerCase(lowername,lowername);\r
791        \r
792                 if(name!=lowername)\r
793                 {\r
794                         st2.Bind(0,lowername);\r
795                         st2.Step();\r
796 \r
797                         if(st2.RowReturned())\r
798                         {\r
799                                 st2.ResultInt(0,newboardid);\r
800 \r
801                                 upd2.Bind(0,newboardid);\r
802                                 upd2.Bind(1,boardid);\r
803                                 upd2.Step();\r
804                                 upd2.Reset();\r
805 \r
806                                 upd3.Bind(0,newboardid);\r
807                                 upd3.Bind(1,boardid);\r
808                                 upd3.Step();\r
809                                 upd3.Reset();\r
810 \r
811                                 del.Bind(0,boardid);\r
812                                 del.Step();\r
813                                 del.Reset();\r
814                         }\r
815                         else\r
816                         {\r
817                                 upd.Bind(0,lowername);\r
818                                 upd.Bind(1,boardid);\r
819                                 upd.Step();\r
820                                 upd.Reset();\r
821                         }\r
822 \r
823                         st2.Reset();\r
824                 }\r
825        \r
826                 st.Step();\r
827         }\r
828 \r
829 }\r