Codificación de URL usando C #

Tengo una aplicación que envía una solicitud POST al software del foro de VB y registra a alguien (sin configurar cookies ni nada).

Una vez que el usuario inicia sesión, creo una variable que crea una ruta en su máquina local.

c: \ tempfolder \ date \ username

El problema es que algunos nombres de usuario arrojan una excepción de “Caracteres ilegales”. Por ejemplo, si mi nombre de usuario era mas|fenix arrojaría una excepción …

 Path.Combine( _ Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), _ DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username) 

No quiero eliminarlo de la cadena, pero una carpeta con su nombre de usuario se crea a través de FTP en un servidor. Y esto lleva a mi segunda pregunta. Si estoy creando una carpeta en el servidor, ¿puedo dejar los “caracteres ilegales” en? Solo pregunto esto porque el servidor está basado en Linux, y no estoy seguro si Linux lo acepta o no.

EDITAR: Parece que la encoding de URL NO es lo que quiero … Esto es lo que quiero hacer:

 old username = mas|fenix new username = mas%xxfenix 

Donde% xx es el valor ASCII o cualquier otro valor que identifique fácilmente el personaje.

Editar: Tenga en cuenta que esta respuesta ahora está desactualizada. Vea la respuesta de Siarhei Kuchuk a continuación para una mejor solución

UrlEncoding hará lo que está sugiriendo aquí. Con C #, simplemente usa HttpUtility , como se mencionó.

También puede Regexar los caracteres ilegales y luego reemplazarlos, pero esto se vuelve mucho más complejo, ya que tendrá que tener alguna forma de máquina de estado (cambiar … caso, por ejemplo) para reemplazar con los caracteres correctos. Dado que UrlEncode hace por adelantado, es bastante fácil.

En cuanto a Linux frente a Windows, hay algunos caracteres aceptables en Linux que no están en Windows, pero no me preocuparía, ya que el nombre de la carpeta puede devolverse decodificando la cadena Url, usando UrlDecode , para que pueda hacer un viaje de ida y vuelta los cambios.

He estado experimentando con los diversos métodos .NET proporciona encoding de URL. Tal vez la siguiente tabla sea útil (como resultado de una aplicación de prueba que escribí):

 Unencoded UrlEncoded UrlEncodedUnicode UrlPathEncoded EscapedDataString EscapedUriString HtmlEncoded HtmlAttributeEncoded HexEscaped AAAAAAAA %41 BBBBBBBB %42 aaaaaaaa %61 bbbbbbbb %62 0 0 0 0 0 0 0 0 %30 1 1 1 1 1 1 1 1 %31 [space] + + %20 %20 %20 [space] [space] %20 ! ! ! ! ! ! ! ! %21 " %22 %22 " %22 %22 " " %22 # %23 %23 # %23 # # # %23 $ %24 %24 $ %24 $ $ $ %24 % %25 %25 % %25 %25 % % %25 & %26 %26 & %26 & & & %26 ' %27 %27 ' ' ' ' ' %27 ( ( ( ( ( ( ( ( %28 ) ) ) ) ) ) ) ) %29 * * * * %2A * * * %2A + %2b %2b + %2B + + + %2B , %2c %2c , %2C , , , %2C - - - - - - - - %2D . . . . . . . . %2E / %2f %2f / %2F / / / %2F : %3a %3a : %3A : : : %3A ; %3b %3b ; %3B ; ; ; %3B < %3c %3c < %3C %3C < < %3C = %3d %3d = %3D = = = %3D > %3e %3e > %3E %3E > > %3E ? %3f %3f ? %3F ? ? ? %3F @ %40 %40 @ %40 @ @ @ %40 [ %5b %5b [ %5B %5B [ [ %5B \ %5c %5c \ %5C %5C \ \ %5C ] %5d %5d ] %5D %5D ] ] %5D ^ %5e %5e ^ %5E %5E ^ ^ %5E _ _ _ _ _ _ _ _ %5F ` %60 %60 ` %60 %60 ` ` %60 { %7b %7b { %7B %7B { { %7B | %7c %7c | %7C %7C | | %7C } %7d %7d } %7D %7D } } %7D ~ %7e %7e ~ ~ ~ ~ ~ %7E Ā %c4%80 %u0100 %c4%80 %C4%80 %C4%80 Ā Ā [OoR] ā %c4%81 %u0101 %c4%81 %C4%81 %C4%81 ā ā [OoR] Ē %c4%92 %u0112 %c4%92 %C4%92 %C4%92 Ē Ē [OoR] ē %c4%93 %u0113 %c4%93 %C4%93 %C4%93 ē ē [OoR] Ī %c4%aa %u012a %c4%aa %C4%AA %C4%AA Ī Ī [OoR] ī %c4%ab %u012b %c4%ab %C4%AB %C4%AB ī ī [OoR] Ō %c5%8c %u014c %c5%8c %C5%8C %C5%8C Ō Ō [OoR] ō %c5%8d %u014d %c5%8d %C5%8D %C5%8D ō ō [OoR] Ū %c5%aa %u016a %c5%aa %C5%AA %C5%AA Ū Ū [OoR] ū %c5%ab %u016b %c5%ab %C5%AB %C5%AB ū ū [OoR] 

Las columnas representan codificaciones de la siguiente manera:

  • UrlEncoded: HttpUtility.UrlEncode

  • UrlEncodedUnicode: HttpUtility.UrlEncodeUnicode

  • UrlPathEncoded: HttpUtility.UrlPathEncode

  • EscapedDataString: Uri.EscapeDataString

  • EscapedUriString: Uri.EscapeUriString

  • HtmlEncoded: HttpUtility.HtmlEncode

  • HtmlAttributeEncoded: HttpUtility.HtmlAttributeEncode

  • HexEscaped: Uri.HexEscape

NOTAS:

  1. HexEscape solo puede manejar los primeros 255 caracteres. Por lo tanto, arroja una excepción ArgumentOutOfRange para los caracteres Latin A-Extended (por ejemplo, Ā).

  2. Esta tabla se generó en .NET 4.0 (ver el comentario de Levi Botelho a continuación que dice que la encoding en .NET 4.5 es ligeramente diferente).

EDITAR:

He agregado una segunda tabla con las codificaciones para .NET 4.5. Ver esta respuesta: https://stackoverflow.com/a/21771206/216440

EDICION 2:

Dado que la gente parece apreciar estas tablas, pensé que le gustaría el código fuente que genera la tabla, para que pueda jugar con ustedes mismos. Es una aplicación simple de consola C #, que puede apuntar a .NET 4.0 o 4.5:

 using System; using System.Collections.Generic; using System.Text; // Need to add a Reference to the System.Web assembly. using System.Web; namespace UriEncodingDEMO2 { class Program { static void Main(string[] args) { EncodeStrings(); Console.WriteLine(); Console.WriteLine("Press any key to continue..."); Console.Read(); } public static void EncodeStrings() { string stringToEncode = "ABCD" + "abcd" + "0123" + " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" + "ĀāĒēĪīŌōŪū"; // Need to set the console encoding to display non-ASCII characters correctly (eg the // Latin A-Extended characters such as ĀāĒē...). Console.OutputEncoding = Encoding.UTF8; // Will also need to set the console font (in the console Properties dialog) to a font // that displays the extended character set correctly. // The following fonts all display the extended characters correctly: // Consolas // DejaVu Sana Mono // Lucida Console // Also, in the console Properties, set the Screen Buffer Size and the Window Size // Width properties to at least 140 characters, to display the full width of the // table that is generated. Dictionary> columnDetails = new Dictionary>(); columnDetails.Add("Unencoded", (unencodedString => unencodedString)); columnDetails.Add("UrlEncoded", (unencodedString => HttpUtility.UrlEncode(unencodedString))); columnDetails.Add("UrlEncodedUnicode", (unencodedString => HttpUtility.UrlEncodeUnicode(unencodedString))); columnDetails.Add("UrlPathEncoded", (unencodedString => HttpUtility.UrlPathEncode(unencodedString))); columnDetails.Add("EscapedDataString", (unencodedString => Uri.EscapeDataString(unencodedString))); columnDetails.Add("EscapedUriString", (unencodedString => Uri.EscapeUriString(unencodedString))); columnDetails.Add("HtmlEncoded", (unencodedString => HttpUtility.HtmlEncode(unencodedString))); columnDetails.Add("HtmlAttributeEncoded", (unencodedString => HttpUtility.HtmlAttributeEncode(unencodedString))); columnDetails.Add("HexEscaped", (unencodedString => { // Uri.HexEscape can only handle the first 255 characters so for the // Latin A-Extended characters, such as A, it will throw an // ArgumentOutOfRange exception. try { return Uri.HexEscape(unencodedString.ToCharArray()[0]); } catch { return "[OoR]"; } })); char[] charactersToEncode = stringToEncode.ToCharArray(); string[] stringCharactersToEncode = Array.ConvertAll(charactersToEncode, (character => character.ToString())); DisplayCharacterTable(stringCharactersToEncode, columnDetails); } private static void DisplayCharacterTable(TUnencoded[] unencodedArray, Dictionary> mappings) { foreach (string key in mappings.Keys) { Console.Write(key.Replace(" ", "[space]") + " "); } Console.WriteLine(); foreach (TUnencoded unencodedObject in unencodedArray) { string stringCharToEncode = unencodedObject.ToString(); foreach (string columnHeader in mappings.Keys) { int columnWidth = columnHeader.Length + 1; Func encoder = mappings[columnHeader]; string encodedString = encoder(unencodedObject); // ASSUMPTION: Column header will always be wider than encoded string. Console.Write(encodedString.Replace(" ", "[space]").PadRight(columnWidth)); } Console.WriteLine(); } } } } 

Debe codificar solo el nombre de usuario u otra parte de la URL que podría no ser válida. La URL que codifica una URL puede generar problemas ya que algo como esto:

 string url = HttpUtility.UrlEncode("http://www.google.com/search?q=Example"); 

Rendirá

http% 3a% 2f% 2fwww.google.com% 2fsearch% 3fq% 3dExample

Esto obviamente no va a funcionar bien. En su lugar, debe codificar SÓLO el valor del par de clave / valor en la cadena de consulta, como este:

 string url = "http://www.google.com/search?q=" + HttpUtility.UrlEncode("Example"); 

Espero que eso ayude. Además, como mencionó Teedyay , aún deberá asegurarse de que se eliminen los caracteres ilegales de nombre de archivo o de lo contrario al sistema de archivos no le gustará la ruta.

Desde .NET Framework 4.5 puede usar WebUtility.UrlEncode .

En primer lugar, reside en System.dll , por lo que no requiere ninguna referencia adicional.

En segundo lugar, escapa correctamente de los caracteres de las URL , a diferencia de Uri.EscapeUriString (ver comentarios a la respuesta de drweb86).

En tercer lugar, no tiene ningún límite en la longitud de la cadena , a diferencia de Uri.EscapeDataString (ver pregunta relacionada ), por lo que se puede usar para solicitudes POST, por ejemplo.

En cuarto lugar, está disponible en WinRT , a diferencia de HttpUtility (ver pregunta relacionada ).

Mejor forma es usar

 Uri.EscapeUriString 

para no hacer referencia al perfil completo de .net 4.

Levi Botelho comentó que la tabla de codificaciones que se generó previamente ya no es precisa para .NET 4.5, ya que las codificaciones cambiaron ligeramente entre .NET 4.0 y 4.5. Así que he regenerado la tabla para .NET 4.5:

 Unencoded UrlEncoded UrlEncodedUnicode UrlPathEncoded WebUtilityUrlEncoded EscapedDataString EscapedUriString HtmlEncoded HtmlAttributeEncoded WebUtilityHtmlEncoded HexEscaped AAAAAAAAAA %41 BBBBBBBBBB %42 aaaaaaaaaa %61 bbbbbbbbbb %62 0 0 0 0 0 0 0 0 0 0 %30 1 1 1 1 1 1 1 1 1 1 %31 [space] + + %20 + %20 %20 [space] [space] [space] %20 ! ! ! ! ! %21 ! ! ! ! %21 " %22 %22 " %22 %22 %22 " " " %22 # %23 %23 # %23 %23 # # # # %23 $ %24 %24 $ %24 %24 $ $ $ $ %24 % %25 %25 % %25 %25 %25 % % % %25 & %26 %26 & %26 %26 & & & & %26 ' %27 %27 ' %27 %27 ' ' ' ' %27 ( ( ( ( ( %28 ( ( ( ( %28 ) ) ) ) ) %29 ) ) ) ) %29 * * * * * %2A * * * * %2A + %2b %2b + %2B %2B + + + + %2B , %2c %2c , %2C %2C , , , , %2C - - - - - - - - - - %2D . . . . . . . . . . %2E / %2f %2f / %2F %2F / / / / %2F : %3a %3a : %3A %3A : : : : %3A ; %3b %3b ; %3B %3B ; ; ; ; %3B < %3c %3c < %3C %3C %3C < < < %3C = %3d %3d = %3D %3D = = = = %3D > %3e %3e > %3E %3E %3E > > > %3E ? %3f %3f ? %3F %3F ? ? ? ? %3F @ %40 %40 @ %40 %40 @ @ @ @ %40 [ %5b %5b [ %5B %5B [ [ [ [ %5B \ %5c %5c \ %5C %5C %5C \ \ \ %5C ] %5d %5d ] %5D %5D ] ] ] ] %5D ^ %5e %5e ^ %5E %5E %5E ^ ^ ^ %5E _ _ _ _ _ _ _ _ _ _ %5F ` %60 %60 ` %60 %60 %60 ` ` ` %60 { %7b %7b { %7B %7B %7B { { { %7B | %7c %7c | %7C %7C %7C | | | %7C } %7d %7d } %7D %7D %7D } } } %7D ~ %7e %7e ~ %7E ~ ~ ~ ~ ~ %7E Ā %c4%80 %u0100 %c4%80 %C4%80 %C4%80 %C4%80 Ā Ā Ā [OoR] ā %c4%81 %u0101 %c4%81 %C4%81 %C4%81 %C4%81 ā ā ā [OoR] Ē %c4%92 %u0112 %c4%92 %C4%92 %C4%92 %C4%92 Ē Ē Ē [OoR] ē %c4%93 %u0113 %c4%93 %C4%93 %C4%93 %C4%93 ē ē ē [OoR] Ī %c4%aa %u012a %c4%aa %C4%AA %C4%AA %C4%AA Ī Ī Ī [OoR] ī %c4%ab %u012b %c4%ab %C4%AB %C4%AB %C4%AB ī ī ī [OoR] Ō %c5%8c %u014c %c5%8c %C5%8C %C5%8C %C5%8C Ō Ō Ō [OoR] ō %c5%8d %u014d %c5%8d %C5%8D %C5%8D %C5%8D ō ō ō [OoR] Ū %c5%aa %u016a %c5%aa %C5%AA %C5%AA %C5%AA Ū Ū Ū [OoR] ū %c5%ab %u016b %c5%ab %C5%AB %C5%AB %C5%AB ū ū ū [OoR] 

Las columnas representan codificaciones de la siguiente manera:

  • UrlEncoded: HttpUtility.UrlEncode
  • UrlEncodedUnicode: HttpUtility.UrlEncodeUnicode
  • UrlPathEncoded: HttpUtility.UrlPathEncode
  • WebUtilityUrlEncoded: WebUtility.UrlEncode
  • EscapedDataString: Uri.EscapeDataString
  • EscapedUriString: Uri.EscapeUriString
  • HtmlEncoded: HttpUtility.HtmlEncode
  • HtmlAttributeEncoded: HttpUtility.HtmlAttributeEncode
  • WebUtilityHtmlEncoded: WebUtility.HtmlEncode
  • HexEscaped: Uri.HexEscape

NOTAS:

  1. HexEscape solo puede manejar los primeros 255 caracteres. Por lo tanto, arroja una excepción ArgumentOutOfRange para los caracteres Latin A-Extended (por ejemplo, Ā).

  2. Esta tabla se generó en .NET 4.5 (ver respuesta https://stackoverflow.com/a/11236038/216440 para las codificaciones relevantes para .NET 4.0 y versiones posteriores).

EDITAR:

  1. Como resultado de la respuesta de Discord, agregué los nuevos métodos WebUtility UrlEncode y HtmlEncode, que se introdujeron en .NET 4.5.

La encoding de URL es fácil en .NET. Utilizar:

 System.Web.HttpUtility.UrlEncode(string url) 

Si eso se decodificará para obtener el nombre de la carpeta, igual deberá excluir los caracteres que no se pueden usar en los nombres de las carpetas (*,?, /, Etc.)

Si no puede ver System.Web, cambie la configuración de su proyecto. El marco de destino debe ser “.NET Framework 4” en lugar de “.NET Framework 4 Client Profile”

La implementación .NET de UrlEncode no cumple con RFC 3986.

  1. Algunos caracteres no están codificados, pero deberían serlo. Los caracteres !()* Se enumeran en la sección 2.2 del RFC como caracteres reservados que deben codificarse aún .NET no codifica estos caracteres.

  2. Algunos caracteres están codificados, pero no deberían serlo. Los caracteres .-_ No están listados en la sección 2.2 del RFC como un carácter reservado que no debe codificarse aún .NET codifica erróneamente estos caracteres.

  3. El RFC especifica que para ser consistentes, las implementaciones deben usar HEXDIG en mayúsculas, donde .NET produce HEXDIG en minúsculas.

Idealmente, estos entrarían en una clase llamada “FileNaming” o tal vez simplemente cambiar el nombre de Encode a “FileNameEncode”. Nota: estos no están diseñados para manejar rutas completas, solo la carpeta y / o los nombres de archivo. Lo ideal sería dividir (“/”) su ruta completa primero y luego verificar las piezas. Y, obviamente, en lugar de una unión, podría agregar el carácter “%” a la lista de caracteres no permitidos en Windows, pero creo que es más útil / legible / factual de esta manera. Decode () es exactamente igual, pero cambia el Reemplazo (Uri.HexEscape (s [0]), s) “escapado” con el carácter.

 public static List urlEncodedCharacters = new List { "/", "\\", "<", ">", ":", "\"", "|", "?", "%" //and others, but not * }; //Since this is a superset of urlEncodedCharacters, we won't be able to only use UrlEncode() - instead we'll use HexEncode public static List specialCharactersNotAllowedInWindows = new List { "/", "\\", "<", ">", ":", "\"", "|", "?", "*" //windows dissallowed character set }; public static string Encode(string fileName) { //CheckForFullPath(fileName); // optional: make sure it's not a path? List charactersToChange = new List(specialCharactersNotAllowedInWindows); charactersToChange.AddRange(urlEncodedCharacters. Where(x => !urlEncodedCharacters.Union(specialCharactersNotAllowedInWindows).Contains(x))); // add any non duplicates (%) charactersToChange.ForEach(s => fileName = fileName.Replace(s, Uri.HexEscape(s[0]))); // "?" => "%3f" return fileName; } 

Gracias @ simon-tewsi por la muy útil tabla de arriba!

He escrito un método de C # que codifica en URL TODOS los símbolos:

  ///  /// !#$345Hf} → %21%23%24%33%34%35%48%66%7D ///  public static string UrlEncodeExtended( string value ) { char[] chars = value.ToCharArray(); StringBuilder encodedValue = new StringBuilder(); foreach (char c in chars) { encodedValue.Append( "%" + ( (int)c ).ToString( "X2" ) ); } return encodedValue.ToString(); } 

Además de la respuesta de @Dan Herbert, usted debería codificar solo los valores en general.

Split tiene el parámetro params Split (‘&’, ‘=’); expresión primero dividida por & then ‘=’ por lo que los elementos impares son todos los valores a codificar que se muestran a continuación.

 public static void EncodeQueryString(ref string queryString) { var array=queryString.Split('&','='); for (int i = 0; i < array.Length; i++) { string part=array[i]; if(i%2==1) { part=System.Web.HttpUtility.UrlEncode(array[i]); queryString=queryString.Replace(array[i],part); } } }