Esempio n. 1
0
 /// <summary>
 /// Creates a new instance of the <see cref="NntpArticleBuilder"/> class.
 /// </summary>
 public NntpArticleBuilder()
 {
     headers       = new MultiValueDictionary <string, string>();
     body          = new List <string>();
     groupsBuilder = new NntpGroupsBuilder();
     messageId     = NntpMessageId.Empty;
 }
Esempio n. 2
0
 /// <summary>
 /// Creates a new instance of the <see cref="NntpStatResponse"/> class.
 /// </summary>
 /// <param name="code">The response code received from the server.</param>
 /// <param name="message">The response message received from the server.</param>
 /// <param name="success">A value indicating whether the command succeeded or failed.</param>
 /// <param name="responseType">The type of the response received from the server.</param>
 /// <param name="number">The <see cref="NntpArticle"/> number received from the server.</param>
 /// <param name="messageId">The <see cref="NntpMessageId"/> received from the server.</param>
 public NntpStatResponse(int code, string message, bool success, NntpStatResponseType responseType, int number, NntpMessageId messageId)
     : base(code, message, success)
 {
     ResponseType = responseType;
     Number       = number;
     MessageId    = messageId ?? NntpMessageId.Empty;
 }
Esempio n. 3
0
        public void SerializedInstanceShouldBeDeserializedCorrectly(string messageId)
        {
            var    expectedMessageId = new NntpMessageId(messageId);
            string json            = JsonConvert.SerializeObject(expectedMessageId);
            var    actualMessageId = JsonConvert.DeserializeObject <NntpMessageId>(json);

            Assert.Equal(expectedMessageId, actualMessageId);
        }
Esempio n. 4
0
 /// <summary>
 /// Creates a new instance of the <see cref="NzbSegment"/> class.
 /// </summary>
 /// <param name="number">Segment number of the article, gleaned by parsing (yy/zz).</param>
 /// <param name="size">Size of the article, in bytes, as a number, with no comma separation.</param>
 /// <param name="messageId">The Message-ID of this article.</param>
 public NzbSegment(
     int number,
     long size,
     NntpMessageId messageId)
 {
     Number    = number;
     Size      = size;
     MessageId = messageId ?? NntpMessageId.Empty;
 }
Esempio n. 5
0
        public void EqualsWithSameValuesShouldReturnTrue(string first, string second)
        {
            var firstMessageId  = new NntpMessageId(first);
            var secondMessageId = new NntpMessageId(second);

            Assert.Equal(firstMessageId, secondMessageId);
            Assert.True(firstMessageId == secondMessageId);
            Assert.True(firstMessageId.Equals(secondMessageId));
        }
Esempio n. 6
0
        private static void WriteHeader(INntpConnection connection, string key, string val)
        {
            if (key == NntpHeaders.MessageId)
            {
                val = new NntpMessageId(val);
            }
            string line = $"{key}: {val}";

            if (line.Length <= maxHeaderLength)
            {
                connection.WriteLine(line);
                return;
            }

            // header line is too long, fold it
            connection.WriteLine(line.Substring(0, maxHeaderLength));
            line = line.Substring(maxHeaderLength);
            while (line.Length > maxHeaderLength)
            {
                connection.WriteLine("\t" + line.Substring(0, maxHeaderLength - 1));
                line = line.Substring(maxHeaderLength - 1);
            }
            connection.WriteLine("\t" + line);
        }
Esempio n. 7
0
        //connection.Command($"XFEATURE COMPRESS GZIP{(withTerminator ? " TERMINATOR" : string.Empty)}", new ResponseParser(290));

        public NntpMultiLineResponse Xzhdr(string field, NntpMessageId messageId) => throw new NotImplementedException();
Esempio n. 8
0
 /// <summary>
 /// The <a href="https://tools.ietf.org/html/rfc3977#section-8.6">LIST HEADERS</a>
 /// command returns a list of fields that may be
 /// retrieved using the HDR command.
 /// </summary>
 /// <param name="messageId">The message-id of the article to received from the server.</param>
 /// <returns>A multi-line response containg a list of header
 /// fields that may be retrieved using the HDR command.</returns>
 public NntpMultiLineResponse ListHeaders(NntpMessageId messageId) =>
 connection.MultiLineCommand($"LIST HEADERS {messageId}", new MultiLineResponseParser(215));
Esempio n. 9
0
 /// <summary>
 /// The <a href="https://tools.ietf.org/html/rfc3977#section-8.5">HDR</a>
 /// command provides access to specific fields from an article
 /// specified by message-id, or from a specified article or range of
 /// articles in the currently selected newsgroup.
 /// </summary>
 /// <param name="field">The header field to retrieve.</param>
 /// <param name="messageId">The message-id of the article to received from the server.</param>
 /// <returns>A multi-line response containing the specfied header fields.</returns>
 public NntpMultiLineResponse Hdr(string field, NntpMessageId messageId) =>
 connection.MultiLineCommand($"HDR {field} {messageId}", new MultiLineResponseParser(225));
Esempio n. 10
0
 /// <summary>
 /// The <a href="https://tools.ietf.org/html/rfc3977#section-8.3">OVER</a>
 /// command returns the contents of all the fields in the
 /// database for an article specified by message-id, or from a specified
 /// article or range of articles in the currently selected newsgroup.
 /// </summary>
 /// <param name="messageId">The message-id of the article to received from the server.</param>
 /// <returns>A multi-line response containing header fields.</returns>
 public NntpMultiLineResponse Over(NntpMessageId messageId) =>
 connection.MultiLineCommand($"OVER {messageId}", new MultiLineResponseParser(224));
Esempio n. 11
0
 /// <summary>
 /// The <a href="https://tools.ietf.org/html/rfc3977#section-6.2.4">STAT</a>
 /// command behaves identically to the ARTICLE command except
 /// that, if the article exists, it is NOT presented to the client and
 /// the response code is 223 instead of 220.  Note that the response is
 /// NOT multi-line.
 /// </summary>
 /// <param name="messageId">The message-id of the article to received from the server.</param>
 /// <returns>A stat response object.</returns>
 public NntpStatResponse Stat(NntpMessageId messageId) =>
 connection.Command($"STAT {messageId.ThrowIfNullOrWhiteSpace(nameof(messageId))}", new StatResponseParser());
Esempio n. 12
0
 /// <summary>
 /// The <a href="https://tools.ietf.org/html/rfc3977#section-6.2.3">BODY</a>
 /// command behaves identically to the ARTICLE command except
 /// that, if the article exists, the response code is 222 instead of 220
 /// and only the body is presented (the empty line separating the headers
 /// and body MUST NOT be included).
 /// </summary>
 /// <param name="messageId">The message-id of the article to received from the server.</param>
 /// <returns>An article response object.</returns>
 public NntpArticleResponse Body(NntpMessageId messageId) =>
 connection.MultiLineCommand(
     $"BODY {messageId.ThrowIfNullOrWhiteSpace(nameof(messageId))}",
     new ArticleResponseParser(ArticleRequestType.Body));
Esempio n. 13
0
        /// <summary>
        /// Initialize the <see cref="NntpArticleBuilder"/> from the given <see cref="NntpArticle"/>.
        /// All properties are overwritten.
        /// </summary>
        /// <param name="article">The <see cref="NntpArticle"/> to initialize the <see cref="NntpArticleBuilder"/> with.</param>
        /// <returns>The <see cref="NntpArticleBuilder"/> so that additional calls can be chained.</returns>
        public NntpArticleBuilder InitializeFrom(NntpArticle article)
        {
            messageId = null;
            from      = null;
            subject   = null;

            headers.Clear();
            body.Clear();
            groups.Clear();

            foreach (KeyValuePair <string, ICollection <string> > header in article.Headers)
            {
                foreach (string value in header.Value)
                {
                    switch (header.Key)
                    {
                    case NntpHeaders.MessageId:
                        // skip additional messageid's
                        break;

                    case NntpHeaders.From:
                        if (from == null)
                        {
                            from = value;
                        }
                        break;

                    case NntpHeaders.Subject:
                        if (subject == null)
                        {
                            subject = value;
                        }
                        break;

                    case NntpHeaders.Date:
                        if (dateTime == null)
                        {
                            if (DateTimeOffset.TryParseExact(value, dateFormat, CultureInfo.InvariantCulture,
                                                             DateTimeStyles.None, out DateTimeOffset headerDateTime))
                            {
                                dateTime = headerDateTime;
                            }
                        }
                        break;

                    case NntpHeaders.Newsgroups:
                        // convert group header to list of groups, do not add as header
                        AddGroups(value);
                        break;

                    default:
                        headers.Add(header.Key, value);
                        break;
                    }
                }
            }

            body.AddRange(article.Body);
            messageId = article.MessageId;

            return(this);
        }
Esempio n. 14
0
 /// <summary>
 /// Sets the article's required <see cref="NntpHeaders.MessageId"/> header.
 /// </summary>
 /// <param name="value">The <see cref="NntpHeaders.MessageId"/> header value.</param>
 /// <returns>The <see cref="NntpArticleBuilder"/> so that additional calls can be chained.</returns>
 public NntpArticleBuilder SetMessageId(NntpMessageId value)
 {
     messageId = value.ThrowIfNullOrWhiteSpace(nameof(value));
     return(this);
 }
Esempio n. 15
0
        /// <summary>
        /// Initialize the <see cref="NntpArticleBuilder"/> from the given <see cref="NntpArticle"/>.
        /// All properties are overwritten.
        /// </summary>
        /// <param name="article">The <see cref="NntpArticle"/> to initialize the <see cref="NntpArticleBuilder"/> with.</param>
        /// <returns>The <see cref="NntpArticleBuilder"/> so that additional calls can be chained.</returns>
        public NntpArticleBuilder InitializeFrom(NntpArticle article)
        {
            Guard.ThrowIfNull(article, nameof(article));

            messageId     = new NntpMessageId(article.MessageId.Value);
            groupsBuilder = new NntpGroupsBuilder().Add(article.Groups);
            headers       = new MultiValueDictionary <string, string>();
            from          = null;
            subject       = null;
            dateTime      = null;
            body          = null;

            foreach (KeyValuePair <string, ImmutableHashSet <string> > header in article.Headers)
            {
                foreach (string value in header.Value)
                {
                    switch (header.Key)
                    {
                    case NntpHeaders.MessageId:
                        if (!messageId.HasValue)
                        {
                            messageId = value;
                        }
                        else
                        {
                            log.Warn("Found more than 1 {messageId} header. Skipping it.", NntpHeaders.MessageId);
                        }
                        break;

                    case NntpHeaders.From:
                        if (from == null)
                        {
                            from = value;
                        }
                        else
                        {
                            log.Warn("Found more than 1 {from} header. Skipping it.", NntpHeaders.From);
                        }
                        break;

                    case NntpHeaders.Subject:
                        if (subject == null)
                        {
                            subject = value;
                        }
                        else
                        {
                            log.Warn("Found more than 1 {subject} header. Skipping it.", NntpHeaders.Subject);
                        }
                        break;

                    case NntpHeaders.Date:
                        if (dateTime == null)
                        {
                            if (DateTimeOffset.TryParseExact(value, dateFormat, CultureInfo.InvariantCulture,
                                                             DateTimeStyles.None, out DateTimeOffset headerDateTime))
                            {
                                dateTime = headerDateTime;
                            }
                            else
                            {
                                log.Warn("{date} header has invalid value {value}. Skipping it.", NntpHeaders.Date, value);
                            }
                        }
                        else
                        {
                            log.Warn("Found more than 1 {date} header. Skipping it.", NntpHeaders.Date);
                        }
                        break;

                    case NntpHeaders.Newsgroups:
                        // convert group header to list of groups, do not add as header
                        groupsBuilder.Add(value);
                        break;

                    default:
                        headers.Add(header.Key, value);
                        break;
                    }
                }
            }

            // make copy of body
            body = article.Body.ToList();

            return(this);
        }
Esempio n. 16
0
 /// <summary>
 /// Throws an <exception cref="ArgumentNullException"/> if the messageId of it's value is null.
 /// Throws an <exception cref="ArgumentException"/> if the value of the messageId is empty or
 /// if it consists only of white-space characters.
 /// </summary>
 /// <param name="messageId">The messageId to check.</param>
 /// <param name="name">The name of the messageId.</param>
 /// <returns>The original <see cref="NntpMessageId"/>.</returns>
 /// <exception cref="ArgumentNullException"></exception>
 /// <exception cref="ArgumentException"></exception>
 public static NntpMessageId ThrowIfNullOrWhiteSpace(this NntpMessageId messageId, string name)
 {
     Guard.ThrowIfNull(messageId, name);
     Guard.ThrowIfNullOrWhiteSpace(messageId.Value, name);
     return(messageId);
 }