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 if(mess.StartFreenetInsert())
\r
791 SendBufferedLine("240 Article received OK");
\r
795 SendBufferedLine("441 Posting failed. Make sure the identity you are sending with exists!");
\r
801 SendBufferedLine("441 Posting failed");
\r
805 void NNTPConnection::HandleReceivedData()
\r
807 if(m_status.m_isposting==false)
\r
809 // get end of command line
\r
810 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n");
\r
812 // we got a command
\r
813 if(endpos!=m_receivebuffer.end())
\r
815 NNTPCommand command;
\r
816 std::string commandline(m_receivebuffer.begin(),endpos);
\r
818 // remove command from receive buffer
\r
819 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+2);
\r
821 // remove any leading/trailing whitespace
\r
822 commandline=StringFunctions::TrimWhitespace(commandline);
\r
824 // split out command and arguments separated by space or tab
\r
825 StringFunctions::SplitMultiple(commandline," \t",command.m_arguments);
\r
827 // command is first element in argument vector
\r
828 command.m_command=command.m_arguments[0];
\r
829 // erase command from argument vector and make it upper case
\r
830 command.m_arguments.erase(command.m_arguments.begin());
\r
831 StringFunctions::UpperCase(command.m_command,command.m_command);
\r
833 if(HandleCommand(command)==true)
\r
839 SendBufferedLine("500 Unknown command");
\r
841 m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPConnection::HandleReceivedData received unhandled NNTP command : "+commandline);
\r
849 // check for end of post
\r
850 std::vector<char>::iterator endpos=Find(m_receivebuffer,"\r\n.\r\n");
\r
852 if(endpos!=m_receivebuffer.end())
\r
855 std::string message(m_receivebuffer.begin(),endpos);
\r
856 // remove from receive buffer
\r
857 m_receivebuffer.erase(m_receivebuffer.begin(),endpos+5);
\r
859 // get rid of dot stuffing ( 2 dots on start of a line - used to prevent premature message end in NNTP)
\r
860 message=StringFunctions::Replace(message,"\r\n..","\r\n.");
\r
862 HandlePostedMessage(message);
\r
864 // message was received, so posting is completed
\r
865 m_status.m_isposting=false;
\r
871 const bool NNTPConnection::HandleStatCommand(const NNTPCommand &command)
\r
873 SendArticleParts(command);
\r
878 const bool NNTPConnection::HandleQuitCommand(const NNTPCommand &command)
\r
880 SendBufferedLine("205 Connection Closing");
\r
883 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::HandleQuitCommand client closed connection");
\r
887 void NNTPConnection::Run()
\r
890 fd_set writefs,readfs;
\r
893 // seed random number generater for this thread
\r
896 if(m_status.m_allowpost==true)
\r
898 SendBufferedLine("200 Service available, posting allowed");
\r
902 SendBufferedLine("201 Service available, posting prohibited");
\r
910 FD_SET(m_socket,&readfs);
\r
911 if(m_sendbuffer.size()>0)
\r
913 FD_SET(m_socket,&writefs);
\r
919 rval=select(m_socket+1,&readfs,&writefs,0,&tv);
\r
923 if(FD_ISSET(m_socket,&readfs))
\r
926 HandleReceivedData();
\r
928 if(m_socket!=INVALID_SOCKET && FD_ISSET(m_socket,&writefs))
\r
933 else if(rval==SOCKET_ERROR)
\r
935 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::run select returned -1 : "+GetSocketErrorMessage());
\r
938 // }while(!Disconnected() && !ZThread::Thread::interrupted());
\r
939 }while(!Disconnected() && !IsCancelled());
\r
945 void NNTPConnection::SendArticleOverInfo(Message &message)
\r
947 std::string tempval;
\r
949 std::map<long,std::string> references;
\r
951 StringFunctions::Convert(message.GetMessageID(),tempval);
\r
953 line+=message.GetSubject()+"\t";
\r
954 line+=message.GetFromName()+"\t";
\r
955 line+=message.GetDateTime().Format("%a, %d %b %y %H:%M:%S -0000")+"\t";
\r
956 line+=message.GetNNTPArticleID()+"\t";
\r
957 references=message.GetInReplyTo();
\r
958 if(references.size()>0)
\r
960 for(std::map<long,std::string>::reverse_iterator i=references.rbegin(); i!=references.rend(); i++)
\r
962 if(i!=references.rbegin())
\r
966 line+="<"+(*i).second+">"; //+"@freenetproject.org>";
\r
976 SendBufferedLine(line);
\r
979 void NNTPConnection::SendArticleParts(const NNTPConnection::NNTPCommand &command)
\r
981 bool sendheaders,sendbody;
\r
982 std::string successcode;
\r
984 if(command.m_command=="ARTICLE")
\r
990 else if(command.m_command=="HEAD")
\r
996 else if(command.m_command=="BODY")
\r
1000 successcode="222";
\r
1002 else if(command.m_command=="STAT")
\r
1004 sendheaders=false;
\r
1006 successcode="223";
\r
1010 int messageid=m_status.m_messageid;
\r
1011 std::string articleid="";
\r
1012 int type=0; // default to current messageid, 1=messageid, 2=articleid
\r
1014 if(command.m_arguments.size()==1 && command.m_arguments[0].size()>0)
\r
1016 if(command.m_arguments[0].find("<")==std::string::npos)
\r
1018 StringFunctions::Convert(command.m_arguments[0],messageid);
\r
1019 message.Load(messageid,m_status.m_boardid);
\r
1020 m_status.m_messageid=message.GetMessageID();
\r
1025 articleid=command.m_arguments[0];
\r
1026 //strip off < and > and everthing after @
\r
1027 if(articleid.size()>0 && articleid[0]=='<')
\r
1029 articleid.erase(0,1);
\r
1031 if(articleid.size()>0 && articleid[articleid.size()-1]=='>')
\r
1033 articleid.erase(articleid.size()-1);
\r
1036 if(articleid.size()>0 && articleid.find('@')!=std::string::npos)
\r
1038 articleid.erase(articleid.find('@'));
\r
1041 message.Load(articleid);
\r
1047 message.Load(m_status.m_messageid,m_status.m_boardid);
\r
1053 if(m_status.m_boardid!=-1)
\r
1055 if(m_status.m_messageid!=-1)
\r
1057 std::ostringstream tempstr;
\r
1058 std::string article;
\r
1059 if(sendheaders&&sendbody)
\r
1061 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1063 else if(sendheaders && !sendbody)
\r
1065 article=message.GetNNTPHeaders();
\r
1066 // strip off final \r\n from headers
\r
1067 if(article.rfind("\r\n")==article.size()-2)
\r
1069 article.erase(article.size()-2);
\r
1074 article=message.GetNNTPBody();
\r
1076 // dot stuff article
\r
1077 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1079 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1081 SendBufferedLine(tempstr.str());
\r
1082 if(sendheaders || sendbody)
\r
1084 SendBufferedLine(article);
\r
1085 SendBufferedLine(".");
\r
1091 SendBufferedLine("420 Current article number is invalid");
\r
1096 SendBufferedLine("412 No newsgroup selected");
\r
1100 if(m_status.m_boardid!=-1)
\r
1102 if(message.GetMessageID()!=-1)
\r
1104 std::ostringstream tempstr;
\r
1105 std::string article;
\r
1106 if(sendheaders&&sendbody)
\r
1108 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1110 else if(sendheaders && !sendbody)
\r
1112 article=message.GetNNTPHeaders();
\r
1113 // strip off final \r\n from headers
\r
1114 if(article.rfind("\r\n")==article.size()-2)
\r
1116 article.erase(article.size()-2);
\r
1121 article=message.GetNNTPBody();
\r
1123 // dot stuff article
\r
1124 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1126 tempstr << successcode << " " << message.GetMessageID() << " " << message.GetNNTPArticleID();
\r
1128 SendBufferedLine(tempstr.str());
\r
1129 if(sendheaders || sendbody)
\r
1131 SendBufferedLine(article);
\r
1132 SendBufferedLine(".");
\r
1137 SendBufferedLine("423 No article with that number");
\r
1142 SendBufferedLine("412 No newsgroup selected");
\r
1146 if(message.GetMessageID()!=-1)
\r
1148 std::string article;
\r
1149 if(sendheaders&&sendbody)
\r
1151 article=message.GetNNTPHeaders()+"\r\n"+message.GetNNTPBody();
\r
1153 else if(sendheaders && !sendbody)
\r
1155 article=message.GetNNTPHeaders();
\r
1156 // strip off final \r\n from headers
\r
1157 if(article.rfind("\r\n")==article.size()-2)
\r
1159 article.erase(article.size()-2);
\r
1164 article=message.GetNNTPBody();
\r
1166 // dot stuff article
\r
1167 article=StringFunctions::Replace(article,"\r\n.","\r\n..");
\r
1169 SendBufferedLine(successcode+" 0 "+message.GetNNTPArticleID());
\r
1170 if(sendheaders || sendbody)
\r
1172 SendBufferedLine(article);
\r
1173 SendBufferedLine(".");
\r
1178 SendBufferedLine("430 No article with that message-id");
\r
1185 void NNTPConnection::SendBuffered(const std::string &data)
\r
1187 m_sendbuffer.insert(m_sendbuffer.end(),data.begin(),data.end());
\r
1190 void NNTPConnection::SocketReceive()
\r
1192 int rval=recv(m_socket,&m_tempbuffer[0],m_tempbuffer.size(),0);
\r
1195 m_receivebuffer.insert(m_receivebuffer.end(),m_tempbuffer.begin(),m_tempbuffer.begin()+rval);
\r
1200 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPConnection::SocketReceive remote host closed connection");
\r
1204 std::string errnostr;
\r
1205 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1206 // error on receive - close the connection
\r
1208 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketReceive recv returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r
1212 void NNTPConnection::SocketSend()
\r
1214 if(m_sendbuffer.size()>0 && m_socket!=INVALID_SOCKET)
\r
1216 int rval=send(m_socket,&m_sendbuffer[0],m_sendbuffer.size(),0);
\r
1219 m_sendbuffer.erase(m_sendbuffer.begin(),m_sendbuffer.begin()+rval);
\r
1223 std::string errnostr;
\r
1224 StringFunctions::Convert(GetSocketErrorNumber(),errnostr);
\r
1225 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPConnection::SocketSend returned -1 : "+errnostr+" - "+GetSocketErrorMessage());
\r