Codifica degli URL usando C #

Ho un’applicazione che invia una richiesta POST al software del forum VB e registra qualcuno in (senza impostare cookie o altro).

Una volta effettuato l’accesso, l’utente crea una variabile che crea un percorso sul proprio computer locale.

c: \ TempFolder \ Data \ nomeutente

Il problema è che alcuni nomi utente generano un’eccezione “Illegal chars”. Ad esempio se il mio nome utente fosse mas|fenix genererebbe un’eccezione ..

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

Non voglio rimuoverlo dalla stringa, ma una cartella con il loro nome utente viene creata tramite FTP su un server. E questo porta alla mia seconda domanda. Se sto creando una cartella sul server posso lasciare “caratteri illegali”? Lo chiedo solo perché il server è basato su Linux e non sono sicuro che Linux lo accetti o no.

EDIT: Sembra che la codifica dell’URL NON sia quello che voglio .. Ecco cosa voglio fare:

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

Dove% xx è il valore ASCII o qualsiasi altro valore che possa identificare facilmente il carattere.

Modifica: nota che questa risposta non è aggiornata. Vedi la risposta di Siarhei Kuchuk sotto per una soluzione migliore

UrlEncoding farà ciò che stai suggerendo qui. Con C #, si usa semplicemente HttpUtility , come detto.

È inoltre ansible sostituire i caratteri non validi e quindi sostituirli, ma questo diventa molto più complesso, poiché sarà necessario disporre di una qualche forma di macchina di stato (caso … switch, ad esempio) da sostituire con i caratteri corretti. Dal momento che UrlEncode fa questo in anticipo, è piuttosto facile.

Per quanto riguarda Linux contro Windows, ci sono alcuni caratteri che sono accettabili in Linux che non sono in Windows, ma non mi preoccuperei di questo, dato che il nome della cartella può essere restituito decodificando la stringa Url, usando UrlDecode , così puoi UrlDecode giro i cambiamenti.

Ho sperimentato i vari metodi .NET per la codifica degli URL. Forse la seguente tabella sarà utile (come output da una app di test che ho scritto):

 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] 

Le colonne rappresentano le codifiche come segue:

  • UrlEncoded: HttpUtility.UrlEncode

  • UrlEncodedUnicode: HttpUtility.UrlEncodeUnicode

  • UrlPathEncoded: HttpUtility.UrlPathEncode

  • EscapedDataString: Uri.EscapeDataString

  • EscapedUriString: Uri.EscapeUriString

  • HtmlEncoded: HttpUtility.HtmlEncode

  • HtmlAttributeEncoded: HttpUtility.HtmlAttributeEncode

  • HexEscaped: Uri.HexEscape

GLI APPUNTI:

  1. HexEscape può gestire solo i primi 255 caratteri. Pertanto genera un’eccezione ArgumentOutOfRange per i caratteri latini A-Extended (es. À).

  2. Questa tabella è stata generata in .NET 4.0 (vedi il commento di Levi Botelho qui sotto che dice che la codifica in .NET 4.5 è leggermente diversa).

MODIFICARE:

Ho aggiunto una seconda tabella con le codifiche per .NET 4.5. Vedi questa risposta: https://stackoverflow.com/a/21771206/216440

MODIFICA 2:

Dal momento che la gente sembra apprezzare queste tabelle, ho pensato che ti sarebbe piaciuto il codice sorgente che genera il tavolo, così puoi giocare da solo. È una semplice applicazione di console C #, che può scegliere come target .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(); } } } } 

Dovresti codificare solo il nome utente o altra parte dell’URL che potrebbe non essere valido. La codifica URL di un URL può causare problemi in seguito a qualcosa di simile:

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

Cederà

http% 3A% 2F% 2fwww.google.com% 2fsearch% 3fq% 3dExample

Questo ovviamente non funzionerà bene. Invece, dovresti codificare SOLO il valore della coppia chiave / valore nella stringa di query, in questo modo:

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

Speriamo che questo aiuti. Inoltre, come già accennato, dovrai comunque assicurarti che i caratteri dei nomi di file illegali vengano rimossi, altrimenti il ​​file system non gradirà il percorso.

Dal momento che .NET Framework 4.5 è ansible utilizzare WebUtility.UrlEncode .

Innanzitutto, risiede in System.dll , quindi non richiede alcun riferimento aggiuntivo.

In secondo luogo, fugge correttamente i caratteri per gli URL , diversamente da Uri.EscapeUriString (vedere i commenti alla risposta di drweb86).

In terzo luogo, non ha alcun limite sulla lunghezza della stringa , diversamente da Uri.EscapeDataString (vedi domanda correlata ), quindi può essere usato per le richieste POST, per esempio.

In quarto luogo, è disponibile su WinRT , diversamente da HttpUtility (vedi domanda correlata ).

Il modo migliore è usare

 Uri.EscapeUriString 

non fare riferimento al profilo completo di .net 4.

Levi Botelho ha commentato che la tabella delle codifiche precedentemente generata non è più accurata per .NET 4.5, poiché le codifiche sono leggermente cambiate tra .NET 4.0 e 4.5. Quindi ho rigenerato la tabella per .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] 

Le colonne rappresentano le codifiche come segue:

  • 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

GLI APPUNTI:

  1. HexEscape può gestire solo i primi 255 caratteri. Pertanto genera un’eccezione ArgumentOutOfRange per i caratteri latini A-Extended (es. À).

  2. Questa tabella è stata generata in .NET 4.5 (vedere answer https://stackoverflow.com/a/11236038/216440 per le codifiche rilevanti per .NET 4.0 e versioni precedenti).

MODIFICARE:

  1. Come risultato della risposta di Discord, ho aggiunto i nuovi metodi WebUtility UrlEncode e HtmlEncode, introdotti in .NET 4.5.

La codifica dell’URL è semplice in .NET. Uso:

 System.Web.HttpUtility.UrlEncode(string url) 

Se questo verrà decodificato per ottenere il nome della cartella, sarà comunque necessario escludere i caratteri che non possono essere utilizzati nei nomi delle cartelle (*,?, /, Ecc.)

Se non riesci a vedere System.Web, modifica le impostazioni del progetto. Il framework di destinazione dovrebbe essere “.NET Framework 4” anziché “.NET Framework 4 Client Profile”

L’implementazione .NET di UrlEncode non è conforms a RFC 3986.

  1. Alcuni personaggi non sono codificati ma dovrebbero essere. I caratteri !()* Sono elencati nella sezione 2.2 della RFC come caratteri riservati che devono essere codificati, ma .NET non riesce a codificare questi caratteri.

  2. Alcuni caratteri sono codificati ma non dovrebbero esserlo. I caratteri .-_ Non sono elencati nella sezione 2.2 della RFC come un carattere riservato che non dovrebbe essere codificato. NET codifica erroneamente questi caratteri.

  3. La RFC specifica che per essere coerenti, le implementazioni devono utilizzare HEXDIG maiuscolo, dove .NET produce HEXDIG in lettere minuscole.

Idealmente questi andrebbero in una class chiamata “FileNaming” o potrebbero semplicemente rinominare Encode in “FileNameEncode”. Nota: questi non sono progettati per gestire percorsi completi, solo la cartella e / oi nomi dei file. Idealmente dovresti prima dividere (“/”) il tuo percorso completo e poi controllare i pezzi. E ovviamente al posto di un sindacato, potresti semplicemente aggiungere il carattere “%” alla lista di caratteri non consentiti in Windows, ma penso che sia più utile / leggibile / fattuale in questo modo. Decode () è esattamente lo stesso, ma sostituisce la sostituzione (Uri.HexEscape (s [0]), s) “escape” con il carattere.

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

Grazie @ simon-tewsi per la tabella molto utile in alto!

Ho scritto un metodo C # che url-codifica TUTTI i simboli:

  ///  /// !#$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(); } 

Oltre alla risposta di @ Dan Herbert, dovremmo codificare solo i valori in generale.

Split ha parametri param Split (‘&’, ‘=’); espressione in primo luogo divisa per & then ‘=’ quindi gli elementi dispari sono tutti i valori da codificare mostrati di seguito.

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