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