Url parameter values with special characters and IE - c#

Have a webpage that is opened from another system with parameters that can contain extended ascii characters:
http://<host>/submitpage.cshtml?pname=SomeName
The cshtml webpage reads the parameters as usual with:
var pname = Request["pname"];
and shows it on the page with #pname
Works fine for all browsers except IE (even IE11) when pname=Günther or another name with foreign characters; ü, ø and so on.
Example:
http://<host>/submitpage.cshtml?pname=Günther
results in G�nther
The webpage is using <meta charset="UTF-8" />
Any solution? I have no control over the submitting system, som the url cannot be encoded before submit.

So between RFC3986 and RFC2234, we have the following relevant rules for URIs
pchar = unreserved / pct-encoded / sub-delims / ":" / "#"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
pct-encoded = "%" HEXDIG HEXDIG
query = *( pchar / "/" / "?" )
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
DIGIT = %x30-39 ; 0-9
so any implementation that accepts the unencoded letter ü is non-standards compliant and any user agent issuing requests with such characters is also non-compliant. It sounds like you know that this is the case.
IMO, it's a dangerous game making your own system more permissive to patch over the faults of "out of your control" systems. Are you sure the issuer of this request can't fix their code?

Related

Reformatting a string number value to use minus sign instead of parentheses for negative numbers

I built a service to read csv files of trade data from my new prime broker. The files show this format for negative numbers.
This is the code to read the file and process (only showing the part where I check for duplicate symbols since I am storing in Azure Table and cannot have duplicate symbols since the symbol is the row key)
for (var i = 0; i < records.Count - 1; i++)
{
//check if symbol is a duplicate
if (i>0 && records[i].Symbol == records[i - 1].Symbol)
{ //sum the columns in records[i] and records[i-1]
//change ent for symbol to new values
entities[i - (1 + dupeRecords)].CommissionPl = Convert.ToDouble(records[i].CommissionPl) + Convert.ToDouble(records[i - 1].CommissionPl).ToString(CultureInfo.InvariantCulture);
entities[i - (1 + dupeRecords)].PositionPl = Convert.ToDouble(records[i].PositionPl) + Convert.ToDouble(records[i - 1].PositionPl).ToString(CultureInfo.InvariantCulture);
entities[i - (1 + dupeRecords)].TransactionPl = Convert.ToDouble(records[i].TransactionPl) + Convert.ToDouble(records[i - 1].TransactionPl).ToString(CultureInfo.InvariantCulture);
entities[i - (1 + dupeRecords)].TotalPl = Convert.ToDouble(records[i].TotalPl) + Convert.ToDouble(records[i - 1].TotalPl).ToString(CultureInfo.InvariantCulture);
// do not create new ent for this record
//count the dupe entries for the entities index to match up
dupeRecords++;
}
The problem lies in the fact that these entries (i.e. records[i - 1].TotalPl, et al) when negative, despite showing -100 (for example) in the file show as (100) when you hover over them during processing. The Convert.ToDouble function can't process them when they are in parentheses format.
I can't figure out an EASY way to reformat the string value while iterating the records. I could check for parentheses and then strip them and multiply by -1 but I'm probably not seeing an easier solution.
Instead of using Convert.ToDouble, use double.Parse and specify the formats you allow:
NumberStyles styles = NumberStyles.AllowParentheses | NumberStyles.AllowTrailingSign | NumberStyles.Float | NumberStyles.AllowThousands;
entities[i - (1 + dupeRecords)].CommissionPl = double.Parse(records[i].CommissionPl, styles) ...

c# ASHX addHeader causing error

I'm working on a c# .ashx handler file and having this code:
context.Response.AddHeader("HTTP Header", "200");
context.Response.AddHeader("Content", "OK");
when this page is accessed using http protocol, it works fine but if I use https, it generates error below in chrome://net-internals/#events:
t=10983 [st=37] HTTP2_SESSION_RECV_INVALID_HEADER
--> error = "Invalid character in header name."
--> header_name = "http%20header"
--> header_value = "200"
t=10983 [st=37] HTTP2_SESSION_SEND_RST_STREAM
--> description = "Could not parse Spdy Control Frame Header."
--> error_code = "1 (PROTOCOL_ERROR)"
--> stream_id = 1
Is "HTTP Header" a safe header name? I read that "space" shouldn't be a problem in header, what's the actual issue?
So far, above happens in chrome/safari, but works fine in Firefox.
Any kind advise?
Space is not a valid character in a header name. HTTP is defined by RFC 7230.
The syntax of a header field is defined in section 3.2. Header Fields
Each header field consists of a case-insensitive field name followed
by a colon (":"), optional leading whitespace, the field value, and
optional trailing whitespace.
header-field = field-name ":" OWS field-value OWS
field-name = token
field-value = *( field-content / obs-fold )
field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-vchar = VCHAR / obs-text
obs-fold = CRLF 1*( SP / HTAB )
; obsolete line folding
; see Section 3.2.4
So the field name is a token. Tokens are defined in 3.2.6. Field Value Components
Most HTTP header field values are defined using common syntax
components (token, quoted-string, and comment) separated by
whitespace or specific delimiting characters. Delimiters are chosen
from the set of US-ASCII visual characters not allowed in a token
(DQUOTE and "(),/:;?#[\]{}").
token = 1*tchar
tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
/ "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
/ DIGIT / ALPHA
; any VCHAR, except delimiters
The last piece is in 1.2. Syntax Notation
The following core rules are included by reference, as defined in
[RFC5234], Appendix B.1: ALPHA (letters), CR (carriage return), CRLF
(CR LF), CTL (controls), DIGIT (decimal 0-9), DQUOTE (double quote),
HEXDIG (hexadecimal 0-9/A-F/a-f), HTAB (horizontal tab), LF (line
feed), OCTET (any 8-bit sequence of data), SP (space), and VCHAR (any
visible [USASCII] character).
So whitespace is not allowed in the name of a header.

IP regex mask not working in WPF

I read questions about IP mask but haven't found an answer
I'm trying to write a textbox in wpf with using regex to validate IP. This is my xaml code
This code is working
<TextBox wpfApplication2:Masking.Mask="^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"/>
I can write 192 or 255 or 29, for example
After that I want to add a dot character. And this crash my code. So I expecting that I can write
192. or 255. or 29.
I think that problem in brackets, but can't understand how to resolve it. There are my incorrect solutions:
<TextBox wpfApplication2:Masking.Mask="^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])[.]$"/>
and
<TextBox wpfApplication2:Masking.Mask="^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])[.])$"/>
I'm sure that mistake is very silly but can't find it
UPDATE
Thanks for #stribizhev, who gave explanation and answer for IP address.
Just for my aquestion: I should use {0,1} after [.]. So correct answer for my question (how to create mask for numbers 192. or 255. or 29.) is
<TextBox wpfApplication2:Masking.Mask="^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\.){0,1}$"/>
Here is the regex you can use for live validation (not for final one):
^(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])?){0,3}$
See demo
The main point when writing a regex for live validation is to make parts optional. It can be done with *, ? and {0,x} quantifiers. Here is a regex break-down:
^ - start of string
(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) - this is the first number, it is obligatory, but if you plan to let the value be empty, add a ? at the end
(?:\.(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])?){0,3} - a sequence of 0 to 3 occurrences of....
\. - a literal dot (in a verbatim string literal, the one with #"...")
(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])? - a sequence of the numbers allowed, 1 or 0 occurence (as there is ? at the end)
$ - end of string
For final validation, use
^(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])){3}$
See another demo
This regex checks the whole, final IP string.
If you want to accept any IP address as a subnet mask:
var num = #"(25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})";
var rx = new Regex("^" + num + #"\." + num + #"\." + num + #"\." + num + "$");
I considered easier to split the "repeating" match for a single group of numbers in a separate variable.
As an exercise for the reader, I'll give another variant of the expression. This one will capture all the numbers in the same group but different captures:
var rx = new Regex("^(?:" + num + #"(?:\.(?!$)|$)){4}$");
but it's wrong, you should use this
var num = #"(255|254|252|248|240|224|192|128|0+)";
var rx = new Regex("^" + num + #"\." + num + #"\." +num + #"\." +num + "$");
or
var rx = new Regex("^(?:" + num + #"(?:\.(?!$)|$)){4}$");
http://www.freesoft.org/CIE/Course/Subnet/6.htm

What's different Microsoft.JScript.GlobalObject.escape and Uri.EscapeUriString

The service received the string from Uri.EscapeUriString and Microsoft.JScript.GlobalObject.escape are difference, then I use Microsoft.JScript.GlobalObject.escape to handle url is ok.
What's different between Microsoft.JScript.GlobalObject.escape and Uri.EscapeUriString in c#?
Although Uri.EscapeUriString is available to use in C# out of the box, it can not convert all the characters exactly the same way as JavaScript escape function does.
For example let's say the original string is: "Some String's /Hello".
Uri.EscapeUriString("Some String's /Hello")
output:
"Some%20String's%20/Hello"
Microsoft.JScript.GlobalObject.escape("Some String's /Hello")
output:
"Some%20String%27s%20/Hello"
Note how the Uri.EscapeUriString did not escape the '.
That being said, lets look at a more extreme example. Suppose we have this string "& / \ # , + ( ) $ ~ % .. ' " : * ? < > { }". Lets see what escaping this with both methods give us.
Microsoft.JScript.GlobalObject.escape("& / \\ # , + ( ) $ ~ % .. ' \" : * ? < > { }")
output: "%26%20/%20%5C%20%23%20%2C%20+%20%28%20%29%20%24%20%7E%20%25%20..%20%27%20%22%20%3A%20*%20%3F%20%3C%20%3E%20%7B%20%7D"
Uri.EscapeUriString("& / \\ # , + ( ) $ ~ % .. ' \" : * ? < > { }")
output: "&%20/%20%5C%20#%20,%20+%20(%20)%20$%20~%20%25%20..%20'%20%22%20:%20*%20?%20%3C%20%3E%20%7B%20%7D"
Notice that Microsoft.JScript.GlobalObject.escape escaped all characters except +, /, * and ., even those that are valid in a uri. For example the ? and & where escaped even though they are valid in a query string.
So it all depends on where and when you wish to escape your URI and what type of URI you are creating/escaping.

Uri.EscapeDataString weirdness

Why does EscapeDataString behave differently between .NET 4 and 4.5? The outputs are
Uri.EscapeDataString("-_.!~*'()") => "-_.!~*'()"
Uri.EscapeDataString("-_.!~*'()") => "-_.%21~%2A%27%28%29"
The documentation
By default, the EscapeDataString method converts all characters except
for RFC 2396 unreserved characters to their hexadecimal
representation. If International Resource Identifiers (IRIs) or
Internationalized Domain Name (IDN) parsing is enabled, the
EscapeDataString method converts all characters, except for RFC 3986
unreserved characters, to their hexadecimal representation. All
Unicode characters are converted to UTF-8 format before being escaped.
For reference, unreserved characters are defined as follows in RFC 2396:
unreserved = alphanum | mark
mark = "-" | "_" | "." | "!" | "~" | "*" | "'" |
(" | ")"
And in RFC 3986:
ALPHA / DIGIT / "-" / "." / "_" / "~"
The source code
It looks like whether each character of EscapeDataString is escaped is determined roughly like this
is unicode above \x7F
? PERCENT ENCODE
: is a percent symbol
? is an escape char
? LEAVE ALONE
: PERCENT ENCODE
: is a forced character
? PERCENT ENCODE
: is an unreserved character
? PERCENT ENCODE
It's at that final check "is an unreserved character" where the choice between RFC2396 and RFC3986 is made. The source code of the method verbatim is
internal static unsafe bool IsUnreserved(char c)
{
if (Uri.IsAsciiLetterOrDigit(c))
{
return true;
}
if (UriParser.ShouldUseLegacyV2Quirks)
{
return (RFC2396UnreservedMarks.IndexOf(c) >= 0);
}
return (RFC3986UnreservedMarks.IndexOf(c) >= 0);
}
And that code refers to
private static readonly UriQuirksVersion s_QuirksVersion =
(BinaryCompatibility.TargetsAtLeast_Desktop_V4_5
// || BinaryCompatibility.TargetsAtLeast_Silverlight_V6
// || BinaryCompatibility.TargetsAtLeast_Phone_V8_0
) ? UriQuirksVersion.V3 : UriQuirksVersion.V2;
internal static bool ShouldUseLegacyV2Quirks {
get {
return s_QuirksVersion <= UriQuirksVersion.V2;
}
}
Confusion
It seems contradictory that the documentation says the output of EscapeDataString depends on whether IRI/IDN parsing is enabled, whereas the source code says the output is determined by the value of TargetsAtLeast_Desktop_V4_5. Could someone clear this up?
A lot of changes has been done in 4.5 comparing to 4.0 in terms of system functions and how it behaves.
U can have a look at this thread
Why does Uri.EscapeDataString return a different result on my CI server compared to my development machine?
or
U can directly go to the following link
http://msdn.microsoft.com/en-us/library/hh367887(v=vs.110).aspx
All this has been with the input from the users around the world.

Categories

Resources