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); }
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); }
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); }
/// <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; } }
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); }
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; }