Mam aplikację, która wysyła żądanie POST do oprogramowania forum VB i loguje kogoś (bez ustawiania plików cookie lub czegokolwiek).
Po zalogowaniu się użytkownika tworzę zmienną, która tworzy ścieżkę na ich komputerze lokalnym.
c: \ tempfolder \ date \ nazwa użytkownika
Problem polega na tym, że niektóre nazwy użytkowników zgłaszają wyjątek „Nielegalne znaki”. Na przykład, jeśli moja nazwa użytkownika mas|fenix
to zgłasza wyjątek.
Path.Combine( _
Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), _
DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username)
Nie chcę go usuwać z ciągu, ale folder z nazwą użytkownika jest tworzony za pośrednictwem FTP na serwerze. To prowadzi do mojego drugiego pytania. Jeśli tworzę folder na serwerze, czy mogę pozostawić „nielegalne znaki” w? Pytam tylko o to, ponieważ serwer jest oparty na systemie Linux i nie jestem pewien, czy Linux to akceptuje, czy nie.
EDYCJA: Wygląda na to, że kodowanie adresu URL NIE jest tym, czego chcę. Oto, co chcę zrobić:
old username = mas|fenix
new username = mas%xxfenix
Gdzie% xx to wartość ASCII lub dowolna inna wartość, która łatwo identyfikowałaby znak.
Odpowiedzi:
Edycja: pamiętaj, że ta odpowiedź jest nieaktualna. Zobacz odpowiedź Siarhiej Kuchuk jest poniżej dla lepszego fix
UrlEncoding zrobi to, co tutaj sugerujesz. Z C # po prostu używasz
HttpUtility
, jak wspomniano.Możesz także ponownie Zexeksować niedozwolone znaki, a następnie zamienić, ale staje się to o wiele bardziej skomplikowane, ponieważ będziesz musiał mieć jakąś formę automatu stanów (na przykład zmień ... obudowę), aby zastąpić prawidłowymi znakami. Ponieważ
UrlEncode
robi to z góry, jest to raczej łatwe.Jeśli chodzi o Linux kontra Windows, niektóre znaki są akceptowane w Linuksie, ale nie są w systemie Windows, ale nie martwiłbym się tym, ponieważ nazwę folderu można zwrócić, dekodując ciąg adresu URL, używając
UrlDecode
, aby można było przejść w obie strony zmiany.źródło
A potentially dangerous Request.Path value was detected from the client
.Eksperymentowałem z różnymi metodami .NET zapewniającymi kodowanie adresów URL. Być może przydatna będzie poniższa tabela (jako wynik z aplikacji testowej, którą napisałem):
Kolumny przedstawiają kodowanie w następujący sposób:
UrlEncoded:
HttpUtility.UrlEncode
UrlEncodedUnicode:
HttpUtility.UrlEncodeUnicode
UrlPathEncoded:
HttpUtility.UrlPathEncode
EscapedDataString:
Uri.EscapeDataString
EscapedUriString:
Uri.EscapeUriString
HtmlEncoded:
HttpUtility.HtmlEncode
HtmlAttributeEncoded:
HttpUtility.HtmlAttributeEncode
HexEscaped:
Uri.HexEscape
UWAGI:
HexEscape
obsługuje tylko pierwsze 255 znaków. Dlatego zgłaszaArgumentOutOfRange
wyjątek dla znaków Latin A-Extended (np. Ā).Ta tabela została wygenerowana w .NET 4.0 (patrz komentarz Levi Botelho poniżej, który mówi, że kodowanie w .NET 4.5 jest nieco inne).
EDYTOWAĆ:
Dodałem drugą tabelę z kodowaniem dla .NET 4.5. Zobacz tę odpowiedź: https://stackoverflow.com/a/21771206/216440
EDYCJA 2:
Ponieważ ludzie wydają się doceniać te stoły, pomyślałem, że może ci się spodobać kod źródłowy, który generuje ten stół, abyś mógł bawić się wokół siebie. Jest to prosta aplikacja konsoli C #, która może być ukierunkowana na .NET 4.0 lub 4.5:
źródło
Uri.EscapeUriString
, ale uwaga: nie obsługujenull
argumentu.UrlPathEncode
. Więc w zasadzie zastąpićUrlPathEncode
zUri.EscapeUriString
.Powinieneś zakodować tylko nazwę użytkownika lub inną część adresu URL, która może być nieprawidłowa. Kodowanie adresu URL może prowadzić do problemów, ponieważ coś takiego:
Ustąpi
To oczywiście nie zadziała dobrze. Zamiast tego należy zakodować TYLKO wartość pary klucz / wartość w ciągu zapytania, tak jak poniżej:
Mam nadzieję, że to pomaga. Ponadto, jak wspomniano w teedyay , nadal musisz upewnić się, że znaki nielegalnej nazwy pliku zostały usunięte, w przeciwnym razie systemowi plików nie spodoba się ścieżka.
źródło
?
(ponieważ zakłada, że ciąg zapytania jest już zakodowany). W przykładzie Dana Herberta wygląda na to, że udaje,Example
że tekst wymaga kodowania, więcHttpUtility.UrlPathEncode("http://www.google.com/search?q=Example");
nie będzie działać. Wypróbuj z?q=Ex&ple
(tam, gdzie jest pożądany wynik?q=Ex%26ple
). Nie zadziała, ponieważ (1) UrlPathEncode nie dotyka niczego później?
, a (2) UrlPathEncode i tak nie koduje&
.&
, ponieważ potrzebujesz go do ograniczenia parametrów ciągu zapytania. Ale są chwile, kiedy chcesz także zakodowane znaki handlowe.Lepszym sposobem jest użycie
Uri.EscapeUriString
nie odwoływać się do pełnego profilu .net 4.
źródło
Uri.EscapeDataString
NIEUri.EscapeUriString
Przeczytaj ten komentarz, pomógł mi.Od .NET Framework 4.5 i .NET Standard 1.0 powinieneś używać
WebUtility.UrlEncode
. Zalety w porównaniu z alternatywami:Jest częścią .NET Framework 4.5+, .NET Core 1.0+, .NET Standard 1.0+, UWP 10.0+ oraz wszystkich platform Xamarin.
HttpUtility
, chociaż jest wcześniej dostępny w .NET Framework (.NET Framework 1.1+), staje się dostępny na innych platformach znacznie później (.NET Core 2.0+, .NET Standard 2.0+) i nadal nie jest dostępny w UWP (patrz powiązane pytanie ).W .NET Framework znajduje się w nim
System.dll
, więc nie wymaga żadnych dodatkowych odniesień, w przeciwieństwie doHttpUtility
.W odróżnieniu od tego poprawnie zmienia znaki dla adresów URL
Uri.EscapeUriString
(patrz komentarze do odpowiedzi drweb86 ).W przeciwieństwie do (patrz powiązane pytanie ) nie ma żadnych ograniczeń długości łańcucha , więc można go na przykład użyć do żądań POST.
Uri.EscapeDataString
źródło
Levi Botelho skomentował, że wcześniej wygenerowana tabela kodowań nie jest już dokładna dla .NET 4.5, ponieważ kodowania zmieniły się nieznacznie między .NET 4.0 i 4.5. Ponownie wygenerowałem tabelę dla .NET 4.5:
Kolumny przedstawiają kodowanie w następujący sposób:
HttpUtility.UrlEncode
HttpUtility.UrlEncodeUnicode
HttpUtility.UrlPathEncode
WebUtility.UrlEncode
Uri.EscapeDataString
Uri.EscapeUriString
HttpUtility.HtmlEncode
HttpUtility.HtmlAttributeEncode
WebUtility.HtmlEncode
Uri.HexEscape
UWAGI:
HexEscape obsługuje tylko pierwsze 255 znaków. Dlatego zgłasza wyjątek ArgumentOutOfRange dla znaków Latin A-Extended (np. Ā).
Ta tabela została wygenerowana w .NET 4.5 (patrz kodowanie https://stackoverflow.com/a/11236038/216440 dla kodowań odpowiednich dla .NET 4.0 i niższych).
EDYTOWAĆ:
źródło
(Net4.0) ? %3f................................
(Net4.5) ? %3f ..................................
Kodowanie adresów URL jest łatwe w .NET. Posługiwać się:
Jeśli zostanie to zdekodowane w celu uzyskania nazwy folderu, nadal musisz wykluczyć znaki, których nie można użyć w nazwach folderów (*,?, / Itd.)
źródło
Jeśli nie widzisz System.Web, zmień ustawienia projektu. Docelową strukturą powinna być „.NET Framework 4” zamiast „.NET Framework 4 Client Profile”
źródło
Implementacja .NET
UrlEncode
nie jest zgodna z RFC 3986.Niektóre znaki nie są zakodowane, ale powinny być. Te
!()*
znaki są wymienione w sekcji 2.2 RFC jako zarezerwowanego znaków, które muszą być jeszcze kodowanych NET zawodzi kodować te znaki.Niektóre znaki są zakodowane, ale nie powinny. Te
.-_
znaki nie są wymienione w sekcji 2.2 RFC jako zastrzeżonego znaku, który nie powinien zostać zakodowany jeszcze .NET błędnie koduje te znaki.RFC określa, że aby zachować spójność, implementacje powinny używać HEXDIG pisanych wielkimi literami, gdzie .NET produkuje HEXDIG pisany małymi literami.
źródło
Myślę, że ludzie tutaj zostali odsunięci na bok przez wiadomość UrlEncode. URLEncoding nie jest tym, czego chcesz - chcesz zakodować rzeczy, które nie będą działać jako nazwa pliku w systemie docelowym.
Zakładając, że chcesz trochę ogólności - nie krępuj się znaleźć nielegalnych znaków w kilku systemach (MacOS, Windows, Linux i Unix), połącz je, aby utworzyć zestaw znaków do ucieczki.
Jeśli chodzi o ucieczkę, HexEscape powinien być w porządku (Zastąpienie znaków% XX). Konwertuj każdy znak na bajty UTF-8 i koduj wszystko> 128, jeśli chcesz obsługiwać systemy, które nie obsługują Unicode. Ale są też inne sposoby, takie jak użycie ukośników odwrotnych „\” lub kodowania HTML „”. Możesz stworzyć swój własny. Wszystko, co każdy system musi zrobić, to „zakodować” niezgodny znak. Powyższe systemy pozwalają odtworzyć oryginalna nazwa - ale działa również coś takiego jak zastąpienie złych znaków znakiem spacjami.
W przypadku tej samej stycznej jak powyżej jedyny do użycia to
- Koduje wszystko, co jest potrzebne do OAuth, nie koduje rzeczy, których OAuth zabrania kodowania, i koduje przestrzeń jako% 20, a nie + (również w specyfikacji OATH) Patrz: RFC 3986. AFAIK, to jest najnowsza specyfikacja URI.
źródło
Napisałem metodę C #, która url-koduje WSZYSTKIE symbole:
źródło
Idealnie byłoby, gdyby poszedł w klasie o nazwie „FileNaming” lub może po prostu zmienić nazwę Encode na „FileNameEncode”. Uwaga: nie są one zaprojektowane do obsługi Pełnych ścieżek, tylko nazwy folderów i / lub plików. Najlepiej byłoby najpierw podzielić („/”) pełną ścieżkę, a następnie sprawdzić elementy. I oczywiście zamiast unii, możesz po prostu dodać znak „%” do listy znaków niedozwolonych w systemie Windows, ale myślę, że w ten sposób jest to bardziej pomocne / czytelne / oparte na faktach. Dekodowanie () jest dokładnie takie samo, ale przełącza opcję Zamień (Uri.HexEscape (s [0]), s) na „znak ucieczki” ze znakiem.
Dzięki @ simon-tewsi za bardzo przydatną tabelę powyżej!
źródło
Path.GetInvalidFileNameChars()
Oprócz odpowiedzi @Dana Herberta, powinniśmy ogólnie zakodować tylko wartości.
Split ma parametr params Split ('&', '='); wyrażenie najpierw podzielone przez & następnie '=', więc elementy nieparzyste to wszystkie wartości do zakodowania pokazane poniżej.
źródło