1 #include "../../include/nntp/nntpconnection.h"
\r
2 #include "../../include/nntp/uwildmat.h"
\r
3 #include "../../include/stringfunctions.h"
\r
4 #include "../../include/datetime.h"
\r
5 #include "../../include/boardlist.h"
\r
6 #include "../../include/message.h"
\r
7 #include "../../include/messagelist.h"
\r
8 #include "../../include/option.h"
\r
10 #include <algorithm>
\r
12 //#include <zthread/Thread.h>
\r
13 #include "../../include/pthreadwrapper/thread.h"
\r
19 NNTPConnection::NNTPConnection(SOCKET sock)
\r
21 std::string tempval;
\r
24 m_tempbuffer.resize(32768);
\r
26 m_status.m_isposting=false;
\r
27 m_status.m_allowpost=false;
\r
28 m_status.m_boardid=-1;
\r
29 m_status.m_messageid=-1;
\r
30 m_status.m_mode=MODE_NONE;
\r
32 Option::Instance()->Get("NNTPAllowPost",tempval);
\r
35 m_status.m_allowpost=true;
\r
40 NNTPConnection::~NNTPConnection()
\r
45 void NNTPConnection::Disconnect()
\r
47 if(m_socket!=INVALID_SOCKET)
\r
50 closesocket(m_socket);
\r
54 m_socket=INVALID_SOCKET;
\r
58 std::vector<char>::iterator NNTPConnection::Find(std::vector<char> &buffer, const std::string &val)
\r
60 return std::search(buffer.begin(),buffer.end(),val.begin(),val.end());
\r
63 const bool NNTPConnection::HandleArticleCommand(const NNTPCommand &command)
\r
66 SendArticleParts(command);
\r
71 const bool NNTPConnection::HandleBodyCommand(const NNTPCommand &command)
\r
73 SendArticleParts(command);
\r
78 const bool NNTPConnection::HandleCapabilitiesCommand(const NNTPCommand &command)
\r
81 SendBufferedLine("101 Capability list :");
\r
82 SendBufferedLine("VERSION 2");
\r
83 SendBufferedLine("MODE-READER");
\r
84 SendBufferedLine("READER");
\r
85 SendBufferedLine("LIST OVERVIEW.FMT");
\r
86 SendBufferedLine("OVER MSGID");
\r
87 if(m_status.m_allowpost==true)
\r
89 SendBufferedLine("POST");
\r
91 SendBufferedLine(".");
\r
96 const bool NNTPConnection::HandleCommand(const NNTPCommand &command)
\r
98 if(command.m_command=="QUIT")
\r
100 return HandleQuitCommand(command);
\r
102 if(command.m_command=="MODE")
\r
104 return HandleModeCommand(command);
\r
106 if(command.m_command=="CAPABILITIES")
\r
108 return HandleCapabilitiesCommand(command);
\r
110 if(command.m_command=="HELP")
\r
112 return HandleHelpCommand(command);
\r
114 if(command.m_command=="DATE")
\r
116 return HandleDateCommand(command);
\r
118 if(command.m_command=="LIST")
\r
120 return HandleListCommand(command);
\r
122 if(command.m_command=="GROUP")
\r
124 return HandleGroupCommand(command);
\r
126 if(command.m_command=="LISTGROUP")
\r
128 return HandleListGroupCommand(command);
\r
130 if(command.m_command=="LAST")
\r
132 return HandleLastCommand(command);
\r
134 if(command.m_command=="NEXT")
\r
136 return HandleNextCommand(command);
\r
138 if(command.m_command=="ARTICLE")
\r
140 return HandleArticleCommand(command);
\r
142 if(command.m_command=="HEAD")
\r
144 return HandleHeadCommand(command);
\r
146 if(command.m_command=="BODY")
\r
148 return HandleBodyCommand(command);
\r
150 if(command.m_command=="STAT")
\r
152 return HandleStatCommand(command);
\r
154 if(command.m_command=="NEWGROUPS")
\r
156 return HandleNewGroupsCommand(command);
\r
158 if(command.m_command=="POST")
\r
160 return HandlePostCommand(command);
\r
162 if(command.m_command=="OVER" || command.m_command=="XOVER")
\r
164 return HandleOverCommand(command);
\r
170 const bool NNTPConnection::HandleDateCommand(const NNTPCommand &command)
\r
174 SendBufferedLine("111 "+now.Format("%Y%m%d%H%M%S"));
\r
178 const bool NNTPConnection::HandleGroupCommand(const NNTPCommand &command)
\r
180 if(command.m_arguments.size()==1)
\r
183 if(board.Load(command.m_arguments[0])==true)
\r
185 std::ostringstream tempstr;
\r
187 tempstr << "211 " << board.GetMessageCount() << " " << board.GetLowMessageID() << " " << board.GetHighMessageID() << " " << board.GetBoardName();
\r
189 SendBufferedLine(tempstr.str());
\r
191 // set the current boardid to this one
\r
192 m_status.m_boardid=board.GetBoardID();
\r
193 //set the first message id, -1 if there are no messages
\r
194 board.GetLowMessageID()!=0 ? m_status.m_messageid=board.GetLowMessageID() : m_status.m_messageid=-1;
\r
199 SendBufferedLine("411 No such newsgroup");
\r
204 SendBufferedLine("501 Syntax error");
\r
205 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleGroupCommand syntax error");
\r
211 const bool NNTPConnection::HandleHeadCommand(const NNTPCommand &command)
\r
214 SendArticleParts(command);
\r
219 const bool NNTPConnection::HandleHelpCommand(const NNTPCommand &command)
\r
221 SendBufferedLine("100 Help text follows");
\r
222 SendBufferedLine("There is no help text");
\r
223 SendBufferedLine(".");
\r
228 const bool NNTPConnection::HandleLastCommand(const NNTPCommand &command)
\r
230 if(m_status.m_boardid!=-1)
\r
232 if(m_status.m_messageid!=-1)
\r
236 if(mess.LoadPrevious(m_status.m_messageid,m_status.m_boardid))
\r
238 std::ostringstream tempstr;
\r
240 m_status.m_messageid=mess.GetMessageID();
\r
242 tempstr << "223 " << mess.GetMessageID() << " " << mess.GetNNTPArticleID();
\r
244 SendBufferedLine(tempstr.str());
\r
249 SendBufferedLine("422 No previous article in this group");
\r
254 SendBufferedLine("420 Current article number is invalid");
\r
259 SendBufferedLine("412 No newsgroup selected");
\r
265 const bool NNTPConnection::HandleListCommand(const NNTPCommand &command)
\r
268 int type=1; // default LIST type is active
\r
269 std::string arg1="";
\r
270 std::string arg2="";
\r
273 if(command.m_arguments.size()>0)
\r
275 StringFunctions::UpperCase(command.m_arguments[0],arg1);
\r
280 else if(arg1=="NEWSGROUPS")
\r
284 else if(arg1=="OVERVIEW.FMT")
\r
294 if(command.m_arguments.size()>1)
\r
296 arg2=command.m_arguments[1];
\r
299 // LIST ACTIVE [wildmat]
\r
303 std::ostringstream tempstr;
\r
307 SendBufferedLine("215 list of newsgroups follows");
\r
309 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
314 // check wilmat match
\r
317 show=uwildmat((*i).GetBoardName().c_str(),arg2.c_str());
\r
322 tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << (m_status.m_allowpost ? "y" : "n");
\r
323 SendBufferedLine(tempstr.str());
\r
327 SendBufferedLine(".");
\r
334 std::ostringstream tempstr;
\r
338 SendBufferedLine("215 list of newsgroups follows");
\r
340 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
345 // check wilmat match
\r
348 show=uwildmat((*i).GetBoardName().c_str(),arg2.c_str());
\r
353 tempstr << (*i).GetBoardName() << "\t" << (*i).GetBoardDescription();
\r
354 SendBufferedLine(tempstr.str());
\r
358 SendBufferedLine(".");
\r
361 // LIST OVERVIEW.FMT
\r
364 SendBufferedLine("215 Order of fields in overview database.");
\r
365 SendBufferedLine("Subject:");
\r
366 SendBufferedLine("From:");
\r
367 SendBufferedLine("Date:");
\r
368 SendBufferedLine("Message-ID:");
\r
369 SendBufferedLine("References:");
\r
370 SendBufferedLine(":bytes");
\r
371 SendBufferedLine(":lines");
\r
372 SendBufferedLine(".");
\r
377 SendBufferedLine("501 Syntax error");
\r
378 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListCommand unhandled LIST variant");
\r
384 const bool NNTPConnection::HandleListGroupCommand(const NNTPCommand &command)
\r
387 std::ostringstream tempstr;
\r
389 bool validgroup=false;
\r
394 // no args and invalid boardid
\r
395 if(command.m_arguments.size()==0 && m_status.m_boardid==-1)
\r
397 SendBufferedLine("412 No newsgroup selected");
\r
399 else if(command.m_arguments.size()==0)
\r
401 validgroup=board.Load(m_status.m_boardid);
\r
403 else if(command.m_arguments.size()==1)
\r
405 validgroup=board.Load(command.m_arguments[0]);
\r
408 lownum=board.GetLowMessageID();
\r
409 highnum=board.GetHighMessageID();
\r
413 SendBufferedLine("411 No such newsgroup");
\r
416 else if(command.m_arguments.size()==2)
\r
418 validgroup=board.Load(command.m_arguments[0]);
\r
419 std::vector<std::string> rangeparts;
\r
420 StringFunctions::Split(command.m_arguments[1],"-",rangeparts);
\r
422 if(rangeparts.size()>0)
\r
424 StringFunctions::Convert(rangeparts[0],lownum);
\r
426 if(rangeparts.size()>1)
\r
428 StringFunctions::Convert(rangeparts[1],highnum);
\r
435 SendBufferedLine("501 Syntax error");
\r
436 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListGroupCommand unknown arguments");
\r
442 // set boardid and messageid
\r
443 m_status.m_boardid=board.GetBoardID();
\r
444 board.GetLowMessageID()!=0 ? m_status.m_messageid=board.GetLowMessageID() : m_status.m_messageid=-1;
\r
448 lownum=board.GetLowMessageID();
\r
452 highnum=board.GetHighMessageID();
\r
455 tempstr << "211 " << board.GetMessageCount() << " " << board.GetLowMessageID() << " " << board.GetHighMessageID() << " " << board.GetBoardName();
\r
456 SendBufferedLine(tempstr.str());
\r
459 ml.LoadRange(lownum,highnum,board.GetBoardID());
\r
461 for(std::vector<Message>::iterator i=ml.begin(); i!=ml.end(); i++)
\r
464 tempstr << (*i).GetMessageID();
\r
466 SendBufferedLine(tempstr.str());
\r
469 // end of multi-line response
\r
470 SendBufferedLine(".");
\r
477 const bool NNTPConnection::HandleModeCommand(const NNTPCommand &command)
\r
479 if(command.m_arguments.size()>0)
\r
481 std::string arg=command.m_arguments[0];
\r
482 StringFunctions::UpperCase(arg,arg);
\r
485 m_status.m_mode=MODE_READER;
\r
486 if(m_status.m_allowpost==true)
\r
488 SendBufferedLine("200 Posting allowed");
\r
492 SendBufferedLine("201 Posting prohibited");
\r
495 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand set mode to reader");
\r
499 SendBufferedLine("501 Syntax error");
\r
500 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand unknown MODE argument : "+arg);
\r
505 SendBufferedLine("501 Syntax error");
\r
506 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand no argument supplied for MODE");
\r
512 const bool NNTPConnection::HandleNewGroupsCommand(const NNTPCommand &command)
\r
514 if(command.m_arguments.size()>=2)
\r
518 if(command.m_arguments[0].size()==8)
\r
520 StringFunctions::Convert(command.m_arguments[0].substr(0,4),tempint);
\r
521 date.SetYear(tempint);
\r
522 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
523 date.SetMonth(tempint);
\r
524 StringFunctions::Convert(command.m_arguments[0].substr(6,2),tempint);
\r
525 date.SetDay(tempint);
\r
531 If the first two digits of the year are not specified
\r
532 (this is supported only for backward compatibility), the year is to
\r
533 be taken from the current century if yy is smaller than or equal to
\r
534 the current year, and the previous century otherwise.
\r
539 century=now.GetYear()-(now.GetYear()%100);
\r
541 StringFunctions::Convert(command.m_arguments[0].substr(0,2),tempint);
\r
542 tempint<=now.GetYear()-century ? tempint+=century : tempint+=(century-100);
\r
544 //tempint > 50 ? tempint+=1900 : tempint+=2000;
\r
546 date.SetYear(tempint);
\r
547 StringFunctions::Convert(command.m_arguments[0].substr(2,2),tempint);
\r
548 date.SetMonth(tempint);
\r
549 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
550 date.SetDay(tempint);
\r
557 bl.LoadNew(date.Format("%Y-%m-%d %H:%M:%S"));
\r
559 SendBufferedLine("231 List of new newsgroups follows");
\r
561 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
563 std::ostringstream tempstr;
\r
564 tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << m_status.m_allowpost ? "y" : "n";
\r
565 SendBufferedLine(tempstr.str());
\r
568 SendBufferedLine(".");
\r
573 SendBufferedLine("501 Syntax error");
\r
574 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleNewGroupsCommand syntax error");
\r
581 const bool NNTPConnection::HandleNextCommand(const NNTPCommand &command)
\r
583 if(m_status.m_boardid!=-1)
\r
585 if(m_status.m_messageid!=-1)
\r
589 if(mess.LoadNext(m_status.m_messageid,m_status.m_boardid))
\r
591 std::ostringstream tempstr;
\r
593 m_status.m_messageid=mess.GetMessageID();
\r
595 tempstr << "223 " << mess.GetMessageID() << " " << mess.GetNNTPArticleID();
\r
597 SendBufferedLine(tempstr.str());
\r
602 SendBufferedLine("421 No next article in this group");
\r
607 SendBufferedLine("420 Current article number is invalid");
\r
612 SendBufferedLine("412 No newsgroup selected");
\r
619 const bool NNTPConnection::HandleOverCommand(const NNTPCommand &command)
\r
621 long lowmessageid,highmessageid;
\r
622 std::string messageuuid="";
\r
624 lowmessageid=highmessageid=-2;
\r
626 if(command.m_arguments.size()==0)
\r
628 lowmessageid=m_status.m_messageid;
\r
629 highmessageid=m_status.m_messageid;
\r
634 if(command.m_arguments.size()>0 && command.m_arguments[0].find("<")==0 && command.m_arguments[0].find(">")>0)
\r
636 messageuuid=command.m_arguments[0];
\r
637 messageuuid=StringFunctions::Replace(messageuuid,"<","");
\r
638 messageuuid=StringFunctions::Replace(messageuuid,">","");
\r
639 // get rid of @ and everything after
\r
640 if(messageuuid.find("@")!=std::string::npos)
\r
642 messageuuid.erase(messageuuid.find("@"));
\r
645 // single article or range
\r
649 if(command.m_arguments[0].find("-")!=std::string::npos)
\r
651 std::vector<std::string> rangeparts;
\r
652 StringFunctions::Split(command.m_arguments[0],"-",rangeparts);
\r
654 if(rangeparts.size()>0)
\r
656 StringFunctions::Convert(rangeparts[0],lowmessageid);
\r
660 else if(rangeparts.size()>1)
\r
662 StringFunctions::Convert(rangeparts[1],highmessageid);
\r
668 StringFunctions::Convert(command.m_arguments[0],lowmessageid);
\r
673 if(messageuuid!="")
\r
676 if(mess.Load(messageuuid))
\r
678 SendBufferedLine("224 Overview information follows");
\r
679 SendArticleOverInfo(mess);
\r
680 SendBufferedLine(".");
\r
684 SendBufferedLine("423 No such article");
\r
690 if(m_status.m_boardid!=-1 && bd.Load(m_status.m_boardid))
\r
693 if(highmessageid==-2)
\r
696 if(mess.Load(lowmessageid,m_status.m_boardid))
\r
698 SendBufferedLine("224 Overview information follows");
\r
699 SendArticleOverInfo(mess);
\r
700 SendBufferedLine(".");
\r
704 SendBufferedLine("423 No such article in this group");
\r
707 // range with no upper bound
\r
708 else if(highmessageid==-1)
\r
711 ml.LoadRange(lowmessageid,bd.GetHighMessageID(),m_status.m_boardid);
\r
714 SendBufferedLine("224 Overview information follows");
\r
715 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
717 SendArticleOverInfo((*i));
\r
719 SendBufferedLine(".");
\r
723 SendBufferedLine("423 Empty range");
\r
726 // range with upper and lower bound
\r
727 else if(highmessageid>=lowmessageid)
\r
730 ml.LoadRange(lowmessageid,highmessageid,m_status.m_boardid);
\r
733 SendBufferedLine("224 Overview information follows");
\r
734 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
736 SendArticleOverInfo((*i));
\r
738 SendBufferedLine(".");
\r
742 SendBufferedLine("423 Empty range");
\r
748 SendBufferedLine("423 Empty range");
\r
753 SendBufferedLine("423 No newsgroup selected");
\r
761 const bool NNTPConnection::HandlePostCommand(const NNTPCommand &command)
\r
763 if(m_status.m_allowpost==true)
\r
765 SendBufferedLine("340 Send article to be posted");
\r
766 m_status.m_isposting=true;
\r
770 SendBufferedLine("440 Posting not permitted");
\r
776 void NNTPConnection::HandlePostedMessage(const std::string &message)
\r
780 if(mess.ParseNNTPMessage(message))
\r
782 mess.StartFreenetInsert();
\r
783 SendBufferedLine("240 Article received OK");
\r
787 SendBufferedLine("441 Posting failed");
\r
791 void NNTPConnection::HandleReceivedData()
\r
793 if(m_status.m_isposting==false)
\r
795 // get end of command line
\r
796 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n");
\r
798 // we got a command
\r
799 if(endpos!=m_receivebuffer.end())
\r
801 NNTPCommand command;
\r
802 std::string commandline(m_receivebuffer.begin(),endpos);
\r
804 // remove command from receive buffer
\r
805 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+2);
\r
807 // remove any leading/trailing whitespace
\r
808 commandline=StringFunctions::TrimWhitespace(commandline);
\r
810 // split out command and arguments separated by space or tab
\r
811 StringFunctions::SplitMultiple(commandline," \t",command.m_arguments);
\r
813 // command is first element in argument vector
\r
814 command.m_command=command.m_arguments[0];
\r
815 // erase command from argument vector and make it upper case
\r
816 command.m_arguments.erase(command.m_arguments.begin());
\r
817 StringFunctions::UpperCase(command.m_command,command.m_command);
\r
819 if(HandleCommand(command)==true)
\r
825 SendBufferedLine("500 Unknown command");
\r
827 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleReceivedData received unhandled NNTP command : "+commandline);
\r
835 // check for end of post
\r
836 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n.\r\n");
\r
838 if(endpos!=m_receivebuffer.end())
\r
841 std::string message(m_receivebuffer.begin(),endpos);
\r
842 // remove from receive buffer
\r
843 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+5);
\r
845 // get rid of dot stuffing ( 2 dots on start of a line - used to prevent premature message end in NNTP)
\r
846 message=StringFunctions::Replace(message,"\r\n..","\r\n.");
\r
848 HandlePostedMessage(message);
\r
850 // message was received, so posting is completed
\r
851 m_status.m_isposting=false;
\r
857 const bool NNTPConnection::HandleStatCommand(const NNTPCommand &command)
\r
859 SendArticleParts(command);
\r
864 const bool NNTPConnection::HandleQuitCommand(const NNTPCommand &command)
\r
866 SendBufferedLine("205 Connection Closing");
\r
869 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::HandleQuitCommand client closed connection");
\r
873 void NNTPConnection::Run()
\r
876 fd_set writefs,readfs;
\r
879 // seed random number generater for this thread
\r
882 if(m_status.m_allowpost==true)
\r
884 SendBufferedLine("200 Service available, posting allowed");
\r
888 SendBufferedLine("201 Service available, posting prohibited");
\r
896 FD_SET(m_socket,&readfs);
\r
897 if(m_sendbuffer.size()>0)
\r
899 FD_SET(m_socket,&writefs);
\r
905 rval=select(m_socket+1,&readfs,&writefs,0,&tv);
\r
909 if(FD_ISSET(m_socket,&readfs))
\r
912 HandleReceivedData();
\r
914 if(m_socket!=INVALID_SOCKET && FD_ISSET(m_socket,&writefs))
\r
919 else if(rval==SOCKET_ERROR)
\r
921 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::run select returned -1 : "+GetSocketErrorMessage());
\r
924 // }while(!Disconnected() && !ZThread::Thread::interrupted());
\r
925 }while(!Disconnected() && !IsCancelled());
\r
931 void NNTPConnection::SendArticleOverInfo(Message &message)
\r
933 std::string tempval;
\r
935 std::map<long,std::string> references;
\r
937 StringFunctions::Convert(message.GetMessageID(),tempval);
\r
939 line+=message.GetSubject()+"\t";
\r
940 line+=message.GetFromName()+"\t";
\r
941 line+=message.GetDateTime().Format("%a, %d %b %y %H:%M:%S -0000")+"\t";
\r
942 line+=message.GetNNTPArticleID()+"\t";
\r
943 references=message.GetInReplyTo();
\r
944 if(references.size()>0)
\r
946 for(std::map<long,std::string>::reverse_iterator i=references.rbegin(); i!=references.rend(); i++)
\r
948 if(i!=references.rbegin())
\r
952 line+="<"+(*i).second+"@freenetproject.org>";
\r
962 SendBufferedLine(line);
\r
965 void NNTPConnection::SendArticleParts(const NNTPConnection::NNTPCommand &command)
\r
967 bool sendheaders,sendbody;
\r
968 std::string successcode;
\r
970 if(command.m_command=="ARTICLE")
\r
976 else if(command.m_command=="HEAD")
\r
982 else if(command.m_command=="BODY")
\r
988 else if(command.m_command=="STAT")
\r
996 int messageid=m_status.m_messageid;
\r
997 std::string articleid="";
\r
998 int type=0; // default to current messageid, 1=messageid, 2=articleid
\r
1000 if(command.m_arguments.size()==1 && command.m_arguments[0].size()>0)
\r
1002 if(command.m_arguments[0].find("<")==std::string::npos)
\r
1004 StringFunctions::Convert(command.m_arguments[0],messageid);
\r
1005 message.Load(messageid,m_status.m_boardid);
\r
1006 m_status.m_messageid=message.GetMessageID();
\r
1011 articleid=command.m_arguments[0];
\r
1012 message.Load(articleid);
\r
1018 message.Load(m_status.m_messageid,m_status.m_boardid);
\r
1024 if(m_status.m_boardid!=-1)
\r
1026 if(m_status.m_messageid!=-1)
\r
1028 std::ostringstream tempstr;
\r
1029 std::string article;
\r
1030 if(sendheaders&&sendbody)
\r
1032 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1034 else if(sendheaders && !sendbody)
\r
1036 article=message.GetNNTPHeaders();
\r
1037 // strip off final \r\n from headers
\r
1038 if(article.rfind("\r\n")==article.size()-2)
\r
1040 article.erase(article.size()-2);
\r
1045 article=message.GetNNTPBody();
\r
1047 // dot stuff article
\r
1048 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1050 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1052 SendBufferedLine(tempstr.str());
\r
1053 if(sendheaders || sendbody)
\r
1055 SendBufferedLine(article);
\r
1056 SendBufferedLine(".");
\r
1062 SendBufferedLine("420 Current article number is invalid");
\r
1067 SendBufferedLine("412 No newsgroup selected");
\r
1071 if(m_status.m_boardid!=-1)
\r
1073 if(message.GetMessageID()!=-1)
\r
1075 std::ostringstream tempstr;
\r
1076 std::string article;
\r
1077 if(sendheaders&&sendbody)
\r
1079 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1081 else if(sendheaders && !sendbody)
\r
1083 article=message.GetNNTPHeaders();
\r
1084 // strip off final \r\n from headers
\r
1085 if(article.rfind("\r\n")==article.size()-2)
\r
1087 article.erase(article.size()-2);
\r
1092 article=message.GetNNTPBody();
\r
1094 // dot stuff article
\r
1095 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1097 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1099 SendBufferedLine(tempstr.str());
\r
1100 if(sendheaders || sendbody)
\r
1102 SendBufferedLine(article);
\r
1103 SendBufferedLine(".");
\r
1108 SendBufferedLine("423 No article with that number");
\r
1113 SendBufferedLine("412 No newsgroup selected");
\r
1117 if(message.GetMessageID()!=-1)
\r
1119 std::string article;
\r
1120 if(sendheaders&&sendbody)
\r
1122 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1124 else if(sendheaders && !sendbody)
\r
1126 article=message.GetNNTPHeaders();
\r
1127 // strip off final \r\n from headers
\r
1128 if(article.rfind("\r\n")==article.size()-2)
\r
1130 article.erase(article.size()-2);
\r
1135 article=message.GetNNTPBody();
\r
1137 // dot stuff article
\r
1138 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1140 SendBufferedLine(successcode+" 0 "+message.GetNNTPArticleID());
\r
1141 if(sendheaders || sendbody)
\r
1143 SendBufferedLine(article);
\r
1144 SendBufferedLine(".");
\r
1149 SendBufferedLine("430 No article with that message-id");
\r
1156 void NNTPConnection::SendBuffered(const std::string &data)
\r
1158 m_sendbuffer.insert(m_sendbuffer.end(),data.begin(),data.end());
\r
1161 void NNTPConnection::SocketReceive()
\r
1163 int rval=recv(m_socket,&m_tempbuffer[0],m_tempbuffer.size(),0);
\r
1166 m_receivebuffer.insert(m_receivebuffer.end(),m_tempbuffer.begin(),m_tempbuffer.begin()+rval);
\r
1171 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::SocketReceive remote host closed connection");
\r
1175 std::string errnostr;
\r
1176 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1177 // error on receive - close the connection
\r
1179 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketReceive recv returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r
1183 void NNTPConnection::SocketSend()
\r
1185 if(m_sendbuffer.size()>0 && m_socket!=INVALID_SOCKET)
\r
1187 int rval=send(m_socket,&m_sendbuffer[0],m_sendbuffer.size(),0);
\r
1190 m_sendbuffer.erase(m_sendbuffer.begin(),m_sendbuffer.begin()+rval);
\r
1194 std::string errnostr;
\r
1195 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1196 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketSend returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r