d2693f58fa3a54229e9aeceb90b6202013d9cc00
[fms.git] / src / message.cpp
1 #include "../include/message.h"\r
2 #include "../include/nntp/mime/Mime.h"\r
3 #include "../include/uuidgenerator.h"\r
4 #include "../include/stringfunctions.h"\r
5 #include "../include/freenet/messagexml.h"\r
6 #include "../include/option.h"\r
7 \r
8 #include <algorithm>\r
9 \r
10 #ifdef DO_CHARSET_CONVERSION\r
11         #include "../include/charsetconverter.h"\r
12 #endif\r
13 \r
14 #ifdef XMEM\r
15         #include <xmem.h>\r
16 #endif\r
17 \r
18 Message::Message()\r
19 {\r
20         Initialize();\r
21 }\r
22 \r
23 Message::Message(const long messageid)\r
24 {\r
25         Load(messageid);\r
26 }\r
27 \r
28 const bool Message::CheckForAdministrationBoard(const std::vector<std::string> &boards)\r
29 {\r
30         std::string name;\r
31         SQLite3DB::Statement st=m_db->Prepare("SELECT BoardName FROM tblBoard INNER JOIN tblAdministrationBoard ON tblBoard.BoardID=tblAdministrationBoard.BoardID;");\r
32         st.Step();\r
33         \r
34         while(st.RowReturned())\r
35         {\r
36                 st.ResultText(0,name);\r
37 \r
38                 if(std::find(boards.begin(),boards.end(),name)!=boards.end())\r
39                 {\r
40                         return true;\r
41                 }\r
42                 \r
43                 st.Step();\r
44         }\r
45 \r
46         return false;\r
47 }\r
48 \r
49 const int Message::FindLocalIdentityID(const std::string &name)\r
50 {\r
51         SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID FROM tblLocalIdentity WHERE Name=?;");\r
52         st.Bind(0,name);\r
53         st.Step();\r
54         if(st.RowReturned())\r
55         {\r
56                 int result=-1;\r
57                 st.ResultInt(0,result);\r
58                 return result;\r
59         }\r
60         else\r
61         {\r
62                 if(m_addnewpostfromidentities==true)\r
63                 {\r
64                         DateTime now;\r
65                         now.SetToGMTime();\r
66                         st=m_db->Prepare("INSERT INTO tblLocalIdentity(Name) VALUES(?);");\r
67                         st.Bind(0,name);\r
68                         st.Step(true);\r
69                         return st.GetLastInsertRowID();\r
70                 }\r
71                 else\r
72                 {\r
73                         return -1;\r
74                 }\r
75         }\r
76 }\r
77 \r
78 const std::string Message::GetNNTPArticleID() const\r
79 {\r
80         // old message - before 0.1.12 - doesn't have @domain so add @freenetproject.org\r
81         if(m_messageuuid.find("@")==std::string::npos)\r
82         {\r
83                 return "<"+m_messageuuid+"@freenetproject.org>";\r
84         }\r
85         else\r
86         {\r
87                 return "<"+m_messageuuid+">";\r
88         }\r
89 }\r
90 \r
91 const std::string Message::GetNNTPBody() const\r
92 {\r
93         return m_body;\r
94 }\r
95 \r
96 const std::string Message::GetNNTPHeaders() const\r
97 {\r
98         std::string rval("");\r
99 \r
100         rval+="From: "+m_fromname+"\r\n";\r
101         rval+="Newsgroups: ";\r
102         for(std::vector<std::string>::const_iterator i=m_boards.begin(); i!=m_boards.end(); i++)\r
103         {\r
104                 if(i!=m_boards.begin())\r
105                 {\r
106                         rval+=",";\r
107                 }\r
108                 rval+=(*i);\r
109         }\r
110         rval+="\r\n";\r
111         rval+="Subject: "+m_subject+"\r\n";\r
112         // format time as  : Wdy, DD Mon YY HH:MM:SS TIMEZONE\r
113         rval+="Date: "+m_datetime.Format("%a, %d %b %y %H:%M:%S -0000")+"\r\n";\r
114         if(m_inreplyto.size()>0)\r
115         {\r
116                 rval+="References: ";\r
117                 for(std::map<long,std::string>::const_reverse_iterator j=m_inreplyto.rbegin(); j!=m_inreplyto.rend(); j++)\r
118                 {\r
119                         if(j!=m_inreplyto.rend())\r
120                         {\r
121                                 rval+=" ";\r
122                         }\r
123                         // old message - before 0.1.12 - doesn't have @domain so add @freenetproject.org\r
124                         if((*j).second.find("@")==std::string::npos)\r
125                         {\r
126                                 rval+="<"+(*j).second+"@freenetproject.org>";\r
127                         }\r
128                         else\r
129                         {\r
130                                 rval+="<"+(*j).second+">";\r
131                         }\r
132                 }\r
133                 rval+="\r\n";\r
134         }\r
135         rval+="Followup-To: "+m_replyboardname+"\r\n";\r
136         rval+="Path: freenet\r\n";\r
137         rval+="Message-ID: "+GetNNTPArticleID()+"\r\n";\r
138         rval+="Content-Type: text/plain; charset=UTF-8\r\n";\r
139 \r
140         return rval;\r
141 }\r
142 \r
143 void Message::HandleAdministrationMessage()\r
144 {\r
145         // only continue if this message was actually a reply to another message\r
146         if(m_inreplyto.size()>0)\r
147         {\r
148                 int localidentityid=-1;\r
149                 int boardid=0;\r
150                 std::string boardname="";\r
151                 std::string identityname="";\r
152                 int identityid;\r
153                 int changemessagetrust=0;\r
154                 int changetrustlisttrust=0;\r
155                 int origmessagetrust=0;\r
156                 int origtrustlisttrust=0;\r
157                 SQLite3DB::Statement st=m_db->Prepare("SELECT tblBoard.BoardID,BoardName,ModifyLocalMessageTrust,ModifyLocalTrustListTrust FROM tblBoard INNER JOIN tblAdministrationBoard ON tblBoard.BoardID=tblAdministrationBoard.BoardID;");\r
158                 st.Step();\r
159 \r
160                 localidentityid=FindLocalIdentityID(m_fromname);\r
161 \r
162                 while(st.RowReturned() && localidentityid!=-1)\r
163                 {\r
164                         st.ResultInt(0,boardid);\r
165                         st.ResultText(1,boardname);\r
166                         st.ResultInt(2,changemessagetrust);\r
167                         st.ResultInt(3,changetrustlisttrust);\r
168 \r
169                         if(std::find(m_boards.begin(),m_boards.end(),boardname)!=m_boards.end())\r
170                         {\r
171                                 SQLite3DB::Statement origmess=m_db->Prepare("SELECT tblIdentity.IdentityID,tblIdentity.Name,tblIdentityTrust.LocalMessageTrust,tblIdentityTrust.LocalTrustListTrust FROM tblIdentity INNER JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID LEFT JOIN (SELECT IdentityID,LocalMessageTrust,LocalTrustListTrust FROM tblIdentityTrust WHERE LocalIdentityID=?) AS 'tblIdentityTrust' ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID WHERE tblMessage.MessageUUID=?;");\r
172                                 origmess.Bind(0,localidentityid);\r
173                                 origmess.Bind(1,m_inreplyto[0]);\r
174                                 origmess.Step();\r
175 \r
176                                 if(origmess.RowReturned())\r
177                                 {\r
178                                         origmess.ResultInt(0,identityid);\r
179                                         origmess.ResultText(1,identityname);\r
180                                         if(origmess.ResultNull(2)==false)\r
181                                         {\r
182                                                 origmess.ResultInt(2,origmessagetrust);\r
183                                         }\r
184                                         else\r
185                                         {\r
186                                                 //origmessagetrust=m_minlocalmessagetrust;\r
187                                                 origmessagetrust=50;\r
188                                         }\r
189                                         if(origmess.ResultNull(3)==false)\r
190                                         {\r
191                                                 origmess.ResultInt(3,origtrustlisttrust);\r
192                                         }\r
193                                         else\r
194                                         {\r
195                                                 //origtrustlisttrust=m_minlocaltrustlisttrust;\r
196                                                 origtrustlisttrust=50;\r
197                                         }\r
198 \r
199                                         origmessagetrust+=changemessagetrust;\r
200                                         origtrustlisttrust+=changetrustlisttrust;\r
201 \r
202                                         origmessagetrust<0 ? origmessagetrust=0 : false;\r
203                                         origmessagetrust>100 ? origmessagetrust=100 : false;\r
204                                         origtrustlisttrust<0 ? origtrustlisttrust=0 : false;\r
205                                         origtrustlisttrust>100 ? origtrustlisttrust=100 : false;\r
206 \r
207                                         // make sure we have a record in tblIdentityTrust\r
208                                         SQLite3DB::Statement ins=m_db->Prepare("INSERT INTO tblIdentityTrust(LocalIdentityID,IdentityID) VALUES(?,?);");\r
209                                         ins.Bind(0,localidentityid);\r
210                                         ins.Bind(1,identityid);\r
211                                         ins.Step();\r
212 \r
213                                         // update new trust levels\r
214                                         SQLite3DB::Statement update=m_db->Prepare("UPDATE tblIdentityTrust SET LocalMessageTrust=?, LocalTrustListTrust=? WHERE IdentityID=? AND LocalIdentityID=?;");\r
215                                         update.Bind(0,origmessagetrust);\r
216                                         update.Bind(1,origtrustlisttrust);\r
217                                         update.Bind(2,identityid);\r
218                                         update.Bind(3,localidentityid);\r
219                                         update.Step();\r
220 \r
221                                         // insert message to show what id was changed and what current levels are\r
222                                         int lastid=0;\r
223                                         std::string messagebody;\r
224                                         std::string messagetruststr="";\r
225                                         std::string trustlisttruststr="";\r
226                                         UUIDGenerator uuid;\r
227                                         DateTime now;\r
228                                         now.SetToGMTime();\r
229                                         StringFunctions::Convert(origmessagetrust,messagetruststr);\r
230                                         StringFunctions::Convert(origtrustlisttrust,trustlisttruststr);\r
231                                         messagebody="Trust List of "+m_fromname+"\r\n";\r
232                                         messagebody="Trust Changed for "+identityname+"\r\n";\r
233                                         messagebody+="Local Message Trust : "+messagetruststr+"\r\n";\r
234                                         messagebody+="Local Trust List Trust : "+trustlisttruststr+"\r\n";\r
235                                         SQLite3DB::Statement insert=m_db->Prepare("INSERT INTO tblMessage(FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body) VALUES('FMS',?,?,?,?,?,?);");\r
236                                         insert.Bind(0,now.Format("%Y-%m-%d"));\r
237                                         insert.Bind(1,now.Format("%H:%M:%S"));\r
238                                         insert.Bind(2,identityname+" Trust Changed");\r
239                                         insert.Bind(3,uuid.Generate());\r
240                                         insert.Bind(4,boardid);\r
241                                         insert.Bind(5,messagebody);\r
242                                         insert.Step(true);\r
243                                         lastid=insert.GetLastInsertRowID();\r
244 \r
245                                         insert=m_db->Prepare("INSERT INTO tblMessageBoard(MessageID,BoardID) VALUES(?,?);");\r
246                                         insert.Bind(0,lastid);\r
247                                         insert.Bind(1,boardid);\r
248                                         insert.Step();\r
249 \r
250                                         m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"Message::HandleAdministrationMessage updated "+identityname+" to "+messagetruststr+" , "+trustlisttruststr);\r
251 \r
252                                 }\r
253                         }\r
254 \r
255                         st.Step();\r
256                 }\r
257         }\r
258 \r
259 }\r
260 \r
261 void Message::HandleChangeTrust()\r
262 {\r
263         if(m_changemessagetrustonreply!=0 && m_inreplyto.size()>0)\r
264         {\r
265                 int localidentityid=FindLocalIdentityID(m_fromname);\r
266                 if(localidentityid!=-1)\r
267                 {\r
268                         // make sure we have a record in tblIdentityTrust\r
269                         SQLite3DB::Statement ins=m_db->Prepare("INSERT INTO tblIdentityTrust(LocalIdentityID,IdentityID) VALUES(?,?);");\r
270 \r
271                         SQLite3DB::Statement st=m_db->Prepare("SELECT tblIdentity.IdentityID,tblIdentityTrust.LocalMessageTrust FROM tblIdentity INNER JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID LEFT JOIN (SELECT IdentityID,LocalMessageTrust FROM tblIdentityTrust WHERE LocalIdentityID=?) AS 'tblIdentityTrust' ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID WHERE tblMessage.MessageUUID=?;");\r
272                         st.Bind(0,localidentityid);\r
273                         st.Bind(1,m_inreplyto[0]);\r
274                         st.Step();\r
275                         if(st.RowReturned())\r
276                         {\r
277                                 int identityid=0;\r
278                                 int localmessagetrust=0;\r
279 \r
280                                 st.ResultInt(0,identityid);\r
281                                 if(st.ResultNull(1)==false)\r
282                                 {\r
283                                         st.ResultInt(1,localmessagetrust);\r
284                                 }\r
285                                 else\r
286                                 {\r
287                                         //localmessagetrust=m_minlocalmessagetrust;\r
288                                         localmessagetrust=50;\r
289                                 }\r
290 \r
291                                 localmessagetrust+=m_changemessagetrustonreply;\r
292                                 if(localmessagetrust<0)\r
293                                 {\r
294                                         localmessagetrust=0;\r
295                                 }\r
296                                 if(localmessagetrust>100)\r
297                                 {\r
298                                         localmessagetrust=100;\r
299                                 }\r
300 \r
301                                 ins.Bind(0,localidentityid);\r
302                                 ins.Bind(1,identityid);\r
303                                 ins.Step();\r
304 \r
305                                 SQLite3DB::Statement st2=m_db->Prepare("UPDATE tblIdentityTrust SET LocalMessageTrust=? WHERE IdentityID=? AND LocalIdentityID=?;");\r
306                                 st2.Bind(0,localmessagetrust);\r
307                                 st2.Bind(1,identityid);\r
308                                 st2.Bind(2,localidentityid);\r
309                                 st2.Step();\r
310 \r
311                         }\r
312                 }\r
313         }\r
314 }\r
315 \r
316 void Message::Initialize()\r
317 {\r
318         std::string tempval="";\r
319         m_messageid=-1;\r
320         m_messageuuid="";\r
321         m_subject="";\r
322         m_body="";\r
323         m_replyboardname="";\r
324         m_datetime.Set();\r
325         m_fromname="";\r
326         m_boards.clear();\r
327         m_inreplyto.clear();\r
328         m_changemessagetrustonreply=0;\r
329         Option::Instance()->Get("ChangeMessageTrustOnReply",tempval);\r
330         StringFunctions::Convert(tempval,m_changemessagetrustonreply);\r
331         Option::Instance()->Get("AddNewPostFromIdentities",tempval);\r
332         if(tempval=="true")\r
333         {\r
334                 m_addnewpostfromidentities=true;\r
335         }\r
336         else\r
337         {\r
338                 m_addnewpostfromidentities=false;\r
339         }\r
340         tempval="50";\r
341         Option::Instance()->Get("MinLocalMessageTrust",tempval);\r
342         StringFunctions::Convert(tempval,m_minlocalmessagetrust);\r
343         tempval="51";\r
344         Option::Instance()->Get("MinLocalTrustListTrust",tempval);\r
345         StringFunctions::Convert(tempval,m_minlocaltrustlisttrust);\r
346 }\r
347 \r
348 const bool Message::Load(const long messageid, const long boardid)\r
349 {\r
350         \r
351         Initialize();\r
352 \r
353         std::string sql;\r
354         \r
355         sql="SELECT tblMessage.MessageID, MessageUUID, Subject, Body, tblBoard.BoardName, MessageDate, MessageTime, FromName FROM tblMessage INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID INNER JOIN tblBoard ON tblMessage.ReplyBoardID=tblBoard.BoardID WHERE tblMessage.MessageID=?";\r
356         if(boardid!=-1)\r
357         {\r
358                 sql+=" AND tblMessageBoard.BoardID=?";\r
359         }\r
360         sql+=";";\r
361 \r
362         SQLite3DB::Statement st=m_db->Prepare(sql);\r
363         st.Bind(0,messageid);\r
364         if(boardid!=-1)\r
365         {\r
366                 st.Bind(1,boardid);\r
367         }\r
368         st.Step();\r
369 \r
370         if(st.RowReturned())\r
371         {\r
372                 std::string tempdate;\r
373                 std::string temptime;\r
374                 int tempint=-1;\r
375                 st.ResultInt(0,tempint);\r
376                 m_messageid=tempint;\r
377                 st.ResultText(1,m_messageuuid);\r
378                 st.ResultText(2,m_subject);\r
379                 st.ResultText(3,m_body);\r
380                 st.ResultText(4,m_replyboardname);\r
381                 st.ResultText(5,tempdate);\r
382                 st.ResultText(6,temptime);\r
383                 m_datetime.Set(tempdate + " " + temptime);\r
384                 st.ResultText(7,m_fromname);\r
385                 st.Finalize();\r
386 \r
387                 // strip off any \r\n in subject\r
388                 m_subject=StringFunctions::Replace(m_subject,"\r\n","");\r
389 \r
390                 // get board list\r
391                 st=m_db->Prepare("SELECT tblBoard.BoardName FROM tblBoard INNER JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID WHERE tblMessageBoard.MessageID=?;");\r
392                 st.Bind(0,messageid);\r
393                 st.Step();\r
394                 while(st.RowReturned())\r
395                 {\r
396                         std::string tempval;\r
397                         st.ResultText(0,tempval);\r
398                         m_boards.push_back(tempval);\r
399                         st.Step();\r
400                 }\r
401                 st.Finalize();\r
402 \r
403                 // get in reply to list\r
404                 st=m_db->Prepare("SELECT ReplyToMessageUUID, ReplyOrder FROM tblMessageReplyTo INNER JOIN tblMessage ON tblMessageReplyTo.MessageID=tblMessage.MessageID WHERE tblMessage.MessageID=?;");\r
405                 st.Bind(0,messageid);\r
406                 st.Step();\r
407                 while(st.RowReturned())\r
408                 {\r
409                         std::string tempval;\r
410                         int tempint;\r
411                         st.ResultText(0,tempval);\r
412                         st.ResultInt(1,tempint);\r
413                         m_inreplyto[tempint]=tempval;\r
414                         st.Step();\r
415                 }\r
416                 st.Finalize();\r
417 \r
418                 return true;\r
419         }\r
420         else\r
421         {\r
422                 return false;\r
423         }\r
424 \r
425 }\r
426 \r
427 const bool Message::Load(const std::string &messageuuid)\r
428 {\r
429 \r
430         std::string uuid=messageuuid;\r
431 \r
432         if(uuid.size()>0 && uuid[0]=='<')\r
433         {\r
434                 uuid.erase(0,1);\r
435         }\r
436         if(uuid.size()>0 && uuid[uuid.size()-1]=='>')\r
437         {\r
438                 uuid.erase(uuid.size()-1);\r
439         }\r
440         if(uuid.find("@freenetproject.org")!=std::string::npos)\r
441         {\r
442                 uuid.erase(uuid.find("@freenetproject.org"));\r
443         }\r
444 \r
445         SQLite3DB::Statement st=m_db->Prepare("SELECT MessageID FROM tblMessage WHERE MessageUUID=?;");\r
446         st.Bind(0,uuid);\r
447         st.Step();\r
448 \r
449         if(st.RowReturned())\r
450         {\r
451                 int messageid;\r
452                 st.ResultInt(0,messageid);\r
453 \r
454                 return Load(messageid);\r
455         }\r
456         else\r
457         {\r
458                 return false;\r
459         }\r
460 }\r
461 \r
462 const bool Message::LoadNext(const long messageid, const long boardid)\r
463 {\r
464         std::string sql="SELECT tblMessage.MessageID FROM tblMessage INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID WHERE tblMessage.MessageID>?";\r
465         if(boardid!=-1)\r
466         {\r
467                 sql+=" AND tblMessageBoard.BoardID=?";\r
468         }\r
469         sql+=";";\r
470 \r
471         SQLite3DB::Statement st=m_db->Prepare(sql);\r
472 \r
473         st.Bind(0,messageid);\r
474         if(boardid!=-1)\r
475         {\r
476                 st.Bind(1,boardid);\r
477         }\r
478         st.Step();\r
479 \r
480         if(st.RowReturned())\r
481         {\r
482                 int result;\r
483                 st.ResultInt(0,result);\r
484                 return Load(result,boardid);\r
485         }\r
486         else\r
487         {\r
488                 return false;\r
489         }\r
490 }\r
491 \r
492 const bool Message::LoadPrevious(const long messageid, const long boardid)\r
493 {\r
494         std::string sql="SELECT tblMessage.MessageID FROM tblMessage INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID WHERE tblMessage.MessageID<?";\r
495         if(boardid!=-1)\r
496         {\r
497                 sql+=" AND tblMessageBoard.BoardID=?";\r
498         }\r
499         sql+=" ORDER BY tblMessage.MessageID DESC;";\r
500 \r
501         SQLite3DB::Statement st=m_db->Prepare(sql);\r
502 \r
503         st.Bind(0,messageid);\r
504         if(boardid!=-1)\r
505         {\r
506                 st.Bind(1,boardid);\r
507         }\r
508         st.Step();\r
509 \r
510         if(st.RowReturned())\r
511         {\r
512                 int result;\r
513                 st.ResultInt(0,result);\r
514                 return Load(result,boardid);\r
515         }\r
516         else\r
517         {\r
518                 return false;\r
519         }\r
520 }\r
521 \r
522 const bool Message::ParseNNTPMessage(const std::string &nntpmessage)\r
523 {\r
524 \r
525         Initialize();\r
526 \r
527         UUIDGenerator uuid;\r
528         CMimeMessage mime;\r
529         mime.Load(nntpmessage.c_str(),nntpmessage.size());\r
530 \r
531         // get header info\r
532         // date is always set to now regardless of what message has\r
533         m_datetime.SetToGMTime();\r
534 \r
535         // messageuuid is always a unique id we generate regardless of message message-id\r
536         m_messageuuid=uuid.Generate();\r
537         \r
538         // get from\r
539         if(mime.GetFieldValue("From"))\r
540         {\r
541                 m_fromname=mime.GetFieldValue("From");\r
542                 // remove any path folding\r
543                 m_fromname=StringFunctions::Replace(m_fromname,"\r\n","");\r
544                 // strip off everything between () and <> and any whitespace\r
545                 std::string::size_type startpos=m_fromname.find("(");\r
546                 std::string::size_type endpos;\r
547                 if(startpos!=std::string::npos)\r
548                 {\r
549                         endpos=m_fromname.find(")",startpos);\r
550                         if(endpos!=std::string::npos)\r
551                         {\r
552                                 m_fromname.erase(startpos,(endpos-startpos)+1);\r
553                         }\r
554                 }\r
555                 startpos=m_fromname.find("<");\r
556                 if(startpos!=std::string::npos)\r
557                 {\r
558                         endpos=m_fromname.find(">",startpos);\r
559                         if(endpos!=std::string::npos)\r
560                         {\r
561                                 m_fromname.erase(startpos,(endpos-startpos)+1);\r
562                         }\r
563                 }\r
564                 m_fromname=StringFunctions::TrimWhitespace(m_fromname);\r
565 \r
566                 // trim off " from beginning and end\r
567                 if(m_fromname.size()>0 && m_fromname[0]=='\"')\r
568                 {\r
569                         m_fromname.erase(0,1);\r
570                 }\r
571                 if(m_fromname.size()>0 && m_fromname[m_fromname.size()-1]=='\"')\r
572                 {\r
573                         m_fromname.erase(m_fromname.size()-1,1);\r
574                 }\r
575 \r
576                 m_fromname=StringFunctions::TrimWhitespace(m_fromname);\r
577         }\r
578         else\r
579         {\r
580                 m_fromname="Anonymous";\r
581         }\r
582         // get boards posted to\r
583         if(mime.GetFieldValue("Newsgroups"))\r
584         {\r
585                 std::string temp=mime.GetFieldValue("Newsgroups");\r
586                 // remove any path folding\r
587                 temp=StringFunctions::Replace(temp,"\r\n","");\r
588                 std::vector<std::string> parts;\r
589                 StringFunctions::SplitMultiple(temp,", \t",parts);\r
590                 for(std::vector<std::string>::iterator i=parts.begin(); i!=parts.end(); i++)\r
591                 {\r
592                         (*i)=StringFunctions::Replace((*i),"<","");\r
593                         (*i)=StringFunctions::Replace((*i),">","");\r
594                         (*i)=StringFunctions::TrimWhitespace((*i));\r
595                         if((*i)!="")\r
596                         {\r
597                                 m_boards.push_back((*i));\r
598                         }\r
599                 }\r
600         }\r
601         // followup-to board - must be done after board vector populated\r
602         if(mime.GetFieldValue("Followup-To"))\r
603         {\r
604                 m_replyboardname=mime.GetFieldValue("Followup-To");\r
605                 // remove any path folding\r
606                 m_replyboardname=StringFunctions::Replace(m_replyboardname,"\r\n","");\r
607         }\r
608         else\r
609         {\r
610                 if(m_boards.size()>0)\r
611                 {\r
612                         m_replyboardname=m_boards[0];\r
613                 }\r
614         }\r
615         // subject\r
616         if(mime.GetFieldValue("Subject"))\r
617         {\r
618                 m_subject=mime.GetFieldValue("Subject");\r
619                 // remove any path folding\r
620                 m_subject=StringFunctions::Replace(m_subject,"\r\n","");\r
621 #if DO_CHARSET_CONVERSION\r
622                 if(mime.GetFieldCharset("Subject"))\r
623                 {\r
624                         std::string charset=mime.GetFieldCharset("Subject");\r
625                         CharsetConverter ccv;\r
626                         if(charset!="" && charset!="UTF-8" && ccv.SetConversion(charset,"UTF-8"))\r
627                         {\r
628                                 std::string output="";\r
629                                 ccv.Convert(m_subject,output);\r
630                                 m_subject=output;\r
631                         }\r
632                 }\r
633 #endif\r
634         }\r
635         else\r
636         {\r
637                 m_subject="No Subject";\r
638         }\r
639         // references\r
640         if(mime.GetFieldValue("References"))\r
641         {\r
642                 std::string temp=mime.GetFieldValue("References");\r
643                 // remove any path folding\r
644                 temp=StringFunctions::Replace(temp,"\r\n","");\r
645                 std::vector<std::string> parts;\r
646                 int count=0;\r
647                 StringFunctions::SplitMultiple(temp,", \t",parts);\r
648                 for(std::vector<std::string>::reverse_iterator i=parts.rbegin(); i!=parts.rend(); i++)\r
649                 {\r
650                         // get rid of < and > and any whitespace\r
651                         (*i)=StringFunctions::Replace((*i),"<","");\r
652                         (*i)=StringFunctions::Replace((*i),">","");\r
653                         (*i)=StringFunctions::TrimWhitespace((*i));\r
654                         /*\r
655                         // erase @ and everything after\r
656                         if((*i).find("@")!=std::string::npos)\r
657                         {\r
658                                 (*i).erase((*i).find("@"));\r
659                         }\r
660                         */\r
661                         // only erase after @ if message is old type with @freenetproject.org\r
662                         if((*i).find("@freenetproject.org")!=std::string::npos)\r
663                         {\r
664                                 (*i).erase((*i).find("@"));\r
665                         }\r
666                         if((*i)!="")\r
667                         {\r
668                                 m_inreplyto[count++]=(*i);\r
669                         }\r
670                 }\r
671         }\r
672 \r
673         CMimeBody::CBodyList mbl;\r
674         mime.GetBodyPartList(mbl);\r
675 \r
676         // append all text parts of nntp message to body\r
677         for(CMimeBody::CBodyList::iterator i=mbl.begin(); i!=mbl.end(); i++)\r
678         {\r
679                 if((*i)->IsText() && (*i)->GetContent())\r
680                 {\r
681                         std::string bodypart=(char *)(*i)->GetContent();\r
682 #ifdef DO_CHARSET_CONVERSION\r
683                         std::string charset=(*i)->GetCharset();\r
684                         if(charset!="" && charset!="UTF-8")\r
685                         {\r
686                                 CharsetConverter ccv;\r
687                                 if(ccv.SetConversion(charset,"UTF-8"))\r
688                                 {\r
689                                         std::string output="";\r
690                                         ccv.Convert(bodypart,output);\r
691                                         bodypart=output;\r
692                                 }\r
693                         }\r
694 #endif\r
695                         m_body+=bodypart;\r
696                 }\r
697         }\r
698 \r
699         return true;\r
700 }\r
701 \r
702 const bool Message::StartFreenetInsert()\r
703 {\r
704 \r
705         MessageXML xml;\r
706         int localidentityid=-1;\r
707 \r
708         xml.SetMessageID(m_messageuuid);\r
709         xml.SetSubject(m_subject);\r
710         xml.SetBody(m_body);\r
711         xml.SetReplyBoard(m_replyboardname);\r
712         xml.SetDate(m_datetime.Format("%Y-%m-%d"));\r
713         xml.SetTime(m_datetime.Format("%H:%M:%S"));\r
714         \r
715         StripAdministrationBoards();\r
716         for(std::vector<std::string>::iterator i=m_boards.begin(); i!=m_boards.end(); i++)\r
717         {\r
718                 xml.AddBoard((*i));\r
719         }\r
720         \r
721         for(std::map<long,std::string>::iterator j=m_inreplyto.begin(); j!=m_inreplyto.end(); j++)\r
722         {\r
723                 xml.AddInReplyTo((*j).first,(*j).second);\r
724         }\r
725 \r
726         localidentityid=FindLocalIdentityID(m_fromname);\r
727         if(localidentityid==-1)\r
728         {\r
729                 return false;\r
730         }\r
731 \r
732         SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblMessageInserts(LocalIdentityID,MessageUUID,MessageXML) VALUES(?,?,?);");\r
733         st.Bind(0,localidentityid);\r
734         st.Bind(1,m_messageuuid);\r
735         st.Bind(2,xml.GetXML());\r
736         st.Step();\r
737 \r
738         HandleChangeTrust();\r
739 \r
740         return true;\r
741 \r
742 }\r
743 \r
744 void Message::StripAdministrationBoards()\r
745 {\r
746         SQLite3DB::Statement st=m_db->Prepare("SELECT tblBoard.BoardID FROM tblBoard INNER JOIN tblAdministrationBoard ON tblBoard.BoardID=tblAdministrationBoard.BoardID WHERE BoardName=?;");\r
747         for(std::vector<std::string>::iterator i=m_boards.begin(); i!=m_boards.end(); )\r
748         {\r
749                 st.Bind(0,(*i));\r
750                 st.Step();\r
751                 if(st.RowReturned())\r
752                 {\r
753                         if(m_replyboardname==(*i))\r
754                         {\r
755                                 m_replyboardname="";\r
756                         }\r
757                         i=m_boards.erase(i);\r
758                 }\r
759                 else\r
760                 {\r
761                         i++;\r
762                 }\r
763                 st.Reset();\r
764         }\r
765         if(m_replyboardname=="" && m_boards.begin()!=m_boards.end())\r
766         {\r
767                 m_replyboardname=(*m_boards.begin());\r
768         }\r
769 }\r