Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
[assembly: InternalsVisibleTo("GeneXus.Deploy.AzureFunctions.Handlers")]
[assembly: InternalsVisibleTo("AzureFunctionsTest")]
[assembly: InternalsVisibleTo("GXQueue")]
[assembly: InternalsVisibleTo("DotNetCoreUnitTest")]
35 changes: 35 additions & 0 deletions dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
using System.Security;
using System.Threading.Tasks;
using System.Drawing.Imaging;
using System.Net.Http.Headers;

namespace GeneXus.Utils
{
Expand Down Expand Up @@ -4196,6 +4197,40 @@ internal static string AttributeEncode(string sText)
return HttpUtility.HtmlAttributeEncode(sText);
}

internal static string EncodeContentDispositionHeader(string value, int browserType)
{
int filenameIdx = value.IndexOf("filename", StringComparison.OrdinalIgnoreCase);
int eqIdx = value.IndexOf("=", filenameIdx);
if (filenameIdx == -1 || eqIdx == -1 || browserType == GxContext.BROWSER_SAFARI) //Safari does not supports yet ContentDispositon file name encoding value.
{
return value;
}

string rawFilename = value.Substring(eqIdx + 1).Trim();
try
{
string dispositionType = value.Substring(0, value.IndexOf(";")).Trim();
value = new ContentDispositionHeaderValue(dispositionType) { FileName = rawFilename }.ToString();
}
catch (Exception)
{
value = value.Substring(0, eqIdx + 1) + EncodeContentDispositionFileName(rawFilename);
}
return value;
}

private static string EncodeContentDispositionFileName(string filename)
{
try
{
return Uri.EscapeDataString(filename);
}
catch (UriFormatException) //Contains High Surrogate Chars
{
return GXUtil.UrlEncode(filename);
}
}

public static string HtmlEndTag(HTMLElement element)
{
if ((Preferences.DocType == HTMLDocType.HTML4 || Preferences.DocType == HTMLDocType.NONE || Preferences.DocType == HTMLDocType.HTML4S) &&
Expand Down
24 changes: 2 additions & 22 deletions dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,32 +149,12 @@ public void AppendHeader( string name, string value)
{
if(string.Compare(name, "Content-Disposition", true) == 0)
{
value = GetEncodedContentDisposition(value);
value = GXUtil.EncodeContentDispositionHeader(value, _context.GetBrowserType());
}
if (_context!=null)
_context.SetHeader(name, value);
}
private string GetEncodedContentDisposition(string value)
{
int filenameIdx = value.ToLower().IndexOf("filename");
if(filenameIdx != -1)
{
int eqIdx = value.ToLower().IndexOf("=", filenameIdx);
if (eqIdx != -1)
{
string filename = value.Substring(eqIdx + 1).Trim();
try
{
value = value.Substring(0, eqIdx + 1) + Uri.EscapeDataString(filename);
}
catch(UriFormatException) //Contains High Surrogate Chars
{
value = value.Substring(0, eqIdx + 1) + GXUtil.UrlEncode(filename);
}
}
}
return value;
}

}

public class GxSoapRequest : GxHttpRequest
Expand Down
66 changes: 66 additions & 0 deletions dotnet/test/DotNetCoreUnitTest/HttpUtils/HttpUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using GeneXus.Application;
using GeneXus.Utils;
using Xunit;

namespace DotNetCoreUnitTest.HttpUtils
{
public class TestHttpUtils
{
[Fact]
public void TestContentDispositionHeaderEncoding1()
{
String contentDisposition = "attachment; filename=file.pdf";
String expectedContentDisposition = contentDisposition;
DoTest(contentDisposition, expectedContentDisposition);
}

[Fact]
public void TestContentDispositionHeaderEncoding2()
{
String contentDisposition = "attachment; filename=file.pdf";
String expectedContentDisposition = contentDisposition;
DoTest(contentDisposition, expectedContentDisposition, GxContext.BROWSER_SAFARI);
}

[Fact]
public void TestContentDispositionHeaderEncoding3()
{
String contentDisposition = "attachment; filename=注文詳細.xlsx";
String expectedContentDisposition = "attachment; filename=\"=?utf-8?B?5rOo5paH6Kmz57SwLnhsc3g=?=\"";
DoTest(contentDisposition, expectedContentDisposition);
}

[Fact]
public void TestContentDispositionHeaderEncoding4()
{
String contentDisposition = "attachment; filename=注文詳細.xlsx";
String expectedContentDisposition = contentDisposition;
//Safari does not support rfc5987
DoTest(contentDisposition, expectedContentDisposition, GxContext.BROWSER_SAFARI);
}

[Fact]
public void TestContentDispositionHeaderEncoding5()
{
String contentDisposition = "form-data; filename=file.pdf";
String expectedContentDisposition = contentDisposition;
DoTest(contentDisposition, expectedContentDisposition);
}

[Fact]
public void TestContentDispositionHeaderEncoding6()
{
String contentDisposition = "ATTACHMENT; FILEname=注文詳細.xlsx";
String expectedContentDisposition = "ATTACHMENT; filename=\"=?utf-8?B?5rOo5paH6Kmz57SwLnhsc3g=?=\"";
DoTest(contentDisposition, expectedContentDisposition);
}

private static void DoTest(string contentDisposition, string expectedContentDisposition, int browserType = GxContext.BROWSER_CHROME)
{
string encodedValue = GXUtil.EncodeContentDispositionHeader(contentDisposition, browserType);

Assert.Equal(expectedContentDisposition, encodedValue);
}
}
}