private static ImapSearchCriteria FromUri(Uri uri,
                                              bool convertLiteral,
                                              bool synchronizedLiteral,
                                              bool splitCharset,
                                              out bool containsLiteral,
                                              out string charset)
        {
            if (uri == null)
            throw new ArgumentNullException("uri");

              containsLiteral = false;
              charset = null;

              var q = uri.Query;

              if (q.Length == 0)
            return null;
              else if (q.Length == 1) // '?'
            return new ImapSearchCriteria(string.Empty);

              /*
               * http://tools.ietf.org/html/rfc5092
               * RFC 5092 - IMAP URL Scheme
               *
               *    Note that quoted strings and non-synchronizing literals [LITERAL+]
               *    are allowed in the <enc-search> content; however, synchronizing
               *    literals are not allowed, as their presence would effectively mean
               *    that the agent interpreting IMAP URLs needs to parse an <enc-search>
               *    content, find all synchronizing literals, and perform proper command
               *    continuation request handling (see Sections 4.3 and 7 of [IMAP4]).
               */
              var query = PercentEncoding.Decode(q.Substring(1), false);
              var len = query.Length;
              var convertedQuery = new ByteStringBuilder(len);

              if (splitCharset) {
            var queryString = new ByteString(query);

            if (queryString.StartsWithIgnoreCase(charsetSpecification)) {
              // CHARSET<SP>astring<SP>
              var posEndOfCharset = queryString.IndexOf(Octets.SP, charsetSpecification.Length);

              if (posEndOfCharset < 0) {
            throw new ArgumentException("search criteria contains invalid charset specification", "uri");
              }
              else {
            charset = queryString.Substring(charsetSpecification.Length,
                                            posEndOfCharset - charsetSpecification.Length).ToString();

            query = queryString.Substring(posEndOfCharset + 1).ByteArray;
            len = query.Length;
              }
            }
              }

              for (var i = 0; i < len;) {
            if (query[i] == ImapOctets.DQuote) {
              /*
               * quoted
               */
              var start = i;

              for (;;) {
            if (++i == len)
              throw new ArgumentException("search criteria contains unclosed quoted string", "uri");

            if (query[i] == ImapOctets.DQuote) {
              break;
            }
            else if (query[i] == ImapOctets.BackSlash) {
              if (++i == len || !(query[i] == ImapOctets.DQuote || query[i] == ImapOctets.BackSlash))
                throw new ArgumentException("search criteria contains invalid quoted string", "uri");
            }
              }

              i++;

              convertedQuery.Append(query, start, i - start);
            }
            else if (query[i] == ImapOctets.OpenBrace) {
              /*
               * literal
               */
              var start = i;
              var isLiteralSynchronizing = false;
              var literalLength = 0;

              for (;;) {
            if (++i == len)
              throw new ArgumentException("search criteria contains incomplete literal", "uri");

            if (Octets.IsDecimalNumber(query[i])) {
              literalLength = literalLength * 10 + (query[i] - 0x30 /* '0' */);
              // TODO: check length
            }
            else if (query[i] == ImapOctets.CloseBrace) {
              // {xxx}
              isLiteralSynchronizing = true;
              break;
            }
            else if (query[i] == ImapOctets.Plus) {
              // {xxx+}
              if (++i == len || query[i] != ImapOctets.CloseBrace)
                throw new ArgumentException("search criteria contains incomplete non-synchronized literal", "uri");
              isLiteralSynchronizing = false;
              break;
            }
            else {
              throw new ArgumentException("search criteria contains invalid literal", "uri");
            }
              }

              if (++i == len || query[i] != Octets.CR)
            throw new ArgumentException("search criteria contains incomplete literal (CR not found)", "uri");
              if (++i == len || query[i] != Octets.LF)
            throw new ArgumentException("search criteria contains incomplete literal (LF not found)", "uri");
              if (++i == len && 0 < literalLength)
            throw new ArgumentException("search criteria contains incomplete literal (unexpected EOL)", "uri");

              containsLiteral = true;

              if (convertLiteral) {
            if (synchronizedLiteral)
              convertedQuery.Append(string.Format("{{{0}}}\x0d\x0a", literalLength));
            else
              convertedQuery.Append(string.Format("{{{0}+}}\x0d\x0a", literalLength));

            convertedQuery.Append(query, i, literalLength);
              }
              else {
            if (synchronizedLiteral != isLiteralSynchronizing)
              throw new ArgumentException(synchronizedLiteral
                                          ? "search criteria contains non-synchronizing literal"
                                          : "search criteria contains synchronizing literal",
                                          "uri");

            convertedQuery.Append(query, start, i - start + literalLength);
              }

              i += literalLength;
            }
            else {
              convertedQuery.Append(query[i++]);
            }
              }

              return new ImapSearchCriteria(new ImapPreformattedString(convertedQuery.ToByteArray()));
        }
Exemple #2
0
        public void TestStartsWithIgnoreCase()
        {
            var str = new ByteString("aBC");

              Assert.IsTrue(str.StartsWithIgnoreCase(new ByteString("abc")));
              Assert.IsTrue(str.StartsWithIgnoreCase(new ByteString("aBc")));
              Assert.IsTrue(str.StartsWithIgnoreCase(new ByteString("aBC")));
              Assert.IsTrue(str.StartsWithIgnoreCase(new ByteString("ABc")));
              Assert.IsTrue(str.StartsWithIgnoreCase(new ByteString("AbC")));
              Assert.IsFalse(str.StartsWithIgnoreCase(new ByteString("abd")));
              Assert.IsFalse(str.StartsWithIgnoreCase(new ByteString("abcdef")));
        }