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
393 // no args and invalid boardid
\r
394 if(command.m_arguments.size()==0 && m_status.m_boardid==-1)
\r
396 SendBufferedLine("412 No newsgroup selected");
\r
398 else if(command.m_arguments.size()==0)
\r
400 validgroup=board.Load(m_status.m_boardid);
\r
402 else if(command.m_arguments.size()==1)
\r
404 validgroup=board.Load(command.m_arguments[0]);
\r
407 lownum=board.GetLowMessageID();
\r
408 highnum=board.GetHighMessageID();
\r
412 SendBufferedLine("411 No such newsgroup");
\r
415 else if(command.m_arguments.size()==2)
\r
417 validgroup=board.Load(command.m_arguments[0]);
\r
418 std::vector<std::string> rangeparts;
\r
419 StringFunctions::Split(command.m_arguments[1],"-",rangeparts);
\r
421 if(rangeparts.size()>0)
\r
423 StringFunctions::Convert(rangeparts[0],lownum);
\r
425 if(rangeparts.size()>1)
\r
427 StringFunctions::Convert(rangeparts[1],highnum);
\r
434 SendBufferedLine("501 Syntax error");
\r
435 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleListGroupCommand unknown arguments");
\r
441 // set boardid and messageid
\r
442 m_status.m_boardid=board.GetBoardID();
\r
443 board.GetLowMessageID()!=0 ? m_status.m_messageid=board.GetLowMessageID() : m_status.m_messageid=-1;
\r
447 lownum=board.GetLowMessageID();
\r
451 highnum=board.GetHighMessageID();
\r
454 tempstr << "211 " << board.GetMessageCount() << " " << board.GetLowMessageID() << " " << board.GetHighMessageID() << " " << board.GetBoardName();
\r
455 SendBufferedLine(tempstr.str());
\r
458 ml.LoadRange(lownum,highnum,board.GetBoardID());
\r
460 for(std::vector<Message>::iterator i=ml.begin(); i!=ml.end(); i++)
\r
463 tempstr << (*i).GetMessageID();
\r
465 SendBufferedLine(tempstr.str());
\r
468 // end of multi-line response
\r
469 SendBufferedLine(".");
\r
476 const bool NNTPConnection::HandleModeCommand(const NNTPCommand &command)
\r
478 if(command.m_arguments.size()>0)
\r
480 std::string arg=command.m_arguments[0];
\r
481 StringFunctions::UpperCase(arg,arg);
\r
484 m_status.m_mode=MODE_READER;
\r
485 if(m_status.m_allowpost==true)
\r
487 SendBufferedLine("200 Posting allowed");
\r
491 SendBufferedLine("201 Posting prohibited");
\r
494 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand set mode to reader");
\r
498 SendBufferedLine("501 Syntax error");
\r
499 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand unknown MODE argument : "+arg);
\r
504 SendBufferedLine("501 Syntax error");
\r
505 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleModeCommand no argument supplied for MODE");
\r
511 const bool NNTPConnection::HandleNewGroupsCommand(const NNTPCommand &command)
\r
513 if(command.m_arguments.size()>=2)
\r
517 if(command.m_arguments[0].size()==8)
\r
519 StringFunctions::Convert(command.m_arguments[0].substr(0,4),tempint);
\r
520 date.SetYear(tempint);
\r
521 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
522 date.SetMonth(tempint);
\r
523 StringFunctions::Convert(command.m_arguments[0].substr(6,2),tempint);
\r
524 date.SetDay(tempint);
\r
530 If the first two digits of the year are not specified
\r
531 (this is supported only for backward compatibility), the year is to
\r
532 be taken from the current century if yy is smaller than or equal to
\r
533 the current year, and the previous century otherwise.
\r
538 century=now.GetYear()-(now.GetYear()%100);
\r
540 StringFunctions::Convert(command.m_arguments[0].substr(0,2),tempint);
\r
541 tempint<=now.GetYear()-century ? tempint+=century : tempint+=(century-100);
\r
543 //tempint > 50 ? tempint+=1900 : tempint+=2000;
\r
545 date.SetYear(tempint);
\r
546 StringFunctions::Convert(command.m_arguments[0].substr(2,2),tempint);
\r
547 date.SetMonth(tempint);
\r
548 StringFunctions::Convert(command.m_arguments[0].substr(4,2),tempint);
\r
549 date.SetDay(tempint);
\r
556 bl.LoadNew(date.Format("%Y-%m-%d %H:%M:%S"));
\r
558 SendBufferedLine("231 List of new newsgroups follows");
\r
560 for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)
\r
562 std::ostringstream tempstr;
\r
563 tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << m_status.m_allowpost ? "y" : "n";
\r
564 SendBufferedLine(tempstr.str());
\r
567 SendBufferedLine(".");
\r
572 SendBufferedLine("501 Syntax error");
\r
573 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleNewGroupsCommand syntax error");
\r
580 const bool NNTPConnection::HandleNextCommand(const NNTPCommand &command)
\r
582 if(m_status.m_boardid!=-1)
\r
584 if(m_status.m_messageid!=-1)
\r
588 if(mess.LoadNext(m_status.m_messageid,m_status.m_boardid))
\r
590 std::ostringstream tempstr;
\r
592 m_status.m_messageid=mess.GetMessageID();
\r
594 tempstr << "223 " << mess.GetMessageID() << " " << mess.GetNNTPArticleID();
\r
596 SendBufferedLine(tempstr.str());
\r
601 SendBufferedLine("421 No next article in this group");
\r
606 SendBufferedLine("420 Current article number is invalid");
\r
611 SendBufferedLine("412 No newsgroup selected");
\r
618 const bool NNTPConnection::HandleOverCommand(const NNTPCommand &command)
\r
620 long lowmessageid,highmessageid;
\r
621 std::string messageuuid="";
\r
623 lowmessageid=highmessageid=-2;
\r
625 if(command.m_arguments.size()==0)
\r
627 lowmessageid=m_status.m_messageid;
\r
628 highmessageid=m_status.m_messageid;
\r
633 if(command.m_arguments.size()>0 && command.m_arguments[0].find("<")==0 && command.m_arguments[0].find(">")>0)
\r
635 messageuuid=command.m_arguments[0];
\r
636 messageuuid=StringFunctions::Replace(messageuuid,"<","");
\r
637 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
646 // single article or range
\r
650 if(command.m_arguments[0].find("-")!=std::string::npos)
\r
652 std::vector<std::string> rangeparts;
\r
653 StringFunctions::Split(command.m_arguments[0],"-",rangeparts);
\r
655 if(rangeparts.size()>0)
\r
657 StringFunctions::Convert(rangeparts[0],lowmessageid);
\r
661 else if(rangeparts.size()>1)
\r
663 StringFunctions::Convert(rangeparts[1],highmessageid);
\r
669 StringFunctions::Convert(command.m_arguments[0],lowmessageid);
\r
674 if(messageuuid!="")
\r
677 if(mess.Load(messageuuid))
\r
679 SendBufferedLine("224 Overview information follows");
\r
680 SendArticleOverInfo(mess);
\r
681 SendBufferedLine(".");
\r
685 SendBufferedLine("423 No such article");
\r
691 if(m_status.m_boardid!=-1 && bd.Load(m_status.m_boardid))
\r
694 if(highmessageid==-2)
\r
697 if(mess.Load(lowmessageid,m_status.m_boardid))
\r
699 SendBufferedLine("224 Overview information follows");
\r
700 SendArticleOverInfo(mess);
\r
701 SendBufferedLine(".");
\r
705 SendBufferedLine("423 No such article in this group");
\r
708 // range with no upper bound
\r
709 else if(highmessageid==-1)
\r
712 ml.LoadRange(lowmessageid,bd.GetHighMessageID(),m_status.m_boardid);
\r
715 SendBufferedLine("224 Overview information follows");
\r
716 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
718 SendArticleOverInfo((*i));
\r
720 SendBufferedLine(".");
\r
724 SendBufferedLine("423 Empty range");
\r
727 // range with upper and lower bound
\r
728 else if(highmessageid>=lowmessageid)
\r
731 ml.LoadRange(lowmessageid,highmessageid,m_status.m_boardid);
\r
734 SendBufferedLine("224 Overview information follows");
\r
735 for(MessageList::iterator i=ml.begin(); i!=ml.end(); i++)
\r
737 SendArticleOverInfo((*i));
\r
739 SendBufferedLine(".");
\r
743 SendBufferedLine("423 Empty range");
\r
749 SendBufferedLine("423 Empty range");
\r
754 SendBufferedLine("423 No newsgroup selected");
\r
762 const bool NNTPConnection::HandlePostCommand(const NNTPCommand &command)
\r
764 if(m_status.m_allowpost==true)
\r
766 SendBufferedLine("340 Send article to be posted");
\r
767 m_status.m_isposting=true;
\r
771 SendBufferedLine("440 Posting not permitted");
\r
777 void NNTPConnection::HandlePostedMessage(const std::string &message)
\r
781 if(mess.ParseNNTPMessage(message))
\r
783 if(mess.PostedToAdministrationBoard()==true)
\r
785 mess.HandleAdministrationMessage();
\r
789 mess.StartFreenetInsert();
\r
791 SendBufferedLine("240 Article received OK");
\r
795 SendBufferedLine("441 Posting failed");
\r
799 void NNTPConnection::HandleReceivedData()
\r
801 if(m_status.m_isposting==false)
\r
803 // get end of command line
\r
804 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n");
\r
806 // we got a command
\r
807 if(endpos!=m_receivebuffer.end())
\r
809 NNTPCommand command;
\r
810 std::string commandline(m_receivebuffer.begin(),endpos);
\r
812 // remove command from receive buffer
\r
813 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+2);
\r
815 // remove any leading/trailing whitespace
\r
816 commandline=StringFunctions::TrimWhitespace(commandline);
\r
818 // split out command and arguments separated by space or tab
\r
819 StringFunctions::SplitMultiple(commandline," \t",command.m_arguments);
\r
821 // command is first element in argument vector
\r
822 command.m_command=command.m_arguments[0];
\r
823 // erase command from argument vector and make it upper case
\r
824 command.m_arguments.erase(command.m_arguments.begin());
\r
825 StringFunctions::UpperCase(command.m_command,command.m_command);
\r
827 if(HandleCommand(command)==true)
\r
833 SendBufferedLine("500 Unknown command");
\r
835 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleReceivedData received unhandled NNTP command : "+commandline);
\r
843 // check for end of post
\r
844 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n.\r\n");
\r
846 if(endpos!=m_receivebuffer.end())
\r
849 std::string message(m_receivebuffer.begin(),endpos);
\r
850 // remove from receive buffer
\r
851 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+5);
\r
853 // get rid of dot stuffing ( 2 dots on start of a line - used to prevent premature message end in NNTP)
\r
854 message=StringFunctions::Replace(message,"\r\n..","\r\n.");
\r
856 HandlePostedMessage(message);
\r
858 // message was received, so posting is completed
\r
859 m_status.m_isposting=false;
\r
865 const bool NNTPConnection::HandleStatCommand(const NNTPCommand &command)
\r
867 SendArticleParts(command);
\r
872 const bool NNTPConnection::HandleQuitCommand(const NNTPCommand &command)
\r
874 SendBufferedLine("205 Connection Closing");
\r
877 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::HandleQuitCommand client closed connection");
\r
881 void NNTPConnection::Run()
\r
884 fd_set writefs,readfs;
\r
887 // seed random number generater for this thread
\r
890 if(m_status.m_allowpost==true)
\r
892 SendBufferedLine("200 Service available, posting allowed");
\r
896 SendBufferedLine("201 Service available, posting prohibited");
\r
904 FD_SET(m_socket,&readfs);
\r
905 if(m_sendbuffer.size()>0)
\r
907 FD_SET(m_socket,&writefs);
\r
913 rval=select(m_socket+1,&readfs,&writefs,0,&tv);
\r
917 if(FD_ISSET(m_socket,&readfs))
\r
920 HandleReceivedData();
\r
922 if(m_socket!=INVALID_SOCKET && FD_ISSET(m_socket,&writefs))
\r
927 else if(rval==SOCKET_ERROR)
\r
929 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::run select returned -1 : "+GetSocketErrorMessage());
\r
932 // }while(!Disconnected() && !ZThread::Thread::interrupted());
\r
933 }while(!Disconnected() && !IsCancelled());
\r
939 void NNTPConnection::SendArticleOverInfo(Message &message)
\r
941 std::string tempval;
\r
943 std::map<long,std::string> references;
\r
945 StringFunctions::Convert(message.GetMessageID(),tempval);
\r
947 line+=message.GetSubject()+"\t";
\r
948 line+=message.GetFromName()+"\t";
\r
949 line+=message.GetDateTime().Format("%a, %d %b %y %H:%M:%S -0000")+"\t";
\r
950 line+=message.GetNNTPArticleID()+"\t";
\r
951 references=message.GetInReplyTo();
\r
952 if(references.size()>0)
\r
954 for(std::map<long,std::string>::reverse_iterator i=references.rbegin(); i!=references.rend(); i++)
\r
956 if(i!=references.rbegin())
\r
960 line+="<"+(*i).second+">"; //+"@freenetproject.org>";
\r
970 SendBufferedLine(line);
\r
973 void NNTPConnection::SendArticleParts(const NNTPConnection::NNTPCommand &command)
\r
975 bool sendheaders,sendbody;
\r
976 std::string successcode;
\r
978 if(command.m_command=="ARTICLE")
\r
984 else if(command.m_command=="HEAD")
\r
990 else if(command.m_command=="BODY")
\r
996 else if(command.m_command=="STAT")
\r
1000 successcode="223";
\r
1004 int messageid=m_status.m_messageid;
\r
1005 std::string articleid="";
\r
1006 int type=0; // default to current messageid, 1=messageid, 2=articleid
\r
1008 if(command.m_arguments.size()==1 && command.m_arguments[0].size()>0)
\r
1010 if(command.m_arguments[0].find("<")==std::string::npos)
\r
1012 StringFunctions::Convert(command.m_arguments[0],messageid);
\r
1013 message.Load(messageid,m_status.m_boardid);
\r
1014 m_status.m_messageid=message.GetMessageID();
\r
1019 articleid=command.m_arguments[0];
\r
1020 //strip off < and > and everthing after @
\r
1021 if(articleid.size()>0 && articleid[0]=='<')
\r
1023 articleid.erase(0,1);
\r
1025 if(articleid.size()>0 && articleid[articleid.size()-1]=='>')
\r
1027 articleid.erase(articleid.size()-1);
\r
1030 if(articleid.size()>0 && articleid.find('@')!=std::string::npos)
\r
1032 articleid.erase(articleid.find('@'));
\r
1035 message.Load(articleid);
\r
1041 message.Load(m_status.m_messageid,m_status.m_boardid);
\r
1047 if(m_status.m_boardid!=-1)
\r
1049 if(m_status.m_messageid!=-1)
\r
1051 std::ostringstream tempstr;
\r
1052 std::string article;
\r
1053 if(sendheaders&&sendbody)
\r
1055 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1057 else if(sendheaders && !sendbody)
\r
1059 article=message.GetNNTPHeaders();
\r
1060 // strip off final \r\n from headers
\r
1061 if(article.rfind("\r\n")==article.size()-2)
\r
1063 article.erase(article.size()-2);
\r
1068 article=message.GetNNTPBody();
\r
1070 // dot stuff article
\r
1071 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1073 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1075 SendBufferedLine(tempstr.str());
\r
1076 if(sendheaders || sendbody)
\r
1078 SendBufferedLine(article);
\r
1079 SendBufferedLine(".");
\r
1085 SendBufferedLine("420 Current article number is invalid");
\r
1090 SendBufferedLine("412 No newsgroup selected");
\r
1094 if(m_status.m_boardid!=-1)
\r
1096 if(message.GetMessageID()!=-1)
\r
1098 std::ostringstream tempstr;
\r
1099 std::string article;
\r
1100 if(sendheaders&&sendbody)
\r
1102 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1104 else if(sendheaders && !sendbody)
\r
1106 article=message.GetNNTPHeaders();
\r
1107 // strip off final \r\n from headers
\r
1108 if(article.rfind("\r\n")==article.size()-2)
\r
1110 article.erase(article.size()-2);
\r
1115 article=message.GetNNTPBody();
\r
1117 // dot stuff article
\r
1118 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1120 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1122 SendBufferedLine(tempstr.str());
\r
1123 if(sendheaders || sendbody)
\r
1125 SendBufferedLine(article);
\r
1126 SendBufferedLine(".");
\r
1131 SendBufferedLine("423 No article with that number");
\r
1136 SendBufferedLine("412 No newsgroup selected");
\r
1140 if(message.GetMessageID()!=-1)
\r
1142 std::string article;
\r
1143 if(sendheaders&&sendbody)
\r
1145 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1147 else if(sendheaders && !sendbody)
\r
1149 article=message.GetNNTPHeaders();
\r
1150 // strip off final \r\n from headers
\r
1151 if(article.rfind("\r\n")==article.size()-2)
\r
1153 article.erase(article.size()-2);
\r
1158 article=message.GetNNTPBody();
\r
1160 // dot stuff article
\r
1161 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1163 SendBufferedLine(successcode+" 0 "+message.GetNNTPArticleID());
\r
1164 if(sendheaders || sendbody)
\r
1166 SendBufferedLine(article);
\r
1167 SendBufferedLine(".");
\r
1172 SendBufferedLine("430 No article with that message-id");
\r
1179 void NNTPConnection::SendBuffered(const std::string &data)
\r
1181 m_sendbuffer.insert(m_sendbuffer.end(),data.begin(),data.end());
\r
1184 void NNTPConnection::SocketReceive()
\r
1186 int rval=recv(m_socket,&m_tempbuffer[0],m_tempbuffer.size(),0);
\r
1189 m_receivebuffer.insert(m_receivebuffer.end(),m_tempbuffer.begin(),m_tempbuffer.begin()+rval);
\r
1194 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::SocketReceive remote host closed connection");
\r
1198 std::string errnostr;
\r
1199 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1200 // error on receive - close the connection
\r
1202 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketReceive recv returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r
1206 void NNTPConnection::SocketSend()
\r
1208 if(m_sendbuffer.size()>0 && m_socket!=INVALID_SOCKET)
\r
1210 int rval=send(m_socket,&m_sendbuffer[0],m_sendbuffer.size(),0);
\r
1213 m_sendbuffer.erase(m_sendbuffer.begin(),m_sendbuffer.begin()+rval);
\r
1217 std::string errnostr;
\r
1218 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1219 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketSend returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r