Ik heb een applicatie die een POST-verzoek naar de VB-forumsoftware stuurt en iemand inlogt (zonder cookies of iets dergelijks in te stellen).
Zodra de gebruiker is ingelogd, maak ik een variabele die een pad aanmaakt op hun lokale computer.
c:\tempfolder\date\gebruikersnaam
Het probleem is dat sommige gebruikersnamen een “Illegal chars”-uitzondering genereren. Als mijn gebruikersnaam bijvoorbeeld mas|fenix
was, zou er een uitzondering optreden..
Path.Combine( _
Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), _
DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username)
Ik wil het niet uit de string verwijderen, maar er wordt een map met hun gebruikersnaam gemaakt via FTP op een server. En dit leidt tot mijn tweede vraag. Als ik een map aan het maken ben op de server, kan ik dan de “illegale tekens” erin laten? Ik vraag dit alleen omdat de server op Linux is gebaseerd, en ik weet niet zeker of Linux het accepteert of niet.
EDIT: het lijkt erop dat URL-codering NIET is wat ik wil. Dit is wat ik wil doen:
old username = mas|fenix
new username = mas%xxfenix
Waarbij %xx de ASCII-waarde is of een andere waarde die het teken gemakkelijk zou kunnen identificeren.
Antwoord 1, autoriteit 100%
Bewerken: dit antwoord is nu verouderd. Zie Siarhei Kuchuk’s antwoord hierondervoor een betere oplossing
UrlEncoding doet wat u hier voorstelt. Met C# gebruik je gewoon HttpUtility
, zoals vermeld.
Je kunt ook de illegale karakters Regexen en dan vervangen, maar dit wordt veel ingewikkelder, omdat je een of andere vorm van state machine (switch … case, bijvoorbeeld) moet hebben om te vervangen door de juiste karakters. Aangezien UrlEncode
dit van tevoren doet, is het vrij eenvoudig.
Wat Linux versus Windows betreft, zijn er enkele tekens die acceptabel zijn in Linux die niet in Windows staan, maar daar zou ik me geen zorgen over maken, omdat de mapnaam kan worden geretourneerd door de URL-tekenreeks te decoderen, met behulp van UrlDecode
, zodat u de wijzigingen kunt afronden.
Antwoord 2, autoriteit 92%
Ik heb geëxperimenteerd met de verschillende methoden die .NET biedt voor URL-codering. Misschien is de volgende tabel nuttig (als uitvoer van een test-app die ik heb geschreven):
Unencoded UrlEncoded UrlEncodedUnicode UrlPathEncoded EscapedDataString EscapedUriString HtmlEncoded HtmlAttributeEncoded HexEscaped
A A A A A A A A %41
B B B B B B B B %42
a a a a a a a a %61
b b b b b b b b %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]
De kolommen vertegenwoordigen de coderingen als volgt:
-
UrlEncoded:
HttpUtility.UrlEncode
-
UrlEncodedUnicode:
HttpUtility.UrlEncodeUnicode
-
UrlPathEncoded:
HttpUtility.UrlPathEncode
-
EscapedDataString:
Uri.EscapeDataString
-
EscapedUriString:
Uri.EscapeUriString
-
HtmlEncoded:
HttpUtility.HtmlEncode
-
HtmlAttributeEncoded:
HttpUtility.HtmlAttributeEncode
-
HexEscaped:
Uri.HexEscape
OPMERKINGEN:
-
HexEscape
kan alleen de eerste 255 tekens verwerken. Daarom genereert het eenArgumentOutOfRange
-uitzondering voor de Latijnse A-Extended-tekens (bijv. Ā). -
Deze tabel is gegenereerd in .NET 4.0 (zie de opmerking van Levi Botelho hieronder waarin staat dat de codering in .NET 4.5 iets anders is).
BEWERKEN:
Ik heb een tweede tabel toegevoegd met de coderingen voor .NET 4.5. Zie dit antwoord: https://stackoverflow.com/a/21771206/216440
BEWERK 2:
Omdat mensen deze tafels lijken te waarderen, dacht ik dat je de broncode die de tafel genereert misschien wel leuk zou vinden, zodat je zelf kunt spelen. Het is een eenvoudige C#-consoletoepassing, die zich op .NET 4.0 of 4.5 kan richten:
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<string, Func<string, string>> columnDetails =
new Dictionary<string, Func<string, string>>();
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<char, string>(charactersToEncode,
(character => character.ToString()));
DisplayCharacterTable<string>(stringCharactersToEncode, columnDetails);
}
private static void DisplayCharacterTable<TUnencoded>(TUnencoded[] unencodedArray,
Dictionary<string, Func<TUnencoded, string>> 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<TUnencoded, string> 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();
}
}
}
}
Klik hier om code uit te voeren op dotnetfiddle.net
Antwoord 3, autoriteit 92%
Je moet alleen de gebruikersnaam of een ander deel van de URL coderen dat mogelijk ongeldig is. URL-codering van een URL kan tot problemen leiden, aangezien zoiets als dit:
string url = HttpUtility.UrlEncode("http://www.google.com/search?q=Example");
Zal opleveren
http%3a%2f%2fwww.google.com%2fsearch%3fq%3dExample
Dit gaat duidelijk niet goed werken. In plaats daarvan moet u ALLEEN de waarde van het sleutel/waarde-paar in de queryreeks coderen, zoals dit:
string url = "http://www.google.com/search?q=" + HttpUtility.UrlEncode("Example");
Hopelijk helpt dat. Zoals teedyayal zei, moet je er ook voor zorgen dat het illegale bestand -naamtekens worden verwijderd, anders zal het bestandssysteem het pad niet leuk vinden.
Antwoord 4, autoriteit 92%
Betere manier is om
om niet te verwijzen naar het volledige profiel van .net 4.
Antwoord 5, autoriteit 94%
Sinds .NET Framework 4.5en .NET Standard 1.0moet u WebUtility.UrlEncode
. Voordelen ten opzichte van alternatieven:
-
Het maakt deel uit van .NET Framework 4.5+, .NET Core 1.0+, .NET Standard 1.0+, UWP 10.0+ en ook van alle Xamarin-platforms.
HttpUtility
, hoewel het eerder beschikbaar was in .NET Framework (.NET Framework 1.1+), wordt het veel later beschikbaar op andere platforms (.NET Core 2.0+, .NET Standard 2.0+) en is het nog steeds niet beschikbaar in UWP (zie gerelateerde vraag). -
In .NET Framework bevindt het zich in
System.dll
, dus het vereist geen aanvullende verwijzingen, in tegenstelling totHttpUtility
. -
Het ontsnapt correct tekens voor URL’s, in tegenstelling tot
Uri.EscapeUriString
(zie commentaar op het antwoord van drweb86). -
Het heeft geen limiet voor de lengte van de string, in tegenstelling tot
Uri.EscapeDataString
(zie gerelateerde vraag), zodat het bijvoorbeeld kan worden gebruikt voor POST-verzoeken.
Antwoord 6, autoriteit 45%
Levi Botelho merkte op dat de tabel met coderingen die eerder werd gegenereerd niet langer nauwkeurig is voor .NET 4.5, aangezien de coderingen tussen .NET 4.0 en 4.5 enigszins zijn gewijzigd. Dus ik heb de tabel opnieuw gegenereerd voor .NET 4.5:
Unencoded UrlEncoded UrlEncodedUnicode UrlPathEncoded WebUtilityUrlEncoded EscapedDataString EscapedUriString HtmlEncoded HtmlAttributeEncoded WebUtilityHtmlEncoded HexEscaped
A A A A A A A A A A %41
B B B B B B B B B B %42
a a a a a a a a a a %61
b b b b b b b b b b %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]
De kolommen vertegenwoordigen de coderingen als volgt:
- 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
OPMERKINGEN:
-
HexEscape kan alleen de eerste 255 tekens aan. Daarom genereert het een ArgumentOutOfRange-uitzondering voor de Latijnse A-Extended-tekens (bijv. Ā).
-
Deze tabel is gegenereerd in .NET 4.5 (zie antwoord https://stackoverflow.com/a/11236038/216440 voor de coderingen die relevant zijn voor .NET 4.0 en lager).
BEWERKEN:
- Als gevolg van het antwoord van Discord heb ik de nieuwe WebUtility UrlEncode- en HtmlEncode-methoden toegevoegd, die in .NET 4.5 zijn geïntroduceerd.
Antwoord 7, autoriteit 31%
Url-codering is eenvoudig in .NET. Gebruik:
System.Web.HttpUtility.UrlEncode(string url)
Als dat wordt gedecodeerd om de mapnaam te krijgen, moet je nog steeds tekens uitsluiten die niet in mapnamen kunnen worden gebruikt (*, ?, /, enz.)
Antwoord 8, autoriteit 6%
Als u System.Web niet kunt zien, wijzigt u uw projectinstellingen. Het doelframework moet “.NET Framework 4” zijn in plaats van “.NET Framework 4 Client Profile”
Antwoord 9, autoriteit 4%
De .NET-implementatie van UrlEncode
voldoet niet aan RFC 3986.
-
Sommige tekens zijn niet gecodeerd, maar zouden dat wel moeten zijn. De tekens
!()*
worden in sectie 2.2 van de RFC vermeld als gereserveerde tekens die moeten worden gecodeerd, maar .NET kan deze tekens niet coderen. -
Sommige tekens zijn gecodeerd, maar zouden dat niet moeten zijn. De tekens
.-_
worden niet vermeld in sectie 2.2 van de RFC als een gereserveerd teken dat nog niet mag worden gecodeerd. NET codeert deze tekens ten onrechte. -
De RFC specificeert dat implementaties, om consistent te zijn, HEXDIG in hoofdletters moeten gebruiken, waarbij .NET HEXDIG in kleine letters produceert.
Antwoord 10, autoriteit 2%
Ik denk dat de mensen hier op een zijspoor zijn geraakt door het UrlEncode-bericht. URLEncoding is nietwat je wilt — je wilt dingen coderen die niet werken als bestandsnaam op het doelsysteem.
Ervan uitgaande dat je enige algemeenheid wilt — voel je vrij om de illegale tekens op verschillende systemen (MacOS, Windows, Linux en Unix) te vinden, voeg ze samen om een set tekens te vormen om te ontsnappen.
Wat betreft de ontsnapping, een HexEscape zou in orde moeten zijn (de tekens vervangen door %XX). Converteer elk teken naar UTF-8 bytes en codeer alles >128 als u systemen wilt ondersteunen die geen unicode gebruiken. Maar er zijn andere manieren, zoals het gebruik van backslashes “\” of HTML-codering “””. U kunt uw eigen maken. Het enige wat elk systeem hoeft te doen is het niet-compatibele teken weg te ‘coderen’. Met de bovenstaande systemen kunt u de oorspronkelijke naam — maar zoiets als het vervangen van de slechte tekens door spaties werkt ook.
Op dezelfde raaklijn als hierboven, is de enige te gebruiken
Uri.EscapeDataString
— Het codeert alles wat nodig is voor OAuth, het codeert niet de dingen die OAuth codering verbiedt, en codeert de spatie als %20 en niet + (Ook in de OATH-specificatie) Zie: RFC 3986. AFAIK, dit is de nieuwste URI-specificatie.
Antwoord 11, autoriteit 2%
Ik heb een C#-methode geschreven die ALLE symbolen url-codeert:
/// <summary>
/// !#$345Hf} → %21%23%24%33%34%35%48%66%7D
/// </summary>
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();
}
Antwoord 12
Idealiter zouden deze in een klasse met de naam “FileNaming” gaan of misschien gewoon Encode hernoemen naar “FileNameEncode”. Opmerking: deze zijn niet ontworpen om volledige paden te verwerken, alleen de map- en/of bestandsnamen. Idealiter zou u eerst uw volledige pad splitsen (“/”) en vervolgens de stukken controleren.
En natuurlijk zou je in plaats van een unie, gewoon het “%”-teken kunnen toevoegen aan de lijst met tekens die niet zijn toegestaan in Windows, maar ik denk dat het op deze manier nuttiger/leesbaarder/feitelijker is.
Decode() is precies hetzelfde, maar verwisselt de Replace(Uri.HexEscape(s[0]), s) “escaped” met het karakter.
public static List<string> urlEncodedCharacters = new List<string>
{
"/", "\\", "<", ">", ":", "\"", "|", "?", "%" //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<string> specialCharactersNotAllowedInWindows = new List<string>
{
"/", "\\", "<", ">", ":", "\"", "|", "?", "*" //windows dissallowed character set
};
public static string Encode(string fileName)
{
//CheckForFullPath(fileName); // optional: make sure it's not a path?
List<string> charactersToChange = new List<string>(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;
}
Bedankt @ Simon-Tewsi voor de zeer nuttige tabel hierboven!
Antwoord 13
Naast het antwoord van @dan Herbert,
Jij we moeten alleen de waarden coderen.
Split heeft paramets parameter split (‘& amp;’, ‘=’); expressie eerst verdeeld over & amp; Dan ‘=’ is oneven elementen alle waarden die hieronder worden gecodeerd.
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);
}
}
}