version 0.2.8
[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                                         }\r
188                                         if(origmess.ResultNull(3)==false)\r
189                                         {\r
190                                                 origmess.ResultInt(3,origtrustlisttrust);\r
191                                         }\r
192                                         else\r
193                                         {\r
194                                                 origtrustlisttrust=m_minlocaltrustlisttrust;\r
195                                         }\r
196 \r
197                                         origmessagetrust+=changemessagetrust;\r
198                                         origtrustlisttrust+=changetrustlisttrust;\r
199 \r
200                                         origmessagetrust<0 ? origmessagetrust=0 : false;\r
201                                         origmessagetrust>100 ? origmessagetrust=100 : false;\r
202                                         origtrustlisttrust<0 ? origtrustlisttrust=0 : false;\r
203                                         origtrustlisttrust>100 ? origtrustlisttrust=100 : false;\r
204 \r
205                                         // make sure we have a record in tblIdentityTrust\r
206                                         SQLite3DB::Statement ins=m_db->Prepare("INSERT INTO tblIdentityTrust(LocalIdentityID,IdentityID) VALUES(?,?);");\r
207                                         ins.Bind(0,localidentityid);\r
208                                         ins.Bind(1,identityid);\r
209                                         ins.Step();\r
210 \r
211                                         // update new trust levels\r
212                                         SQLite3DB::Statement update=m_db->Prepare("UPDATE tblIdentityTrust SET LocalMessageTrust=?, LocalTrustListTrust=? WHERE IdentityID=? AND LocalIdentityID=?;");\r
213                                         update.Bind(0,origmessagetrust);\r
214                                         update.Bind(1,origtrustlisttrust);\r
215                                         update.Bind(2,identityid);\r
216                                         update.Bind(3,localidentityid);\r
217                                         update.Step();\r
218 \r
219                                         // insert message to show what id was changed and what current levels are\r
220                                         int lastid=0;\r
221                                         std::string messagebody;\r
222                                         std::string messagetruststr="";\r
223                                         std::string trustlisttruststr="";\r
224                                         UUIDGenerator uuid;\r
225                                         DateTime now;\r
226                                         now.SetToGMTime();\r
227                                         StringFunctions::Convert(origmessagetrust,messagetruststr);\r
228                                         StringFunctions::Convert(origtrustlisttrust,trustlisttruststr);\r
229                                         messagebody="Trust List of "+m_fromname+"\r\n";\r
230                                         messagebody="Trust Changed for "+identityname+"\r\n";\r
231                                         messagebody+="Local Message Trust : "+messagetruststr+"\r\n";\r
232                                         messagebody+="Local Trust List Trust : "+trustlisttruststr+"\r\n";\r
233                                         SQLite3DB::Statement insert=m_db->Prepare("INSERT INTO tblMessage(FromName,MessageDate,MessageTime,Subject,MessageUUID,ReplyBoardID,Body) VALUES('FMS',?,?,?,?,?,?);");\r
234                                         insert.Bind(0,now.Format("%Y-%m-%d"));\r
235                                         insert.Bind(1,now.Format("%H:%M:%S"));\r
236                                         insert.Bind(2,identityname+" Trust Changed");\r
237                                         insert.Bind(3,uuid.Generate());\r
238                                         insert.Bind(4,boardid);\r
239                                         insert.Bind(5,messagebody);\r
240                                         insert.Step(true);\r
241                                         lastid=insert.GetLastInsertRowID();\r
242 \r
243                                         insert=m_db->Prepare("INSERT INTO tblMessageBoard(MessageID,BoardID) VALUES(?,?);");\r
244                                         insert.Bind(0,lastid);\r
245                                         insert.Bind(1,boardid);\r
246                                         insert.Step();\r
247 \r
248                                         m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"Message::HandleAdministrationMessage updated "+identityname+" to "+messagetruststr+" , "+trustlisttruststr);\r
249 \r
250                                 }\r
251                         }\r
252 \r
253                         st.Step();\r
254                 }\r
255         }\r
256 \r
257 }\r
258 \r
259 void Message::HandleChangeTrust()\r
260 {\r
261         if(m_changemessagetrustonreply!=0 && m_inreplyto.size()>0)\r
262         {\r
263                 int localidentityid=FindLocalIdentityID(m_fromname);\r
264                 if(localidentityid!=-1)\r
265                 {\r
266                         // make sure we have a record in tblIdentityTrust\r
267                         SQLite3DB::Statement ins=m_db->Prepare("INSERT INTO tblIdentityTrust(LocalIdentityID,IdentityID) VALUES(?,?);");\r
268 \r
269                         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
270                         st.Bind(0,localidentityid);\r
271                         st.Bind(1,m_inreplyto[0]);\r
272                         st.Step();\r
273                         if(st.RowReturned())\r
274                         {\r
275                                 int identityid=0;\r
276                                 int localmessagetrust=0;\r
277 \r
278                                 st.ResultInt(0,identityid);\r
279                                 if(st.ResultNull(1)==false)\r
280                                 {\r
281                                         st.ResultInt(1,localmessagetrust);\r
282                                 }\r
283                                 else\r
284                                 {\r
285                                         localmessagetrust=m_minlocalmessagetrust;\r
286                                 }\r
287 \r
288                                 localmessagetrust+=m_changemessagetrustonreply;\r
289                                 if(localmessagetrust<0)\r
290                                 {\r
291                                         localmessagetrust=0;\r
292                                 }\r
293                                 if(localmessagetrust>100)\r
294                                 {\r
295                                         localmessagetrust=100;\r
296                                 }\r
297 \r
298                                 ins.Bind(0,localidentityid);\r
299                                 ins.Bind(1,identityid);\r
300                                 ins.Step();\r
301 \r
302                                 SQLite3DB::Statement st2=m_db->Prepare("UPDATE tblIdentityTrust SET LocalMessageTrust=? WHERE IdentityID=? AND LocalIdentityID=?;");\r
303                                 st2.Bind(0,localmessagetrust);\r
304                                 st2.Bind(1,identityid);\r
305                                 st2.Bind(2,localidentityid);\r
306                                 st2.Step();\r
307 \r
308                         }\r
309                 }\r
310         }\r
311 }\r
312 \r
313 void Message::Initialize()\r
314 {\r
315         std::string tempval="";\r
316         m_messageid=-1;\r
317         m_messageuuid="";\r
318         m_subject="";\r
319         m_body="";\r
320         m_replyboardname="";\r
321         m_datetime.Set();\r
322         m_fromname="";\r
323         m_boards.clear();\r
324         m_inreplyto.clear();\r
325         m_changemessagetrustonreply=0;\r
326         Option::Instance()->Get("ChangeMessageTrustOnReply",tempval);\r
327         StringFunctions::Convert(tempval,m_changemessagetrustonreply);\r
328         Option::Instance()->Get("AddNewPostFromIdentities",tempval);\r
329         if(tempval=="true")\r
330         {\r
331                 m_addnewpostfromidentities=true;\r
332         }\r
333         else\r
334         {\r
335                 m_addnewpostfromidentities=false;\r
336         }\r
337         tempval="50";\r
338         Option::Instance()->Get("MinLocalMessageTrust",tempval);\r
339         StringFunctions::Convert(tempval,m_minlocalmessagetrust);\r
340         tempval="51";\r
341         Option::Instance()->Get("MinLocalTrustListTrust",tempval);\r
342         StringFunctions::Convert(tempval,m_minlocaltrustlisttrust);\r
343 }\r
344 \r
345 const bool Message::Load(const long messageid, const long boardid)\r
346 {\r
347         \r
348         Initialize();\r
349 \r
350         std::string sql;\r
351         \r
352         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
353         if(boardid!=-1)\r
354         {\r
355                 sql+=" AND tblMessageBoard.BoardID=?";\r
356         }\r
357         sql+=";";\r
358 \r
359         SQLite3DB::Statement st=m_db->Prepare(sql);\r
360         st.Bind(0,messageid);\r
361         if(boardid!=-1)\r
362         {\r
363                 st.Bind(1,boardid);\r
364         }\r
365         st.Step();\r
366 \r
367         if(st.RowReturned())\r
368         {\r
369                 std::string tempdate;\r
370                 std::string temptime;\r
371                 int tempint=-1;\r
372                 st.ResultInt(0,tempint);\r
373                 m_messageid=tempint;\r
374                 st.ResultText(1,m_messageuuid);\r
375                 st.ResultText(2,m_subject);\r
376                 st.ResultText(3,m_body);\r
377                 st.ResultText(4,m_replyboardname);\r
378                 st.ResultText(5,tempdate);\r
379                 st.ResultText(6,temptime);\r
380                 m_datetime.Set(tempdate + " " + temptime);\r
381                 st.ResultText(7,m_fromname);\r
382                 st.Finalize();\r
383 \r
384                 // strip off any \r\n in subject\r
385                 m_subject=StringFunctions::Replace(m_subject,"\r\n","");\r
386 \r
387                 // get board list\r
388                 st=m_db->Prepare("SELECT tblBoard.BoardName FROM tblBoard INNER JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID WHERE tblMessageBoard.MessageID=?;");\r
389                 st.Bind(0,messageid);\r
390                 st.Step();\r
391                 while(st.RowReturned())\r
392                 {\r
393                         std::string tempval;\r
394                         st.ResultText(0,tempval);\r
395                         m_boards.push_back(tempval);\r
396                         st.Step();\r
397                 }\r
398                 st.Finalize();\r
399 \r
400                 // get in reply to list\r
401                 st=m_db->Prepare("SELECT ReplyToMessageUUID, ReplyOrder FROM tblMessageReplyTo INNER JOIN tblMessage ON tblMessageReplyTo.MessageID=tblMessage.MessageID WHERE tblMessage.MessageID=?;");\r
402                 st.Bind(0,messageid);\r
403                 st.Step();\r
404                 while(st.RowReturned())\r
405                 {\r
406                         std::string tempval;\r
407                         int tempint;\r
408                         st.ResultText(0,tempval);\r
409                         st.ResultInt(1,tempint);\r
410                         m_inreplyto[tempint]=tempval;\r
411                         st.Step();\r
412                 }\r
413                 st.Finalize();\r
414 \r
415                 return true;\r
416         }\r
417         else\r
418         {\r
419                 return false;\r
420         }\r
421 \r
422 }\r
423 \r
424 const bool Message::Load(const std::string &messageuuid)\r
425 {\r
426 \r
427         std::string uuid=messageuuid;\r
428 \r
429         if(uuid.size()>0 && uuid[0]=='<')\r
430         {\r
431                 uuid.erase(0,1);\r
432         }\r
433         if(uuid.size()>0 && uuid[uuid.size()-1]=='>')\r
434         {\r
435                 uuid.erase(uuid.size()-1);\r
436         }\r
437         if(uuid.find("@freenetproject.org")!=std::string::npos)\r
438         {\r
439                 uuid.erase(uuid.find("@freenetproject.org"));\r
440         }\r
441 \r
442         SQLite3DB::Statement st=m_db->Prepare("SELECT MessageID FROM tblMessage WHERE MessageUUID=?;");\r
443         st.Bind(0,uuid);\r
444         st.Step();\r
445 \r
446         if(st.RowReturned())\r
447         {\r
448                 int messageid;\r
449                 st.ResultInt(0,messageid);\r
450 \r
451                 return Load(messageid);\r
452         }\r
453         else\r
454         {\r
455                 return false;\r
456         }\r
457 }\r
458 \r
459 const bool Message::LoadNext(const long messageid, const long boardid)\r
460 {\r
461         std::string sql="SELECT tblMessage.MessageID FROM tblMessage INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID WHERE tblMessage.MessageID>?";\r
462         if(boardid!=-1)\r
463         {\r
464                 sql+=" AND tblMessageBoard.BoardID=?";\r
465         }\r
466         sql+=";";\r
467 \r
468         SQLite3DB::Statement st=m_db->Prepare(sql);\r
469 \r
470         st.Bind(0,messageid);\r
471         if(boardid!=-1)\r
472         {\r
473                 st.Bind(1,boardid);\r
474         }\r
475         st.Step();\r
476 \r
477         if(st.RowReturned())\r
478         {\r
479                 int result;\r
480                 st.ResultInt(0,result);\r
481                 return Load(result,boardid);\r
482         }\r
483         else\r
484         {\r
485                 return false;\r
486         }\r
487 }\r
488 \r
489 const bool Message::LoadPrevious(const long messageid, const long boardid)\r
490 {\r
491         std::string sql="SELECT tblMessage.MessageID FROM tblMessage INNER JOIN tblMessageBoard ON tblMessage.MessageID=tblMessageBoard.MessageID WHERE tblMessage.MessageID<?";\r
492         if(boardid!=-1)\r
493         {\r
494                 sql+=" AND tblMessageBoard.BoardID=?";\r
495         }\r
496         sql+=" ORDER BY tblMessage.MessageID DESC;";\r
497 \r
498         SQLite3DB::Statement st=m_db->Prepare(sql);\r
499 \r
500         st.Bind(0,messageid);\r
501         if(boardid!=-1)\r
502         {\r
503                 st.Bind(1,boardid);\r
504         }\r
505         st.Step();\r
506 \r
507         if(st.RowReturned())\r
508         {\r
509                 int result;\r
510                 st.ResultInt(0,result);\r
511                 return Load(result,boardid);\r
512         }\r
513         else\r
514         {\r
515                 return false;\r
516         }\r
517 }\r
518 \r
519 const bool Message::ParseNNTPMessage(const std::string &nntpmessage)\r
520 {\r
521 \r
522         Initialize();\r
523 \r
524         UUIDGenerator uuid;\r
525         CMimeMessage mime;\r
526         mime.Load(nntpmessage.c_str(),nntpmessage.size());\r
527 \r
528         // get header info\r
529         // date is always set to now regardless of what message has\r
530         m_datetime.SetToGMTime();\r
531 \r
532         // messageuuid is always a unique id we generate regardless of message message-id\r
533         m_messageuuid=uuid.Generate();\r
534         \r
535         // get from\r
536         if(mime.GetFieldValue("From"))\r
537         {\r
538                 m_fromname=mime.GetFieldValue("From");\r
539                 // remove any path folding\r
540                 m_fromname=StringFunctions::Replace(m_fromname,"\r\n","");\r
541                 // strip off everything between () and <> and any whitespace\r
542                 std::string::size_type startpos=m_fromname.find("(");\r
543                 std::string::size_type endpos;\r
544                 if(startpos!=std::string::npos)\r
545                 {\r
546                         endpos=m_fromname.find(")",startpos);\r
547                         if(endpos!=std::string::npos)\r
548                         {\r
549                                 m_fromname.erase(startpos,(endpos-startpos)+1);\r
550                         }\r
551                 }\r
552                 startpos=m_fromname.find("<");\r
553                 if(startpos!=std::string::npos)\r
554                 {\r
555                         endpos=m_fromname.find(">",startpos);\r
556                         if(endpos!=std::string::npos)\r
557                         {\r
558                                 m_fromname.erase(startpos,(endpos-startpos)+1);\r
559                         }\r
560                 }\r
561                 m_fromname=StringFunctions::TrimWhitespace(m_fromname);\r
562 \r
563                 // trim off " from beginning and end\r
564                 if(m_fromname.size()>0 && m_fromname[0]=='\"')\r
565                 {\r
566                         m_fromname.erase(0,1);\r
567                 }\r
568                 if(m_fromname.size()>0 && m_fromname[m_fromname.size()-1]=='\"')\r
569                 {\r
570                         m_fromname.erase(m_fromname.size()-1,1);\r
571                 }\r
572 \r
573                 m_fromname=StringFunctions::TrimWhitespace(m_fromname);\r
574         }\r
575         else\r
576         {\r
577                 m_fromname="Anonymous";\r
578         }\r
579         // get boards posted to\r
580         if(mime.GetFieldValue("Newsgroups"))\r
581         {\r
582                 std::string temp=mime.GetFieldValue("Newsgroups");\r
583                 // remove any path folding\r
584                 temp=StringFunctions::Replace(temp,"\r\n","");\r
585                 std::vector<std::string> parts;\r
586                 StringFunctions::SplitMultiple(temp,", \t",parts);\r
587                 for(std::vector<std::string>::iterator i=parts.begin(); i!=parts.end(); i++)\r
588                 {\r
589                         (*i)=StringFunctions::Replace((*i),"<","");\r
590                         (*i)=StringFunctions::Replace((*i),">","");\r
591                         (*i)=StringFunctions::TrimWhitespace((*i));\r
592                         if((*i)!="")\r
593                         {\r
594                                 m_boards.push_back((*i));\r
595                         }\r
596                 }\r
597         }\r
598         // followup-to board - must be done after board vector populated\r
599         if(mime.GetFieldValue("Followup-To"))\r
600         {\r
601                 m_replyboardname=mime.GetFieldValue("Followup-To");\r
602                 // remove any path folding\r
603                 m_replyboardname=StringFunctions::Replace(m_replyboardname,"\r\n","");\r
604         }\r
605         else\r
606         {\r
607                 if(m_boards.size()>0)\r
608                 {\r
609                         m_replyboardname=m_boards[0];\r
610                 }\r
611         }\r
612         // subject\r
613         if(mime.GetFieldValue("Subject"))\r
614         {\r
615                 m_subject=mime.GetFieldValue("Subject");\r
616                 // remove any path folding\r
617                 m_subject=StringFunctions::Replace(m_subject,"\r\n","");\r
618 #if DO_CHARSET_CONVERSION\r
619                 if(mime.GetFieldCharset("Subject"))\r
620                 {\r
621                         std::string charset=mime.GetFieldCharset("Subject");\r
622                         CharsetConverter ccv;\r
623                         if(charset!="" && charset!="UTF-8" && ccv.SetConversion(charset,"UTF-8"))\r
624                         {\r
625                                 std::string output="";\r
626                                 ccv.Convert(m_subject,output);\r
627                                 m_subject=output;\r
628                         }\r
629                 }\r
630 #endif\r
631         }\r
632         else\r
633         {\r
634                 m_subject="No Subject";\r
635         }\r
636         // references\r
637         if(mime.GetFieldValue("References"))\r
638         {\r
639                 std::string temp=mime.GetFieldValue("References");\r
640                 // remove any path folding\r
641                 temp=StringFunctions::Replace(temp,"\r\n","");\r
642                 std::vector<std::string> parts;\r
643                 int count=0;\r
644                 StringFunctions::SplitMultiple(temp,", \t",parts);\r
645                 for(std::vector<std::string>::reverse_iterator i=parts.rbegin(); i!=parts.rend(); i++)\r
646                 {\r
647                         // get rid of < and > and any whitespace\r
648                         (*i)=StringFunctions::Replace((*i),"<","");\r
649                         (*i)=StringFunctions::Replace((*i),">","");\r
650                         (*i)=StringFunctions::TrimWhitespace((*i));\r
651                         /*\r
652                         // erase @ and everything after\r
653                         if((*i).find("@")!=std::string::npos)\r
654                         {\r
655                                 (*i).erase((*i).find("@"));\r
656                         }\r
657                         */\r
658                         // only erase after @ if message is old type with @freenetproject.org\r
659                         if((*i).find("@freenetproject.org")!=std::string::npos)\r
660                         {\r
661                                 (*i).erase((*i).find("@"));\r
662                         }\r
663                         if((*i)!="")\r
664                         {\r
665                                 m_inreplyto[count++]=(*i);\r
666                         }\r
667                 }\r
668         }\r
669 \r
670         CMimeBody::CBodyList mbl;\r
671         mime.GetBodyPartList(mbl);\r
672 \r
673         // append all text parts of nntp message to body\r
674         for(CMimeBody::CBodyList::iterator i=mbl.begin(); i!=mbl.end(); i++)\r
675         {\r
676                 if((*i)->IsText() && (*i)->GetContent())\r
677                 {\r
678                         std::string bodypart=(char *)(*i)->GetContent();\r
679 #ifdef DO_CHARSET_CONVERSION\r
680                         std::string charset=(*i)->GetCharset();\r
681                         if(charset!="" && charset!="UTF-8")\r
682                         {\r
683                                 CharsetConverter ccv;\r
684                                 if(ccv.SetConversion(charset,"UTF-8"))\r
685                                 {\r
686                                         std::string output="";\r
687                                         ccv.Convert(bodypart,output);\r
688                                         bodypart=output;\r
689                                 }\r
690                         }\r
691 #endif\r
692                         m_body+=bodypart;\r
693                 }\r
694         }\r
695 \r
696         return true;\r
697 }\r
698 \r
699 const bool Message::StartFreenetInsert()\r
700 {\r
701 \r
702         MessageXML xml;\r
703         int localidentityid=-1;\r
704 \r
705         xml.SetMessageID(m_messageuuid);\r
706         xml.SetSubject(m_subject);\r
707         xml.SetBody(m_body);\r
708         xml.SetReplyBoard(m_replyboardname);\r
709         xml.SetDate(m_datetime.Format("%Y-%m-%d"));\r
710         xml.SetTime(m_datetime.Format("%H:%M:%S"));\r
711         \r
712         StripAdministrationBoards();\r
713         for(std::vector<std::string>::iterator i=m_boards.begin(); i!=m_boards.end(); i++)\r
714         {\r
715                 xml.AddBoard((*i));\r
716         }\r
717         \r
718         for(std::map<long,std::string>::iterator j=m_inreplyto.begin(); j!=m_inreplyto.end(); j++)\r
719         {\r
720                 xml.AddInReplyTo((*j).first,(*j).second);\r
721         }\r
722 \r
723         localidentityid=FindLocalIdentityID(m_fromname);\r
724         if(localidentityid==-1)\r
725         {\r
726                 return false;\r
727         }\r
728 \r
729         SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblMessageInserts(LocalIdentityID,MessageUUID,MessageXML) VALUES(?,?,?);");\r
730         st.Bind(0,localidentityid);\r
731         st.Bind(1,m_messageuuid);\r
732         st.Bind(2,xml.GetXML());\r
733         st.Step();\r
734 \r
735         HandleChangeTrust();\r
736 \r
737         return true;\r
738 \r
739 }\r
740 \r
741 void Message::StripAdministrationBoards()\r
742 {\r
743         SQLite3DB::Statement st=m_db->Prepare("SELECT tblBoard.BoardID FROM tblBoard INNER JOIN tblAdministrationBoard ON tblBoard.BoardID=tblAdministrationBoard.BoardID WHERE BoardName=?;");\r
744         for(std::vector<std::string>::iterator i=m_boards.begin(); i!=m_boards.end(); )\r
745         {\r
746                 st.Bind(0,(*i));\r
747                 st.Step();\r
748                 if(st.RowReturned())\r
749                 {\r
750                         i=m_boards.erase(i);\r
751                 }\r
752                 else\r
753                 {\r
754                         i++;\r
755                 }\r
756                 st.Reset();\r
757         }\r
758 }\r