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