public void Setup ()
		{
			var bytes = new byte[9 * 1024];
			int position = 0;

			random = new Random ();
			random.NextBytes (bytes);

			// this is our master stream, all operations on the chained stream
			// should match the results on this stream
			master = new MemoryStream (bytes);
			mbuf = new byte[4096];
			buf = new byte[4096];

			// write the content into the memory block stream in random chunks
			blocks = new MemoryBlockStream ();

			Assert.IsTrue (blocks.CanRead, "Expected to be able to read from the memory block stream.");
			Assert.IsTrue (blocks.CanWrite, "Expected to be able to write to the memory block stream.");
			Assert.IsTrue (blocks.CanSeek, "Expected to be able to seek in the memory block stream.");
			Assert.IsFalse (blocks.CanTimeout, "Did not expect to be able to set timeouts in the memory block stream.");

			while (position < bytes.Length) {
				int n = Math.Min (bytes.Length - position, random.Next () % 4096);
				blocks.Write (bytes, position, n);
				position += n;
			}

			blocks.Seek (0, SeekOrigin.Begin);
		}
Пример #2
0
        public void Setup()
        {
            var bytes = new byte[9 * 1024];
            int position = 0;

            random = new Random ();
            random.NextBytes (bytes);

            // this is our master stream, all operations on the chained stream
            // should match the results on this stream
            master = new MemoryStream (bytes);
            mbuf = new byte[4096];
            buf = new byte[4096];

            // write the content into the memory block stream in random chunks
            blocks = new MemoryBlockStream ();
            while (position < bytes.Length) {
                int n = Math.Min (bytes.Length - position, random.Next () % 4096);
                blocks.Write (bytes, position, n);
                position += n;
            }

            blocks.Seek (0, SeekOrigin.Begin);
        }
Пример #3
0
        static void FetchMessageBody(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            var token = engine.ReadToken (ic.CancellationToken);
            var args = new MessageFlagsChangedEventArgs (index);
            var type = FetchReturnType.MimeMessage;
            bool emit = false;

            if (token.Type != ImapTokenType.OpenParen)
                throw ImapEngine.UnexpectedToken (token, false);

            do {
                token = engine.ReadToken (ic.CancellationToken);

                if (token.Type == ImapTokenType.CloseParen || token.Type == ImapTokenType.Eoln)
                    break;

                if (token.Type != ImapTokenType.Atom)
                    throw ImapEngine.UnexpectedToken (token, false);

                var atom = (string) token.Value;
                ulong modseq;
                uint uid;

                switch (atom) {
                case "BODY":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.OpenBracket)
                        throw ImapEngine.UnexpectedToken (token, false);

                    do {
                        token = engine.ReadToken (ic.CancellationToken);

                        if (token.Type == ImapTokenType.CloseBracket)
                            break;

                        if (token.Type == ImapTokenType.OpenParen) {
                            type = FetchReturnType.Stream;

                            do {
                                token = engine.ReadToken (ic.CancellationToken);

                                if (token.Type == ImapTokenType.CloseParen)
                                    break;

                                if (token.Type != ImapTokenType.Atom)
                                    throw ImapEngine.UnexpectedToken (token, false);
                            } while (true);
                        } else if (token.Type != ImapTokenType.Atom) {
                            throw ImapEngine.UnexpectedToken (token, false);
                        } else {
                            type = FetchReturnType.MimeEntity;
                        }
                    } while (true);

                    if (token.Type != ImapTokenType.CloseBracket)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type == ImapTokenType.Atom) {
                        var region = (string) token.Value;

                        if (region[0] != '<' || region[region.Length - 1] != '>')
                            throw ImapEngine.UnexpectedToken (token, false);

                        token = engine.ReadToken (ic.CancellationToken);

                        type = FetchReturnType.Stream;
                    }

                    if (token.Type != ImapTokenType.Literal)
                        throw ImapEngine.UnexpectedToken (token, false);

                    switch (type) {
                    case FetchReturnType.MimeMessage:
                        ic.UserData = MimeMessage.Load (engine.Stream, ic.CancellationToken);
                        break;
                    case FetchReturnType.MimeEntity:
                        ic.UserData = MimeEntity.Load (engine.Stream, ic.CancellationToken);
                        break;
                    default:
                        var stream = new MemoryBlockStream ();
                        var buf = new byte[4096];
                        int nread;

                        ic.CancellationToken.ThrowIfCancellationRequested ();
                        while ((nread = engine.Stream.Read (buf, 0, buf.Length)) > 0) {
                            ic.CancellationToken.ThrowIfCancellationRequested ();
                            stream.Write (buf, 0, nread);
                        }

                        ic.UserData = stream;
                        break;
                    }

                    break;
                case "UID":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out uid) || uid == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    args.Uid = new UniqueId (uid);
                    break;
                case "MODSEQ":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.OpenParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out modseq) || modseq == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.CloseParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    args.ModSeq = modseq;
                    break;
                case "FLAGS":
                    // even though we didn't request this piece of information, the IMAP server
                    // may send it if another client has recently modified the message flags.
                    args.Flags = ImapUtils.ParseFlagsList (engine, ic.CancellationToken);
                    emit = true;
                    break;
                default:
                    throw ImapEngine.UnexpectedToken (token, false);
                }
            } while (true);

            if (token.Type != ImapTokenType.CloseParen)
                throw ImapEngine.UnexpectedToken (token, false);

            if (emit)
                ic.Folder.OnFlagsChanged (args);
        }
Пример #4
0
		/// <summary>
		/// Decrypts the specified encryptedData and extracts the digital signers if the content was also signed.
		/// </summary>
		/// <remarks>
		/// Decrypts the specified encryptedData and extracts the digital signers if the content was also signed.
		/// </remarks>
		/// <returns>The decrypted stream.</returns>
		/// <param name="encryptedData">The encrypted data.</param>
		/// <param name="signatures">A list of digital signatures if the data was both signed and encrypted.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="encryptedData"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="PrivateKeyNotFoundException">
		/// The private key could not be found to decrypt the stream.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The user chose to cancel the password prompt.
		/// </exception>
		/// <exception cref="System.UnauthorizedAccessException">
		/// 3 bad attempts were made to unlock the secret key.
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">
		/// An OpenPGP error occurred.
		/// </exception>
		public Stream GetDecryptedStream (Stream encryptedData, out DigitalSignatureCollection signatures)
		{
			if (encryptedData == null)
				throw new ArgumentNullException ("encryptedData");

			using (var armored = new ArmoredInputStream (encryptedData)) {
				var factory = new PgpObjectFactory (armored);
				var obj = factory.NextPgpObject ();
				var list = obj as PgpEncryptedDataList;

				if (list == null) {
					// probably a PgpMarker...
					obj = factory.NextPgpObject ();

					list = obj as PgpEncryptedDataList;

					if (list == null)
						throw new PgpException ("Unexpected OpenPGP packet.");
				}

				PgpPublicKeyEncryptedData encrypted = null;
				PrivateKeyNotFoundException pkex = null;
				bool hasEncryptedPackets = false;
				PgpSecretKey secret = null;

				foreach (PgpEncryptedData data in list.GetEncryptedDataObjects ()) {
					if ((encrypted = data as PgpPublicKeyEncryptedData) == null)
						continue;

					hasEncryptedPackets = true;

					try {
						secret = GetSecretKey (encrypted.KeyId);
						break;
					} catch (PrivateKeyNotFoundException ex) {
						pkex = ex;
					}
				}

				if (!hasEncryptedPackets)
					throw new PgpException ("No encrypted packets found.");

				if (secret == null)
					throw pkex;

				factory = new PgpObjectFactory (encrypted.GetDataStream (GetPrivateKey (secret)));
				List<IDigitalSignature> onepassList = null;
				PgpSignatureList signatureList = null;
				PgpCompressedData compressed = null;
				var memory = new MemoryBlockStream ();

				obj = factory.NextPgpObject ();
				while (obj != null) {
					if (obj is PgpCompressedData) {
						if (compressed != null)
							throw new PgpException ("Recursive compression packets are not supported.");

						compressed = (PgpCompressedData) obj;
						factory = new PgpObjectFactory (compressed.GetDataStream ());
					} else if (obj is PgpOnePassSignatureList) {
						if (memory.Length == 0) {
							var onepasses = (PgpOnePassSignatureList) obj;

							onepassList = new List<IDigitalSignature> ();

							for (int i = 0; i < onepasses.Count; i++) {
								var onepass = onepasses[i];
								var pubkey = PublicKeyRingBundle.GetPublicKey (onepass.KeyId);

								if (pubkey == null) {
									// too messy, pretend we never found a one-pass signature list
									onepassList = null;
									break;
								}

								onepass.InitVerify (pubkey);

								var signature = new OpenPgpDigitalSignature (pubkey, onepass) {
									PublicKeyAlgorithm = GetPublicKeyAlgorithm (onepass.KeyAlgorithm),
									DigestAlgorithm = GetDigestAlgorithm (onepass.HashAlgorithm),
								};

								onepassList.Add (signature);
							}
						}
					} else if (obj is PgpSignatureList) {
						signatureList = (PgpSignatureList) obj;
					} else if (obj is PgpLiteralData) {
						var literal = (PgpLiteralData) obj;

						using (var stream = literal.GetDataStream ()) {
							var buffer = new byte[4096];
							int nread;

							while ((nread = stream.Read (buffer, 0, buffer.Length)) > 0) {
								if (onepassList != null) {
									// update our one-pass signatures...
									for (int index = 0; index < nread; index++) {
										byte c = buffer[index];

										for (int i = 0; i < onepassList.Count; i++) {
											var pgp = (OpenPgpDigitalSignature) onepassList[i];
											pgp.OnePassSignature.Update (c);
										}
									}
								}

								memory.Write (buffer, 0, nread);
							}
						}
					}

					obj = factory.NextPgpObject ();
				}

				memory.Position = 0;

				if (signatureList != null) {
					if (onepassList != null && signatureList.Count == onepassList.Count) {
						for (int i = 0; i < onepassList.Count; i++) {
							var pgp = (OpenPgpDigitalSignature) onepassList[i];
							pgp.CreationDate = signatureList[i].CreationTime;
							pgp.Signature = signatureList[i];
						}

						signatures = new DigitalSignatureCollection (onepassList);
					} else {
						signatures = GetDigitalSignatures (signatureList, memory);
						memory.Position = 0;
					}
				} else {
					signatures = null;
				}

				return memory;
			}
		}
Пример #5
0
        static void FetchMessageBody(ImapEngine engine, ImapCommand ic, int index)
        {
            var streams = (Dictionary<string, Stream>) ic.UserData;
            var token = engine.ReadToken (ic.CancellationToken);
            var labels = new MessageLabelsChangedEventArgs (index);
            var flags = new MessageFlagsChangedEventArgs (index);
            bool labelsChanged = false;
            bool flagsChanged = false;
            var buf = new byte[4096];
            string specifier;
            Stream stream;
            int nread;

            if (token.Type != ImapTokenType.OpenParen)
                throw ImapEngine.UnexpectedToken (token, false);

            do {
                token = engine.ReadToken (ic.CancellationToken);

                if (token.Type == ImapTokenType.CloseParen || token.Type == ImapTokenType.Eoln)
                    break;

                if (token.Type != ImapTokenType.Atom)
                    throw ImapEngine.UnexpectedToken (token, false);

                var atom = (string) token.Value;
                ulong modseq;
                uint uid;

                switch (atom) {
                case "BODY":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.OpenBracket)
                        throw ImapEngine.UnexpectedToken (token, false);

                    specifier = string.Empty;

                    do {
                        token = engine.ReadToken (ic.CancellationToken);

                        if (token.Type == ImapTokenType.CloseBracket)
                            break;

                        if (token.Type == ImapTokenType.OpenParen) {
                            do {
                                token = engine.ReadToken (ic.CancellationToken);

                                if (token.Type == ImapTokenType.CloseParen)
                                    break;

                                if (token.Type != ImapTokenType.Atom)
                                    throw ImapEngine.UnexpectedToken (token, false);
                            } while (true);
                        } else if (token.Type != ImapTokenType.Atom) {
                            throw ImapEngine.UnexpectedToken (token, false);
                        } else {
                            specifier += (string) token.Value;
                        }
                    } while (true);

                    if (token.Type != ImapTokenType.CloseBracket)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type == ImapTokenType.Atom) {
                        var region = (string) token.Value;

                        if (region[0] != '<' || region[region.Length - 1] != '>')
                            throw ImapEngine.UnexpectedToken (token, false);

                        token = engine.ReadToken (ic.CancellationToken);
                    }

                    switch (token.Type) {
                    case ImapTokenType.Literal:
                        stream = new MemoryBlockStream ();

                        while ((nread = engine.Stream.Read (buf, 0, buf.Length, ic.CancellationToken)) > 0)
                            stream.Write (buf, 0, nread);

                        streams[specifier] = stream;
                        stream.Position = 0;
                        break;
                    case ImapTokenType.QString:
                    case ImapTokenType.Atom:
                        stream = new MemoryStream (Encoding.UTF8.GetBytes ((string) token.Value), false);
                        break;
                    default:
                        throw ImapEngine.UnexpectedToken (token, false);
                    }

                    break;
                case "UID":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out uid) || uid == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    labels.UniqueId = new UniqueId (uid);
                    flags.UniqueId = new UniqueId (uid);
                    break;
                case "MODSEQ":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.OpenParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out modseq) || modseq == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.CloseParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    labels.ModSeq = modseq;
                    flags.ModSeq = modseq;
                    break;
                case "FLAGS":
                    // even though we didn't request this piece of information, the IMAP server
                    // may send it if another client has recently modified the message flags.
                    flags.Flags = ImapUtils.ParseFlagsList (engine, flags.UserFlags, ic.CancellationToken);
                    flagsChanged = true;
                    break;
                case "X-GM-LABELS":
                    // even though we didn't request this piece of information, the IMAP server
                    // may send it if another client has recently modified the message labels.
                    labels.Labels = ImapUtils.ParseLabelsList (engine, ic.CancellationToken);
                    labelsChanged = true;
                    break;
                default:
                    throw ImapEngine.UnexpectedToken (token, false);
                }
            } while (true);

            if (token.Type != ImapTokenType.CloseParen)
                throw ImapEngine.UnexpectedToken (token, false);

            if (flagsChanged)
                ic.Folder.OnMessageFlagsChanged (flags);

            if (labelsChanged)
                ic.Folder.OnMessageLabelsChanged (labels);
        }
		void OnFieldsChanged (object sender, HeaderListChangedEventArgs e)
		{
			var options = FormatOptions.GetDefault ();
			var stream = new MemoryBlockStream ();

			fields.WriteTo (options, stream);
			stream.Write (options.NewLineBytes, 0, options.NewLineBytes.Length);
			stream.Position = 0;

			ContentObject = new ContentObject (stream);
		}
Пример #7
0
		public void TestJwzMbox ()
		{
			var summary = File.ReadAllText (Path.Combine (MboxDataDir, "jwz-summary.txt")).Replace ("\r\n", "\n");
			var options = FormatOptions.Default.Clone ();
			var original = new MemoryBlockStream ();
			var output = new MemoryBlockStream ();
			var builder = new StringBuilder ();
			var expected = new byte[4096];
			var buffer = new byte[4096];
			int nx, n;

			options.NewLineFormat = NewLineFormat.Unix;

			using (var stream = File.OpenRead (Path.Combine (MboxDataDir, "jwz.mbox.txt"))) {
				var parser = new MimeParser (stream, MimeFormat.Mbox);
				int count = 0;

				while (!parser.IsEndOfStream) {
					var message = parser.ParseMessage ();

					builder.AppendFormat ("{0}", parser.MboxMarker).Append ('\n');
					if (message.From.Count > 0)
						builder.AppendFormat ("From: {0}", message.From).Append ('\n');
					if (message.To.Count > 0)
						builder.AppendFormat ("To: {0}", message.To).Append ('\n');
					builder.AppendFormat ("Subject: {0}", message.Subject).Append ('\n');
					builder.AppendFormat ("Date: {0}", DateUtils.FormatDate (message.Date)).Append ('\n');
					DumpMimeTree (builder, message);
					builder.Append ('\n');

					var marker = Encoding.UTF8.GetBytes ((count > 0 ? "\n" : string.Empty) + parser.MboxMarker + "\n");
					output.Write (marker, 0, marker.Length);
					message.WriteTo (options, output);
					count++;
				}
			}

			string actual = builder.ToString ();

			// WORKAROUND: Mono's iso-2022-jp decoder breaks on this input in versions <= 3.2.3 but is fixed in 3.2.4+
			string iso2022jp = Encoding.GetEncoding ("iso-2022-jp").GetString (Convert.FromBase64String ("GyRAOjRGI0stGyhK"));
			if (iso2022jp != "佐藤豊")
				actual = actual.Replace (iso2022jp, "佐藤豊");

			Assert.AreEqual (summary, actual, "Summaries do not match for jwz.mbox");

			using (var stream = File.OpenRead (Path.Combine (MboxDataDir, "jwz.mbox.txt"))) {
				using (var filtered = new FilteredStream (original)) {
					filtered.Add (new Dos2UnixFilter ());
					stream.CopyTo (filtered);
					filtered.Flush ();
				}
			}

			original.Position = 0;
			output.Position = 0;

			Assert.AreEqual (original.Length, output.Length, "The length of the mbox did not match.");

			do {
				var position = original.Position;

				nx = original.Read (expected, 0, expected.Length);
				n = output.Read (buffer, 0, buffer.Length);

				if (nx == 0)
					break;

				for (int i = 0; i < nx; i++) {
					if (buffer[i] == expected[i])
						continue;

					var strExpected = CharsetUtils.Latin1.GetString (expected, 0, nx);
					var strActual = CharsetUtils.Latin1.GetString (buffer, 0, n);

					Assert.AreEqual (strExpected, strActual, "The mbox differs at position {0}", position + i);
				}
			} while (true);
		}
        private bool StoreEntities(OutgoingEmail email, List<string> attachmentList)
        {
            foreach (string iter in attachmentList)
            {
                FileStream stream = File.OpenRead(iter);
                if (!stream.CanRead)
                {
                    return false;
                }

                string mimeType = MimeTypes.GetMimeType(iter);
                ContentType fileType = ContentType.Parse(mimeType);
                MimePart attachment;
                if (fileType.IsMimeType("text", "*"))
                {
                    attachment = new TextPart(fileType.MediaSubtype);
                    foreach (var param in fileType.Parameters)
                        attachment.ContentType.Parameters.Add(param);
                }
                else
                {
                    attachment = new MimePart(fileType);
                }
                attachment.FileName = Path.GetFileName(iter);
                attachment.IsAttachment = true;

                MemoryBlockStream memoryBlockStream = new MemoryBlockStream();
                BestEncodingFilter encodingFilter = new BestEncodingFilter();
                byte[] fileBuffer = new byte[4096];
                int index, length, bytesRead;

                while ((bytesRead = stream.Read(fileBuffer, 0, fileBuffer.Length)) > 0)
                {
                    encodingFilter.Filter(fileBuffer, 0, bytesRead, out index, out length);
                    memoryBlockStream.Write(fileBuffer, 0, bytesRead);
                }

                encodingFilter.Flush(fileBuffer, 0, 0, out index, out length);
                memoryBlockStream.Position = 0;

                attachment.ContentTransferEncoding = encodingFilter.GetBestEncoding(EncodingConstraint.SevenBit);
                attachment.ContentObject = new ContentObject(memoryBlockStream);

                if (attachment != null) email.AttachmentList.Add(attachment);
            }
            return true;
        }