private void IHave(string argsText)
        {
            /* Rfc 977 3.4.1
                IHAVE <messageid>

                Responses:
                            235 article transferred ok
                            335 send article to be transferred.  End with <CR-LF>.<CR-LF>
                            435 article not wanted - do not send it
                            436 transfer failed - try again later
                            437 article rejected - do not try again

                The IHAVE command informs the server that the client has an article
                whose id is <messageid>.  If the server desires a copy of that
                article, it will return a response instructing the client to send the
                entire article.  If the server does not want the article (if, for
                example, the server already has a copy of it), a response indicating
                that the article is not wanted will be returned.

                If transmission of the article is requested, the client should send
                the entire article, including header and body, in the manner
                specified for text transmission from the server. A response code
                indicating success or failure of the transferral of the article will
                be returned.

                This function differs from the POST command in that it is intended
                for use in transferring already-posted articles between hosts.
                Normally it will not be used when the client is a personal
                newsreading program.  In particular, this function will invoke the
                server's news posting program with the appropriate settings (flags,
                options, etc) to indicate that the forthcoming article is being
                forwarded from another host.

                The server may, however, elect not to post or forward the article if
                after further examination of the article it deems it inappropriate to
                do so.  The 436 or 437 error codes may be returned as appropriate to
                the situation.

                Reasons for such subsequent rejection of an article may include such
                problems as inappropriate newsgroups or distributions, disk space
                limitations, article lengths, garbled headers, and the like.  These
                are typically restrictions enforced by the server host's news
                software and not necessarily the NNTP server itself.
            */

            //must this check in all newsgroups???
            if(m_pArticles == null)
            {
                NNTP_Articles_eArgs args = m_pNNTP_Server.OnGetXOVER(this,this.m_SelectedNewsGroup);
                m_pArticles = new NNTP_Articles();
                m_pArticles = args.Articles;
            }

            if(m_pArticles[argsText] == null)
            {
                SendData("335 send article to be transferred.  End with <CR-LF>.<CR-LF>\r\n");

                MemoryStream reply = null;
                ReadReplyCode replyCode = Core.ReadData(m_pClientSocket,out reply,null,m_pNNTP_Server.MaxMessageSize,m_pNNTP_Server.CommandIdleTimeOut,"\r\n.\r\n",".\r\n");
                if(replyCode == ReadReplyCode.Ok)
                {
                    long recivedCount = reply.Length;
                    //------- Do period handling and raise store event  --------//
                    // If line starts with '.', mail client adds additional '.',
                    // remove them.
                    using(MemoryStream msgStream = Core.DoPeriodHandling(reply,false))
                          {
                        reply.Close();
                        // get list of newsgroups to post to
                        string[] newsgroups = HeaderParser.ParseHeaderFields("Newsgroups:",msgStream.ToArray()).Split(Convert.ToChar(","));
                        //get all the necessary headers
                        HeaderParser hp = new HeaderParser(msgStream.ToArray());
                        string   msgId   = m_pNNTP_Server.OnStoreArticle(this,msgStream,newsgroups);
                        string   subject = hp.Subject;
                        string   from    = hp.From;
                        string   date    = hp.MessageDate.ToString("r",System.Globalization.DateTimeFormatInfo.InvariantInfo);
                        string   refs    = hp.References;
                        string   lines   = hp.Lines;
                        //Add msg to current article list

                        if(m_pNNTP_Server.LogCommands)
                        {
                            m_pLogWriter.AddEntry("big binary " + recivedCount.ToString() + " bytes" + "",this.SessionID,m_ConnectedIp,"S");
                        }

                        SendData("240 Article posted successfully.\r\n");
                    }
                    //----------------------------------------------------------//

                }
                else
                {
                    if(replyCode == ReadReplyCode.LengthExceeded)
                    {
                        SendData("441 Requested action aborted: exceeded storage allocation\r\n");
                    }
                    else
                    {
                        SendData("441 Error message not terminated with '.'\r\n");
                    }
                }
            }
            else
            {
                SendData("435 article not wanted - do not send it\r\n");
            }
        }
        private void NewNews(string argsText)
        {
            /* Rfc 977 3.8
                Responses:
                            230 list of new articles by message-id follows

                NEWNEWS newsgroups date time [GMT] [<distribution>]

                A list of message-ids of articles posted or received to the specified
                newsgroup since "date" will be listed. The format of the listing will
                be one message-id per line, as though text were being sent.  A single
                line consisting solely of one period followed by CR-LF will terminate
                the list.

                Date and time are in the same format as the NEWGROUPS command.

                A newsgroup name containing a "*" (an asterisk) may be specified to
                broaden the article search to some or all newsgroups.  The asterisk
                will be extended to match any part of a newsgroup name (e.g.,
                net.micro* will match net.micro.wombat, net.micro.apple, etc). Thus
                if only an asterisk is given as the newsgroup name, all newsgroups
                will be searched for new news.

                (Please note that the asterisk "*" expansion is a general
                replacement; in particular, the specification of e.g., net.*.unix
                should be correctly expanded to embrace names such as net.wombat.unix
                and net.whocares.unix.)

                Conversely, if no asterisk appears in a given newsgroup name, only
                the specified newsgroup will be searched for new articles. Newsgroup
                names must be chosen from those returned in the listing of available
                groups.  Multiple newsgroup names (including a "*") may be specified
                in this command, separated by a comma.  No comma shall appear after
                the last newsgroup in the list.  [Implementors are cautioned to keep
                the 512 character command length limit in mind.]

                The exclamation point ("!") may be used to negate a match. This can
                be used to selectively omit certain newsgroups from an otherwise
                larger list.  For example, a newsgroups specification of
                "net.*,mod.*,!mod.map.*" would specify that all net.<anything> and
                all mod.<anything> EXCEPT mod.map.<anything> newsgroup names would be
                matched.  If used, the exclamation point must appear as the first
                character of the given newsgroup name or pattern.

                The optional parameter "distributions" is a list of distribution
                groups, enclosed in angle brackets.  If specified, the distribution
                portion of an article's newsgroup (e.g, 'net' in 'net.wombat') will
                be examined for a match with the distribution categories listed, and
                only those articles which have at least one newsgroup belonging to
                the list of distributions will be listed.  If more than one
                distribution group is to be supplied, they must be separated by
                commas within the angle brackets.

                The use of the IHAVE, NEWNEWS, and NEWGROUPS commands to distribute
                news is discussed in an earlier part of this document.

                Please note that an empty list (i.e., the text body returned by this
                command consists only of the terminating period) is a possible valid
                response, and indicates that there is currently no new news.
            */

            string newsgroups = "";
            if(argsText.IndexOf("<") > -1)
            {
                newsgroups = argsText.Substring(argsText.IndexOf("<") + 1,argsText.IndexOf(">") - argsText.IndexOf("<") - 1);
                argsText.Substring(0,argsText.IndexOf("<"));
            }

            newsgroups = argsText.Substring(0,argsText.IndexOf(" ")).Trim();
            argsText = argsText.Substring(argsText.IndexOf(" ")).Trim();
            //argsText = "20" + argsText.Substring(0,2) + "/" + argsText.Substring(2,2) + "/" +  argsText.Substring(4,2) +" " + argsText.Substring(7,2) + ":" + argsText.Substring(9,2) + ":" +  argsText.Substring(11,2);

            string[] dateFormats = new string[]{"yyMMdd HHmmss","yyMMdd HHmmss 'GMT'"};
            DateTime since = DateTime.Today;
            since = DateTime.ParseExact(argsText,dateFormats,System.Globalization.DateTimeFormatInfo.InvariantInfo,System.Globalization.DateTimeStyles.AllowWhiteSpaces);

            m_pArticles = new NNTP_Articles();
            m_pArticles = m_pNNTP_Server.OnGetNewNews(this,newsgroups,since).Articles;

            SendData("231 list of new articles follow\r\n");

            foreach(NNTP_Article article in m_pArticles.Articles)
            {
                SendData(article.ID + "\r\n");
            }
            // Send list end
            SendData(".\r\n");
        }
        private void Group(string argsText)
        {
            /* Rfc 977 3.2.1
                GROUP ggg

                Responses:
                            211 n f l s group selected
                                (n = estimated number of articles in group,
                                f = first article number in the group,
                                l = last article number in the group,
                                s = name of the group.)
                            411 no such news group

                The required parameter ggg is the name of the newsgroup to be
                selected (e.g. "net.news").  A list of valid newsgroups may be
                obtained from the LIST command.

                The successful selection response will return the article numbers of
                the first and last articles in the group, and an estimate of the
                number of articles on file in the group.  It is not necessary that
                the estimate be correct, although that is helpful; it must only be
                equal to or larger than the actual number of articles on file.  (Some
                implementations will actually count the number of articles on file.
                Others will just subtract first article number from last to get an
                estimate.)

                When a valid group is selected by means of this command, the
                internally maintained "current article pointer" is set to the first
                article in the group.  If an invalid group is specified, the
                previously selected group and article remain selected.  If an empty
                newsgroup is selected, the "current article pointer" is in an
                indeterminate state and should not be used.

                Note that the name of the newsgroup is not case-dependent.  It must
                otherwise match a newsgroup obtained from the LIST command or an
                error will result.
            */

            NNTP_NewsGroup grp = m_pNNTP_Server.OnGetGroupInfo(this,argsText);

            if(grp != null){
                m_SelectedNewsGroup = argsText;
                m_CurrentArticle    = (grp.ArticlesCount > 0) ? 1 : -1;
                //Load all messages for selected group...
                //This needs some testing with big groups (>10000 articles maybe) for performace
                NNTP_Articles_eArgs args = m_pNNTP_Server.OnGetXOVER(this,this.m_SelectedNewsGroup);
                m_pArticles = new NNTP_Articles();
                m_pArticles = args.Articles;

                SendData("211 " + grp.ArticlesCount + " " + grp.FirstArticleNo + " " + grp.LastArticleNo + " " + argsText + " group selected\r\n");

            }
            else{
                SendData("411 no such news group\r\n");
            }
        }
        private void XOVER(string argsText)
        {
            /*RFC 2980 2.8 XOVER

            XOVER [range]

            The XOVER command returns information from the overview database for
            the article(s) specified.  This command was originally suggested as
            part of the OVERVIEW work described in "The Design of a Common
            Newsgroup Overview Database for Newsreaders" by Geoff Collyer.  This
            document is distributed in the Cnews distribution.  The optional
            range argument may be any of the following:

                        an article number
                        an article number followed by a dash to indicate
                            all following
                        an article number followed by a dash followed by
                            another article number

            If no argument is specified, then information from the current
            article is displayed.  Successful responses start with a 224 response
            followed by the overview information for all matched messages.  Once
            the output is complete, a period is sent on a line by itself.  If no
            argument is specified, the information for the current article is
            returned.  A news group must have been selected earlier, else a 412
            error response is returned.  If no articles are in the range
            specified, a 420 error response is returned by the server.  A 502
            response will be returned if the client only has permission to
            transfer articles.

            Each line of output will be formatted with the article number,
            followed by each of the headers in the overview database or the
            article itself (when the data is not available in the overview
            database) for that article separated by a tab character.  The
            sequence of fields must be in this order: subject, author, date,
            message-id, references, byte count, and line count.  Other optional
            fields may follow line count.  Other optional fields may follow line
            count.  These fields are specified by examining the response to the
            LIST OVERVIEW.FMT command.  Where no data exists, a null field must
            be provided (i.e. the output will have two tab characters adjacent to
            each other).  Servers should not output fields for articles that have
            been removed since the XOVER database was created.

            The LIST OVERVIEW.FMT command should be implemented if XOVER is
            implemented.  A client can use LIST OVERVIEW.FMT to determine what
            optional fields  and in which order all fields will be supplied by
            the XOVER command.  See Section 2.1.7 for more details about the LIST
            OVERVIEW.FMT command.*/

            //NNTP_Articles_eArgs args = OnGetXOVER(this,this.m_SelectedNewsGroup);

            //NNTP_Articles artcls = args.Articles;

            try
            {
                SendData("224 data follows\r\n");

                string From = argsText.Substring(0,argsText.IndexOf("-",0));
                string cTo   = argsText.Substring(argsText.IndexOf("-",0)+1);

                int to = Convert.ToInt32(cTo);
                int from = Convert.ToInt32(From);

                if(m_pArticles == null)
                {
                    NNTP_Articles_eArgs args = m_pNNTP_Server.OnGetXOVER(this,this.m_SelectedNewsGroup);
                    m_pArticles = new NNTP_Articles();
                    m_pArticles = args.Articles;
                }

                for(int counter = from;counter <= to;counter++)
                {

                    SendData(m_pArticles[counter].Number  + "\t" + m_pArticles[counter].Subject + "\t" + m_pArticles[counter].Author + "\t" + m_pArticles[counter].Date
                        + "\t" + m_pArticles[counter].ID + "\t" + m_pArticles[counter].References + "\t" + m_pArticles[counter].ByteCount + "\t" + m_pArticles[counter].Lines + "\r\n");
                }

                SendData(".\r\n");
            }
            catch(Exception x)
            {

            }
        }
        /// <summary>
        /// Gets new article info for newsgroups.
        /// </summary>
        public void GetNewNews(string groups,DateTime since,NNTP_Articles articles)
        {
            byte[] fileData       = null;
            int    msgNo          = 1;
            Hashtable files       = new Hashtable();

            NNTP_NewsGroups newsgroups = ParseNewsGroups(groups);

            foreach(NNTP_NewsGroup group in newsgroups.Newsgroups)
            {

                string groupPath = group.Name.Replace(".","\\");
                string path = m_NNTPStorePath + "groups\\" + groupPath;
                if(!Directory.Exists(path)){
                    Directory.CreateDirectory(path);
                    AddGroup(group.Name);
                }
                string[] articls = Directory.GetFiles(path,"*.txt");

                foreach(string articl in articls)
                {
                    using(FileStream fs = File.OpenRead(articl))
                    {
                        fileData = new byte[fs.Length];
                        fs.Read(fileData,0,(int)fs.Length);
                    }
                    HeaderParser hp = new HeaderParser(fileData);
                    msgNo = Convert.ToInt32(Path.GetFileNameWithoutExtension(articl).Substring(0,Path.GetFileNameWithoutExtension(articl).IndexOf("_")));
                    string date = hp.MessageDate.ToString();

                    if(Convert.ToDateTime(date).CompareTo(since) > 0)
                    {
                        articles.Add(hp.MessageID,msgNo,hp.Subject,hp.From,date,hp.References,hp.Lines,fileData.Length.ToString());
                    }
                }
            }
        }
        /// <summary>
        /// Gets article info for a newsgroup.
        /// </summary>
        public void GetArticles(string group,NNTP_Articles articles)
        {
            byte[] fileData       = null;
            int    msgNo          = 1;
            Hashtable files       = new Hashtable();
            group = group.Replace(".","\\");
            string path = m_NNTPStorePath + "groups\\" + group;
            if(!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
                AddGroup(group);
            }
            string[] articls = Directory.GetFiles(path,"*.txt");

            foreach(string articl in articls)
            {
                using(FileStream fs = File.OpenRead(articl))
                {
                    fileData = new byte[fs.Length];
                    fs.Read(fileData,0,(int)fs.Length);
                }
                HeaderParser hp = new HeaderParser(fileData);
                msgNo = Convert.ToInt32(Path.GetFileNameWithoutExtension(articl).Substring(0,Path.GetFileNameWithoutExtension(articl).IndexOf("_")));
                string date = hp.MessageDate.ToString();
                articles.Add(msgNo,hp.MessageID,hp.Subject,hp.From,date,hp.References,hp.Lines,fileData.Length.ToString());

            }
        }
 public NNTP_Articles_eArgs(NNTP_Articles articles,string newsgroup)
 {
     m_pArticels = articles;
     m_Newsgroup = newsgroup;
 }