version 0.1.10
[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         // 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
34 \r
35         db->Execute("CREATE TABLE IF NOT EXISTS tblDBVersion(\\r
36                                 Major                           INTEGER,\\r
37                                 Minor                           INTEGER\\r
38                                 );");\r
39 \r
40         SQLite3DB::Statement st=db->Prepare("SELECT Major,Minor FROM tblDBVersion;");\r
41         st.Step();\r
42         if(st.RowReturned())\r
43         {\r
44                 int major;\r
45                 int minor;\r
46                 st.ResultInt(0,major);\r
47                 st.ResultInt(1,minor);\r
48                 st.Finalize();\r
49                 if(major==1 && minor==0)\r
50                 {\r
51                         ConvertDB0100To0101();\r
52                 }\r
53         }\r
54         else\r
55         {\r
56                 db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,1);");\r
57         }\r
58 \r
59         db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\\r
60                                 Option                          TEXT UNIQUE,\\r
61                                 OptionValue                     TEXT NOT NULL,\\r
62                                 OptionDescription       TEXT\\r
63                                 );");\r
64 \r
65         db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
66                                 LocalIdentityID                 INTEGER PRIMARY KEY,\\r
67                                 Name                                    TEXT,\\r
68                                 PublicKey                               TEXT UNIQUE,\\r
69                                 PrivateKey                              TEXT UNIQUE,\\r
70                                 SingleUse                               BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
71                                 PublishTrustList                BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
72                                 PublishBoardList                BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
73                                 InsertingIdentity               BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\\r
74                                 LastInsertedIdentity    DATETIME,\\r
75                                 InsertingPuzzle                 BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\\r
76                                 LastInsertedPuzzle              DATETIME,\\r
77                                 InsertingTrustList              BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\\r
78                                 LastInsertedTrustList   DATETIME,\\r
79                                 InsertingBoardList              BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\\r
80                                 LastInsertedBoardList   DATETIME,\\r
81                                 InsertingMessageList    BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\\r
82                                 LastInsertedMessageList DATETIME\\r
83                                 );");\r
84 \r
85         db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\\r
86                                 LocalIdentityID         INTEGER,\\r
87                                 Day                                     DATE,\\r
88                                 InsertIndex                     INTEGER\\r
89                                 );");\r
90 \r
91         db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\\r
92                                 LocalIdentityID         INTEGER,\\r
93                                 Day                                     DATE,\\r
94                                 InsertIndex                     INTEGER\\r
95                                 );");\r
96 \r
97         db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\\r
98                                 IdentityID                      INTEGER,\\r
99                                 Day                                     DATE,\\r
100                                 RequestIndex            INTEGER,\\r
101                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
102                                 );");\r
103 \r
104         db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\\r
105                                 UUID                            TEXT UNIQUE,\\r
106                                 LocalIdentityID         INTEGER,\\r
107                                 Day                                     DATE,\\r
108                                 InsertIndex                     INTEGER,\\r
109                                 Type                            TEXT,\\r
110                                 MimeType                        TEXT,\\r
111                                 PuzzleData                      TEXT,\\r
112                                 PuzzleSolution          TEXT,\\r
113                                 FoundSolution           BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\\r
114                                 );");\r
115 \r
116         db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\\r
117                                 IdentityID                      INTEGER PRIMARY KEY,\\r
118                                 PublicKey                       TEXT UNIQUE,\\r
119                                 Name                            TEXT,\\r
120                                 SingleUse                       BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
121                                 PublishTrustList        BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
122                                 PublishBoardList        BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
123                                 DateAdded                       DATETIME,\\r
124                                 LastSeen                        DATETIME,\\r
125                                 LocalMessageTrust       INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT 50,\\r
126                                 PeerMessageTrust        INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT 50,\\r
127                                 LocalTrustListTrust     INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT 50,\\r
128                                 PeerTrustListTrust      INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT 50\\r
129                                 );");\r
130 \r
131         db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\\r
132                                 IdentityID                      INTEGER,\\r
133                                 Day                                     DATE,\\r
134                                 RequestIndex            INTEGER,\\r
135                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
136                                 );");\r
137 \r
138         db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\\r
139                                 IdentityID                      INTEGER,\\r
140                                 Day                                     DATE,\\r
141                                 RequestIndex            INTEGER,\\r
142                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\\r
143                                 UUID                            TEXT UNIQUE,\\r
144                                 Type                            TEXT,\\r
145                                 MimeType                        TEXT,\\r
146                                 PuzzleData                      TEXT\\r
147                                 );");\r
148 \r
149         db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\\r
150                                 LocalIdentityID         INTEGER,\\r
151                                 Day                                     DATE,\\r
152                                 UUID                            TEXT UNIQUE,\\r
153                                 Solution                        TEXT,\\r
154                                 Inserted                        BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
155                                 );");\r
156 \r
157         db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\\r
158                                 IdentityID                      INTEGER,\\r
159                                 TargetIdentityID        INTEGER,\\r
160                                 MessageTrust            INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\\r
161                                 TrustListTrust          INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100)\\r
162                                 );");\r
163 \r
164         db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\\r
165                                 BoardID                         INTEGER PRIMARY KEY,\\r
166                                 BoardName                       TEXT UNIQUE,\\r
167                                 BoardDescription        TEXT,\\r
168                                 DateAdded                       DATETIME\\r
169                                 );");\r
170 \r
171         db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01');");\r
172         db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01');");\r
173         db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01');");\r
174         db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01');");\r
175 \r
176         db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\\r
177                                 MessageID                       INTEGER PRIMARY KEY,\\r
178                                 IdentityID                      INTEGER,\\r
179                                 FromName                        TEXT,\\r
180                                 MessageDate                     DATE,\\r
181                                 MessageTime                     TIME,\\r
182                                 Subject                         TEXT,\\r
183                                 MessageUUID                     TEXT UNIQUE,\\r
184                                 ReplyBoardID            INTEGER,\\r
185                                 Body                            TEXT\\r
186                                 );");\r
187 \r
188         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\\r
189                                 MessageID                       INTEGER,\\r
190                                 ReplyToMessageUUID      TEXT,\\r
191                                 ReplyOrder                      INTEGER\\r
192                                 );");\r
193 \r
194         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\\r
195                                 MessageID                       INTEGER,\\r
196                                 BoardID                         INTEGER\\r
197                                 );");\r
198 \r
199         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\\r
200                                 IdentityID                      INTEGER,\\r
201                                 Day                                     DATE,\\r
202                                 RequestIndex            INTEGER,\\r
203                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
204                                 );");\r
205 \r
206         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\\r
207                                 IdentityID                      INTEGER,\\r
208                                 Day                                     DATE,\\r
209                                 RequestIndex            INTEGER,\\r
210                                 FromMessageList         BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\\r
211                                 Found                           BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\\r
212                                 );");\r
213 \r
214         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\\r
215                                 LocalIdentityID         INTEGER,\\r
216                                 Day                                     DATE,\\r
217                                 InsertIndex                     INTEGER,\\r
218                                 MessageUUID                     TEXT UNIQUE,\\r
219                                 MessageXML                      TEXT,\\r
220                                 Inserted                        BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
221                                 );");\r
222 \r
223         db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\\r
224                                 LocalIdentityID         INTEGER,\\r
225                                 Day                                     DATE,\\r
226                                 InsertIndex                     INTEGER,\\r
227                                 Inserted                        BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\\r
228                                 );");\r
229 \r
230         db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\\r
231                                 BoardID                                         INTEGER UNIQUE,\\r
232                                 ModifyLocalMessageTrust         INTEGER,\\r
233                                 ModifyLocalTrustListTrust       INTEGER\\r
234                                 );");\r
235 \r
236         // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed\r
237         db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\\r
238                                 LocalIdentityID         INTEGER,\\r
239                                 Date                            DATETIME\\r
240                                 );");\r
241 \r
242         // low / high / message count for each board\r
243         db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \\r
244                                 SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \\r
245                                 FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \\r
246                                 WHERE MessageID>=0 OR MessageID IS NULL \\r
247                                 GROUP BY tblBoard.BoardID;");\r
248 \r
249         // calculates peer trust\r
250         db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \\r
251                                 SELECT TargetIdentityID, \\r
252                                 ROUND(SUM(MessageTrust*(LocalMessageTrust/100.0))/SUM(LocalMessageTrust/100.0),0) AS 'PeerMessageTrust', \\r
253                                 ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(LocalTrustListTrust/100.0),0) AS 'PeerTrustListTrust' \\r
254                                 FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \\r
255                                 WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \\r
256                                 AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \\r
257                                 GROUP BY TargetIdentityID;");\r
258 \r
259         /*\r
260                 These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed\r
261                 All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class\r
262         */\r
263         // drop existing triggers\r
264         db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");\r
265         db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");\r
266         db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");\r
267         db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");\r
268 /*\r
269         // update PeerTrustLevel when deleting a record from tblPeerTrust\r
270         db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \\r
271                                 FOR EACH ROW \\r
272                                 BEGIN \\r
273                                         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
274                                 END;");\r
275 \r
276         // update PeerTrustLevel when inserting a record into tblPeerTrust\r
277         db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \\r
278                                 FOR EACH ROW \\r
279                                 BEGIN \\r
280                                         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
281                                 END;");\r
282 \r
283         // update PeerTrustLevel when updating a record in tblPeerTrust\r
284         db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \\r
285                                 FOR EACH ROW \\r
286                                 BEGIN \\r
287                                         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
288                                         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
289                                 END;");\r
290 \r
291         // 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
292         db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \\r
293                                 FOR EACH ROW \\r
294                                 BEGIN \\r
295                                         UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\\r
296                                 END;");\r
297 */\r
298 \r
299         db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \\r
300                                 FOR EACH ROW \\r
301                                 BEGIN \\r
302                                         DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\\r
303                                         DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\\r
304                                 END;");\r
305 \r
306         db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \\r
307                                 FOR EACH ROW \\r
308                                 BEGIN \\r
309                                         DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\\r
310                                         DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\\r
311                                         DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\\r
312                                         DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\\r
313                                         DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\\r
314                                         DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\\r
315                                 END;");\r
316 \r
317         db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \\r
318                                 FOR EACH ROW \\r
319                                 BEGIN \\r
320                                         DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
321                                         DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
322                                         DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
323                                         DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
324                                         DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
325                                         DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\\r
326                                 END;");\r
327 \r
328         // delete introduction puzzles that were half-way inserted\r
329         db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");\r
330 \r
331         // delete stale introduction puzzles (2 or more days old)\r
332         date.SetToGMTime();\r
333         date.Add(0,0,0,-2);\r
334         db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");\r
335         db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");\r
336 \r
337         date.SetToGMTime();\r
338         // insert SomeDude's public key\r
339         db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw,iXez4j3qCpd596TxXiJgZyTq9o-CElEuJxm~jNNZAuA,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");\r
340         // insert Shadow Panther's public key\r
341         db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");\r
342         // insert garfield's public key\r
343         db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");\r
344 \r
345 }\r
346 \r
347 void ConvertDB0100To0101()\r
348 {\r
349         // added unique constraint to public and private key\r
350         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
351         db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");\r
352         db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");\r
353         db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\\r
354                                 LocalIdentityID                 INTEGER PRIMARY KEY,\\r
355                                 Name                                    TEXT,\\r
356                                 PublicKey                               TEXT UNIQUE,\\r
357                                 PrivateKey                              TEXT UNIQUE,\\r
358                                 SingleUse                               BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\\r
359                                 PublishTrustList                BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\\r
360                                 PublishBoardList                BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\\r
361                                 InsertingIdentity               BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\\r
362                                 LastInsertedIdentity    DATETIME,\\r
363                                 InsertingPuzzle                 BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\\r
364                                 LastInsertedPuzzle              DATETIME,\\r
365                                 InsertingTrustList              BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\\r
366                                 LastInsertedTrustList   DATETIME,\\r
367                                 InsertingBoardList              BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\\r
368                                 LastInsertedBoardList   DATETIME,\\r
369                                 InsertingMessageList    BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\\r
370                                 LastInsertedMessageList DATETIME\\r
371                                 );");\r
372         db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");\r
373         db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");\r
374         db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");\r
375 }\r
376 \r
377 void SetupDefaultOptions()\r
378 {\r
379         // 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
380 \r
381         std::ostringstream tempstr;     // must set tempstr to "" between db inserts\r
382         SQLite3DB::DB *db=SQLite3DB::DB::Instance();\r
383         SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");\r
384 \r
385         // LogLevel\r
386         tempstr.str("");\r
387         tempstr << LogFile::LOGLEVEL_DEBUG;\r
388         st.Bind(0,"LogLevel");\r
389         st.Bind(1,tempstr.str());\r
390         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
391         st.Step();\r
392         st.Reset();\r
393 \r
394         // NNTPListenPort\r
395         st.Bind(0,"NNTPListenPort");\r
396         st.Bind(1,"1119");\r
397         st.Bind(2,"The port that the NNTP service will listen for incoming connections.");\r
398         st.Step();\r
399         st.Reset();\r
400 \r
401         // NNTPBindAddresses\r
402         st.Bind(0,"NNTPBindAddresses");\r
403         st.Bind(1,"localhost");\r
404         st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");\r
405         st.Step();\r
406         st.Reset();\r
407 \r
408         st.Bind(0,"NNTPAllowPost");\r
409         st.Bind(1,"true");\r
410         st.Bind(2,"Allow posting messages from NNTP.  Setting to false will make the newsgroups read only.");\r
411         st.Step();\r
412         st.Reset();\r
413 \r
414         // StartNNTP\r
415         st.Bind(0,"StartNNTP");\r
416         st.Bind(1,"true");\r
417         st.Bind(2,"Start NNTP server.");\r
418         st.Step();\r
419         st.Reset();\r
420 \r
421         st.Bind(0,"StartHTTP");\r
422         st.Bind(1,"true");\r
423         st.Bind(2,"Start HTTP server.");\r
424         st.Step();\r
425         st.Reset();\r
426 \r
427         st.Bind(0,"HTTPListenPort");\r
428         st.Bind(1,"8080");\r
429         st.Bind(2,"Port HTTP server will listen on.");\r
430         st.Step();\r
431         st.Reset();\r
432 \r
433         // StartFreenetUpdater\r
434         st.Bind(0,"StartFreenetUpdater");\r
435         st.Bind(1,"true");\r
436         st.Bind(2,"Start Freenet Updater thread.");\r
437         st.Step();\r
438         st.Reset();\r
439 \r
440         // FCPHost\r
441         st.Bind(0,"FCPHost");\r
442         st.Bind(1,"127.0.0.1");\r
443         st.Bind(2,"Host name or address of Freenet node.");\r
444         st.Step();\r
445         st.Reset();\r
446 \r
447         // FCPPort\r
448         st.Bind(0,"FCPPort");\r
449         st.Bind(1,"9481");\r
450         st.Bind(2,"The port that Freenet is listening for FCP connections on.");\r
451         st.Step();\r
452         st.Reset();\r
453 \r
454         st.Bind(0,"MessageBase");\r
455         st.Bind(1,"fms");\r
456         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
457         st.Step();\r
458         st.Reset();\r
459 \r
460         st.Bind(0,"MaxIdentityRequests");\r
461         st.Bind(1,"5");\r
462         st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");\r
463         st.Step();\r
464         st.Reset();\r
465 \r
466         st.Bind(0,"MaxIdentityIntroductionRequests");\r
467         st.Bind(1,"5");\r
468         st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files.  Each identity may have multiple requests pending.");\r
469         st.Step();\r
470         st.Reset();\r
471 \r
472         st.Bind(0,"MaxIntroductionPuzzleRequests");\r
473         st.Bind(1,"5");\r
474         st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");\r
475         st.Step();\r
476         st.Reset();\r
477 \r
478         st.Bind(0,"MaxTrustListRequests");\r
479         st.Bind(1,"5");\r
480         st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");\r
481         st.Step();\r
482         st.Reset();\r
483 \r
484         st.Bind(0,"MaxMessageListRequests");\r
485         st.Bind(1,"5");\r
486         st.Bind(2,"Maximum number of concurrent requests for new Message Lists");\r
487         st.Step();\r
488         st.Reset();\r
489 \r
490         st.Bind(0,"MaxMessageRequests");\r
491         st.Bind(1,"20");\r
492         st.Bind(2,"Maximum number of concurrent requests for new Messages");\r
493         st.Step();\r
494         st.Reset();\r
495 \r
496         st.Bind(0,"MinLocalMessageTrust");\r
497         st.Bind(1,"50");\r
498         st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");\r
499         st.Step();\r
500         st.Reset();\r
501 \r
502         st.Bind(0,"MinPeerMessageTrust");\r
503         st.Bind(1,"30");\r
504         st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");\r
505         st.Step();\r
506         st.Reset();\r
507 \r
508         st.Bind(0,"MinLocalTrustListTrust");\r
509         st.Bind(1,"51");\r
510         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
511         st.Step();\r
512         st.Reset();\r
513 \r
514         st.Bind(0,"MinPeerTrustListTrust");\r
515         st.Bind(1,"30");\r
516         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
517         st.Step();\r
518         st.Reset();\r
519 \r
520         st.Bind(0,"MessageDownloadMaxDaysBackward");\r
521         st.Bind(1,"5");\r
522         st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");\r
523         st.Step();\r
524         st.Reset();\r
525 \r
526         st.Bind(0,"MessageListDaysBackward");\r
527         st.Bind(1,"5");\r
528         st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");\r
529         st.Step();\r
530         st.Reset();\r
531 \r
532         st.Bind(0,"MaxPeerMessagesPerDay");\r
533         st.Bind(1,"200");\r
534         st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");\r
535         st.Step();\r
536         st.Reset();\r
537 \r
538 }\r
539 \r
540 void SetupLogFile()\r
541 {\r
542         DateTime date;\r
543         std::string configval;\r
544         int loglevel;\r
545 \r
546         date.SetToGMTime();\r
547 \r
548         LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");\r
549         LogFile::Instance()->OpenFile();\r
550         LogFile::Instance()->SetWriteNewLine(true);\r
551         LogFile::Instance()->SetWriteDate(true);\r
552         LogFile::Instance()->SetWriteLogLevel(true);\r
553 \r
554         if(Option::Instance()->Get("LogLevel",configval)==false)\r
555         {\r
556                 configval="4";\r
557                 Option::Instance()->Set("LogLevel",configval);\r
558         }\r
559         if(StringFunctions::Convert(configval,loglevel)==false)\r
560         {\r
561                 loglevel=LogFile::LOGLEVEL_DEBUG;\r
562                 Option::Instance()->Set("LogLevel",loglevel);\r
563         }\r
564         LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);\r
565 }\r
566 \r
567 void SetupNetwork()\r
568 {\r
569 #ifdef _WIN32\r
570         WSAData wsadata;\r
571         WSAStartup(MAKEWORD(2,2),&wsadata);\r
572 #endif\r
573 }\r
574 \r
575 void Shutdown()\r
576 {\r
577         ThreadController::Instance()->ShutdownThreads();\r
578 \r
579         ShutdownNetwork();\r
580 \r
581         LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");\r
582         LogFile::Instance()->WriteNewLine();\r
583 }\r
584 \r
585 void ShutdownNetwork()\r
586 {\r
587 #ifdef _WIN32\r
588         WSACleanup();\r
589 #endif\r
590 }\r
591 \r
592 void SigHandler(int signum)\r
593 {\r
594         Shutdown();\r
595         exit(0);\r
596 }\r
597 \r
598 /*\r
599 void ShutdownThreads(std::vector<PThread::Thread *> &threads)\r
600 {\r
601         std::vector<PThread::Thread *>::iterator i;\r
602         for(i=threads.begin(); i!=threads.end(); i++)\r
603         {\r
604                 (*i)->Cancel();\r
605         }\r
606 \r
607         for(i=threads.begin(); i!=threads.end(); i++)\r
608         {\r
609                 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ShutdownThreads waiting for thread to exit.");\r
610                 //(*i)->wait();\r
611                 (*i)->Join();\r
612                 delete (*i);\r
613         }\r
614 \r
615         threads.clear();\r
616 \r
617 }\r
618 \r
619 void StartThreads(std::vector<PThread::Thread *> &threads)\r
620 {\r
621         std::string startfreenet;\r
622         std::string startnntp;\r
623         std::string starthttp;\r
624 \r
625         if(Option::Instance()->Get("StartFreenetUpdater",startfreenet)==false)\r
626         {\r
627                 startfreenet="true";\r
628                 Option::Instance()->Set("StartFreenetUpdater","true");\r
629         }\r
630 \r
631         if(Option::Instance()->Get("StartNNTP",startnntp)==false)\r
632         {\r
633                 startnntp="true";\r
634                 Option::Instance()->Set("StartNNTP","true");\r
635         }\r
636 \r
637         if(Option::Instance()->Get("StartHTTP",starthttp)==false)\r
638         {\r
639                 starthttp="true";\r
640                 Option::Instance()->Set("StartHTTP","true");\r
641         }\r
642 \r
643         if(startfreenet=="true")\r
644         {\r
645                 PThread::Thread *t=new PThread::Thread(new FreenetMasterThread());\r
646                 threads.push_back(t);\r
647         }\r
648 \r
649         if(startnntp=="true")\r
650         {\r
651                 PThread::Thread *t=new PThread::Thread(new NNTPListener());\r
652                 threads.push_back(t);\r
653         }\r
654 \r
655         if(starthttp=="true")\r
656         {\r
657                 PThread::Thread *t=new PThread::Thread(new HTTPThread());\r
658                 threads.push_back(t);\r
659         }\r
660 \r
661 }\r
662 */\r