Skip to content

Commit

Permalink
Removed Flush() logic from DKIM body filters
Browse files Browse the repository at this point in the history
The problem is that MimePart.WriteTo() will flush the stream
after transcoding the content in cases where the content is
not already in its target encoding.

Fixes issue #178
  • Loading branch information
jstedfast committed Oct 7, 2015
1 parent b2a2bb2 commit 0d7b4d4
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 75 deletions.
73 changes: 73 additions & 0 deletions MimeKit/Cryptography/DkimBodyFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// DkimBodyFilterBase.cs
//
// Author: Jeffrey Stedfast <jeff@xamarin.com>
//
// Copyright (c) 2015 Xamarin Inc. (www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

using MimeKit.IO.Filters;

namespace MimeKit.Cryptography
{
/// <summary>
/// A base implementation for DKIM body filters.
/// </summary>
/// <remarks>
/// A base implementation for DKIM body filters.
/// </remarks>
abstract class DkimBodyFilter : MimeFilterBase
{
/// <summary>
/// Get or set whether the last filtered character was a newline.
/// </summary>
/// <remarks>
/// Gets or sets whether the last filtered character was a newline.
/// </remarks>
internal protected bool LastWasNewLine;

/// <summary>
/// Get or set whether the current line is empty.
/// </summary>
/// <remarks>
/// Gets or sets whether the current line is empty.
/// </remarks>
protected bool IsEmptyLine;

/// <summary>
/// Get or set the number of consecutive empty lines encountered.
/// </summary>
/// <remarks>
/// Gets or sets the number of consecutive empty lines encountered.
/// </remarks>
protected int EmptyLines;

/// <summary>
/// Initializes a new instance of the <see cref="MimeKit.Cryptography.DkimBodyFilterBase"/> class.
/// </summary>
/// <remarks>
/// Creates a new <see cref="DkimBodyFilterBase"/>.
/// </remarks>
protected DkimBodyFilter ()
{
}
}
}
60 changes: 24 additions & 36 deletions MimeKit/Cryptography/DkimRelaxedBodyFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
//

using MimeKit.Utils;
using MimeKit.IO.Filters;

namespace MimeKit.Cryptography {
/// <summary>
Expand All @@ -34,10 +33,9 @@ namespace MimeKit.Cryptography {
/// <remarks>
/// A filter for the DKIM relaxed body canonicalization.
/// </remarks>
class DkimRelaxedBodyFilter : MimeFilterBase
class DkimRelaxedBodyFilter : DkimBodyFilter
{
bool lastWasNewLine, isEmptyLine, lwsp;
int emptyLines;
bool lwsp;

/// <summary>
/// Initializes a new instance of the <see cref="MimeKit.Cryptography.DkimRelaxedBodyFilter"/> class.
Expand All @@ -47,13 +45,13 @@ class DkimRelaxedBodyFilter : MimeFilterBase
/// </remarks>
public DkimRelaxedBodyFilter ()
{
lastWasNewLine = true;
isEmptyLine = true;
emptyLines = 0;
LastWasNewLine = true;
IsEmptyLine = true;
EmptyLines = 0;
lwsp = false;
}

unsafe int Filter (byte* inbuf, int length, byte* outbuf, bool flush)
unsafe int Filter (byte* inbuf, int length, byte* outbuf)
{
byte* inend = inbuf + length;
byte* outptr = outbuf;
Expand All @@ -62,36 +60,36 @@ unsafe int Filter (byte* inbuf, int length, byte* outbuf, bool flush)

while (inptr < inend) {
if (*inptr == (byte) '\r') {
if (!isEmptyLine) {
if (!IsEmptyLine) {
*outptr++ = *inptr;
lwsp = false;
count++;
}
} else if (*inptr == (byte) '\n') {
if (!isEmptyLine) {
if (!IsEmptyLine) {
*outptr++ = *inptr;
lastWasNewLine = true;
isEmptyLine = true;
emptyLines = 0;
LastWasNewLine = true;
IsEmptyLine = true;
EmptyLines = 0;
lwsp = false;
count++;
} else {
emptyLines++;
EmptyLines++;
}
} else {
if (emptyLines > 0) {
if (EmptyLines > 0) {
// unwind our collection of empty lines
while (emptyLines > 0) {
while (EmptyLines > 0) {
*outptr++ = (byte) '\r';
*outptr++ = (byte) '\n';
emptyLines--;
EmptyLines--;
count += 2;
}
}

if ((*inptr).IsBlank ()) {
lastWasNewLine = false;
isEmptyLine = false;
LastWasNewLine = false;
IsEmptyLine = false;
lwsp = true;
} else {
if (lwsp) {
Expand All @@ -100,8 +98,8 @@ unsafe int Filter (byte* inbuf, int length, byte* outbuf, bool flush)
count++;
}

lastWasNewLine = false;
isEmptyLine = false;
LastWasNewLine = false;
IsEmptyLine = false;
lwsp = false;

*outptr++ = *inptr;
Expand All @@ -112,16 +110,6 @@ unsafe int Filter (byte* inbuf, int length, byte* outbuf, bool flush)
inptr++;
}

if (flush && !lastWasNewLine) {
*outptr++ = (byte) '\r';
*outptr++ = (byte) '\n';
lastWasNewLine = true;
isEmptyLine = true;
emptyLines = 0;
lwsp = false;
count += 2;
}

return count;
}

Expand All @@ -141,11 +129,11 @@ unsafe int Filter (byte* inbuf, int length, byte* outbuf, bool flush)
/// <param name="flush">If set to <c>true</c>, all internally buffered data should be flushed to the output buffer.</param>
protected override byte[] Filter (byte[] input, int startIndex, int length, out int outputIndex, out int outputLength, bool flush)
{
EnsureOutputSize (length + (lwsp ? 1 : 0) + emptyLines * 2 + (flush ? 2 : 0), false);
EnsureOutputSize (length + (lwsp ? 1 : 0) + EmptyLines * 2, false);

unsafe {
fixed (byte* inptr = input, outptr = OutputBuffer) {
outputLength = Filter (inptr + startIndex, length, outptr, flush);
outputLength = Filter (inptr + startIndex, length, outptr);
}
}

Expand All @@ -162,9 +150,9 @@ protected override byte[] Filter (byte[] input, int startIndex, int length, out
/// </remarks>
public override void Reset ()
{
lastWasNewLine = true;
isEmptyLine = true;
emptyLines = 0;
LastWasNewLine = true;
IsEmptyLine = true;
EmptyLines = 0;
lwsp = false;

base.Reset ();
Expand Down
56 changes: 21 additions & 35 deletions MimeKit/Cryptography/DkimSimpleBodyFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,15 @@
// THE SOFTWARE.
//

using MimeKit.IO.Filters;

namespace MimeKit.Cryptography {
/// <summary>
/// A filter for the DKIM simple body canonicalization.
/// </summary>
/// <remarks>
/// A filter for the DKIM simple body canonicalization.
/// </remarks>
class DkimSimpleBodyFilter : MimeFilterBase
class DkimSimpleBodyFilter : DkimBodyFilter
{
bool lastWasNewLine, isEmptyLine;
int emptyLines;

/// <summary>
/// Initializes a new instance of the <see cref="MimeKit.Cryptography.DkimSimpleBodyFilter"/> class.
/// </summary>
Expand All @@ -46,12 +41,12 @@ class DkimSimpleBodyFilter : MimeFilterBase
/// </remarks>
public DkimSimpleBodyFilter ()
{
lastWasNewLine = false;
isEmptyLine = true;
emptyLines = 0;
LastWasNewLine = false;
IsEmptyLine = true;
EmptyLines = 0;
}

unsafe int Filter (byte* inbuf, int length, byte* outbuf, bool flush)
unsafe int Filter (byte* inbuf, int length, byte* outbuf)
{
byte* inend = inbuf + length;
byte* outptr = outbuf;
Expand All @@ -60,33 +55,33 @@ unsafe int Filter (byte* inbuf, int length, byte* outbuf, bool flush)

while (inptr < inend) {
if (*inptr == (byte) '\r') {
if (!isEmptyLine) {
if (!IsEmptyLine) {
*outptr++ = *inptr;
count++;
}
} else if (*inptr == (byte) '\n') {
if (!isEmptyLine) {
if (!IsEmptyLine) {
*outptr++ = *inptr;
lastWasNewLine = true;
isEmptyLine = true;
emptyLines = 0;
LastWasNewLine = true;
IsEmptyLine = true;
EmptyLines = 0;
count++;
} else {
emptyLines++;
EmptyLines++;
}
} else {
if (emptyLines > 0) {
if (EmptyLines > 0) {
// unwind our collection of empty lines
while (emptyLines > 0) {
while (EmptyLines > 0) {
*outptr++ = (byte) '\r';
*outptr++ = (byte) '\n';
emptyLines--;
EmptyLines--;
count += 2;
}
}

lastWasNewLine = false;
isEmptyLine = false;
LastWasNewLine = false;
IsEmptyLine = false;

*outptr++ = *inptr;
count++;
Expand All @@ -95,15 +90,6 @@ unsafe int Filter (byte* inbuf, int length, byte* outbuf, bool flush)
inptr++;
}

if (flush && !lastWasNewLine) {
*outptr++ = (byte) '\r';
*outptr++ = (byte) '\n';
lastWasNewLine = true;
isEmptyLine = true;
emptyLines = 0;
count += 2;
}

return count;
}

Expand All @@ -123,11 +109,11 @@ unsafe int Filter (byte* inbuf, int length, byte* outbuf, bool flush)
/// <param name="flush">If set to <c>true</c>, all internally buffered data should be flushed to the output buffer.</param>
protected override byte[] Filter (byte[] input, int startIndex, int length, out int outputIndex, out int outputLength, bool flush)
{
EnsureOutputSize (length + emptyLines * 2 + (flush ? 2 : 0), false);
EnsureOutputSize (length + EmptyLines * 2, false);

unsafe {
fixed (byte* inptr = input, outptr = OutputBuffer) {
outputLength = Filter (inptr + startIndex, length, outptr, flush);
outputLength = Filter (inptr + startIndex, length, outptr);
}
}

Expand All @@ -144,9 +130,9 @@ protected override byte[] Filter (byte[] input, int startIndex, int length, out
/// </remarks>
public override void Reset ()
{
lastWasNewLine = false;
isEmptyLine = true;
emptyLines = 0;
LastWasNewLine = false;
IsEmptyLine = true;
EmptyLines = 0;

base.Reset ();
}
Expand Down
3 changes: 2 additions & 1 deletion MimeKit/MimeKit.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
<Compile Include="Cryptography\DigestAlgorithm.cs" />
<Compile Include="Cryptography\DigitalSignatureCollection.cs" />
<Compile Include="Cryptography\DigitalSignatureVerifyException.cs" />
<Compile Include="Cryptography\DkimBodyFilter.cs" />
<Compile Include="Cryptography\DkimCanonicalizationAlgorithm.cs" />
<Compile Include="Cryptography\DkimHashStream.cs" />
<Compile Include="Cryptography\DkimRelaxedBodyFilter.cs" />
Expand Down Expand Up @@ -256,7 +257,6 @@
<Folder Include="Tnef\" />
<Folder Include="Utils\" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
<ProjectExtensions>
<MonoDevelop>
<Properties>
Expand All @@ -266,4 +266,5 @@
</Properties>
</MonoDevelop>
</ProjectExtensions>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
</Project>
1 change: 1 addition & 0 deletions MimeKit/MimeKit.Mac.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
<Compile Include="Cryptography\DigestAlgorithm.cs" />
<Compile Include="Cryptography\DigitalSignatureCollection.cs" />
<Compile Include="Cryptography\DigitalSignatureVerifyException.cs" />
<Compile Include="Cryptography\DkimBodyFilter.cs" />
<Compile Include="Cryptography\DkimCanonicalizationAlgorithm.cs" />
<Compile Include="Cryptography\DkimHashStream.cs" />
<Compile Include="Cryptography\DkimRelaxedBodyFilter.cs" />
Expand Down
1 change: 1 addition & 0 deletions MimeKit/MimeKit.Net35.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Compile Include="Cryptography\DigestAlgorithm.cs" />
<Compile Include="Cryptography\DigitalSignatureCollection.cs" />
<Compile Include="Cryptography\DigitalSignatureVerifyException.cs" />
<Compile Include="Cryptography\DkimBodyFilter.cs" />
<Compile Include="Cryptography\DkimCanonicalizationAlgorithm.cs" />
<Compile Include="Cryptography\DkimHashStream.cs" />
<Compile Include="Cryptography\DkimRelaxedBodyFilter.cs" />
Expand Down
1 change: 1 addition & 0 deletions MimeKit/MimeKit.Net40.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
<Compile Include="Cryptography\DigestAlgorithm.cs" />
<Compile Include="Cryptography\DigitalSignatureCollection.cs" />
<Compile Include="Cryptography\DigitalSignatureVerifyException.cs" />
<Compile Include="Cryptography\DkimBodyFilter.cs" />
<Compile Include="Cryptography\DkimCanonicalizationAlgorithm.cs" />
<Compile Include="Cryptography\DkimHashStream.cs" />
<Compile Include="Cryptography\DkimRelaxedBodyFilter.cs" />
Expand Down
1 change: 1 addition & 0 deletions MimeKit/MimeKit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Compile Include="Cryptography\DigestAlgorithm.cs" />
<Compile Include="Cryptography\DigitalSignatureCollection.cs" />
<Compile Include="Cryptography\DigitalSignatureVerifyException.cs" />
<Compile Include="Cryptography\DkimBodyFilter.cs" />
<Compile Include="Cryptography\DkimCanonicalizationAlgorithm.cs" />
<Compile Include="Cryptography\DkimHashStream.cs" />
<Compile Include="Cryptography\DkimRelaxedBodyFilter.cs" />
Expand Down
Loading

0 comments on commit 0d7b4d4

Please sign in to comment.