![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 70 Pomógł: 0 Dołączył: 28.01.2004 Skąd: że znowu ლ(ಠ益ಠლ Ostrzeżenie: (0%) ![]() ![]() |
Cześć,
poszukuję najlepszego sposobu na walidację adresów stron w skrypcie PHP. Robię klasę więc wersja obiektowa będzie mile widziana. Próbowałem już funkcji parse_url oraz filter_var - niestety, obie przepuszczają niepoprawne adresy (pomijając fakt, że parse_url nie służy do walidacji). Chciałbym się więc skierować w stronę wyrażeń regularnych, ale w wielu przypadkach użytkownicy to odradzają. Dlaczego? Znalazłem takie wyrażenie regularne:
z jednej strony jest okropnie długie i jego wykonanie może być zasochłonne, ale z drugiej strony - nie przepuści żadnego błędnego URLa. Jeśli mogę to samo uzyskać krótszym i prostszym kodem, to chętnie skorzystam, tylko błagam... nie odsyłajcie do szukajek - większość linków (nawet do Zenda w innym temacie na forum) jest już nieaktualnych, albo proponują tam rozwiązanie przepuszczające np. http://www.. (dwie kropki na końcu) Na dłuższy czas porzuciłem tę kwestię, ale znowu muszę się nią zająć... Nadal poszukuję niezawodnego sposobu parsowania URLi. Wyrażenie, które podałem w powyższym poście przepuszcza adresy typu: Kod http://www.kbrg. (z kropką i bez kropki na końcu)http://www.kbrg Próbowałem też regexpy ze strony http://mathiasbynens.be/demo/url-regex ale nie potrafię dostosować ich do PHP - ciągle wywala mi jakiś błąd (IMG:style_emoticons/default/sad.gif) Jakieś pomysły? Ten post edytował tomilipin 31.08.2013, 15:30:58 |
|
|
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 578 Pomógł: 69 Dołączył: 15.04.2007 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Ja bym to zrobił curlem:
|
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Co jest nie tak z filter_varem? Poprawnie odrzuca pierwszy podany przez Ciebie URL (z kropką na końcu) i przepuszcza drugi (prawidłowy URL).
|
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 70 Pomógł: 0 Dołączył: 28.01.2004 Skąd: że znowu ლ(ಠ益ಠლ Ostrzeżenie: (0%) ![]() ![]() |
timon, Twój kod akceptuje taki adres http://www.kbrg.
Ja już nie rozumiem... czy http://www.kbrg. jest poprawnym URLem? Crozin, filter_var przepuszcza np. to Kod http://example.com/"><script>alert(document.cookie)</script> Generalnie skłaniałem się do użycia tego regexpa Kod _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS ale dostaję takie błędy: Cytat Notice: Undefined variable: _iuS in kaka.php on line 43 Warning: preg_match(): No ending delimiter '_' found in kaka.php on line 44 od razu zaznaczam, że nie znam się na regexp - bazuję na kopiuj-wklej ze strony http://mathiasbynens.be/demo/url-regex |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 578 Pomógł: 69 Dołączył: 15.04.2007 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Mój kod NIE przepuszcza adresu z kropką na końcu. Coś źle wkleiłeś.
wklej to za definicją funkcji. Bez kropki zwraca prawdę, bo to dobry adres Ten post edytował timon27 16.03.2014, 17:22:06 |
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
@timon27: Twój sposób jest wyjątkowo słaby. 1) Wymaga wykonania żądania HTTP, które samo w sobie może się wykonywać dosłownie godzinami 2) Ogranicza się do kodów odpowiedzi z zakresu 200-300, czyli jak zew. strona padnie to nie będzie się dało zapisać jej URL-a?
@tomilipin: Ale URL, który podałeś jest przecież poprawnym URL-em, który jak najbardziej może istnieć. A ochronę przed XSS (bo jak rozumiem to chciałeś tutaj przedstawić) uzyskuje się przy pomocy htmspecialchars, które musi zostać użyte w momencie wstawiania danych do dokumentu HTML. |
|
|
![]()
Post
#7
|
|
Grupa: Zarejestrowani Postów: 70 Pomógł: 0 Dołączył: 28.01.2004 Skąd: że znowu ლ(ಠ益ಠლ Ostrzeżenie: (0%) ![]() ![]() |
Hmm... tak myślę nad tym, co napisał Crozin i dochodzę do wniosku, że faktycznie to może być problem. No bo jeśli strona padnie, ale jej adres jest poprawny, to niestety funkcja timona zwróci FALSE.
Co do filter_var - zastosowałem to tak: Kod var_dump(filter_var($url, FILTER_VALIDATE_URL)); i oto co otrzymałem... Kod string(13) "htp://www.k.." Wszędzie powinno być FALSEstring(17) "http://3628126748" string(16) "http://224.1.1.1" string(17) "http://a.b--c.de/" Natomiast filter_var odrzuca adresy, w których znajdują się znaki Unicode, np. http://www.broń.pl nie mówiąc już o czymś tak egzotycznym jak http://✪df.ws/123 pod którym kryje się działająca strona, ale nawet forumowy parser nie podołał wykryć w tym przypadku linka. Ale nie poddaję się - szukam dalej rozwiązania (IMG:style_emoticons/default/smile.gif) -- edit -- Zrobiłem (IMG:style_emoticons/default/smile.gif) Oto regexp, który perfekcyjnie filtruje URL: Kod %^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)?$%iu Do użytku z preg_match Pozdrawiam i dziękuję za pomoc (IMG:style_emoticons/default/smile.gif) Ten post edytował tomilipin 17.03.2014, 17:43:44 |
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 1 890 Pomógł: 339 Dołączył: 14.12.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Oto regexp, który perfekcyjnie filtruje URL Pierwszy z brzegu kontrprzykład: http://test.aaaaaaaaaaaaaaa Ja kiedyś zrobiłem wyrażenie regularne z listą wszystkich dostępnych [edit] Zresztą można to przyspieszyć rozbijając na kilka akcji, np. najpierw jakiś strpos z listą domen, a później zawężanie wyniku przez regexp (IMG:style_emoticons/default/smile.gif) Ten post edytował sowiq 17.03.2014, 20:03:35 |
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 129 Pomógł: 13 Dołączył: 29.03.2012 Ostrzeżenie: (0%) ![]() ![]() |
Ja natomiast znalazłem coś takiego. Może sie przyda :
|
|
|
![]()
Post
#10
|
|
Grupa: Zarejestrowani Postów: 1 890 Pomógł: 339 Dołączył: 14.12.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
@emillo91, nowe domeny jak .travel, .museum itp. nie załapią się do Twojego regexpa.
|
|
|
![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 70 Pomógł: 0 Dołączył: 28.01.2004 Skąd: że znowu ლ(ಠ益ಠლ Ostrzeżenie: (0%) ![]() ![]() |
Pierwszy z brzegu kontrprzykład: http://test.aaaaaaaaaaaaaaa Fuck... (IMG:style_emoticons/default/rolleyes.gif) Może uda się jakoś rozbudować tego regexpa żeby nie przepuszczał takich adresów?
|
|
|
![]()
Post
#12
|
|
Grupa: Zarejestrowani Postów: 1 890 Pomógł: 339 Dołączył: 14.12.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Ale przecież niekoniecznie musisz to robić za pomocą jednego regexpa.
Moim zdaniem bardzo dobrym sposobem jest to, co napisałem powyżej. Wchodzisz na Wikipedię, kopiujesz listę domen i robisz z tego tablicę w PHP. Pierwszy krok to sprawdzenie, czy domena jest poprawna. A dalej lecisz z kolejnymi warunkami, chociażby przy pomocy regexpa / regexpów. |
|
|
![]()
Post
#13
|
|
Grupa: Zarejestrowani Postów: 71 Pomógł: 6 Dołączył: 22.09.2012 Ostrzeżenie: (0%) ![]() ![]() |
Kilka wyrażeń i ich testy.
http://mathiasbynens.be/demo/url-regex Tylko jeden przeszedł wszystkie testy - @diegoperini Edit: teraz widzę, że tomilipin to wrzucał Ten post edytował karakara 18.03.2014, 18:24:33 |
|
|
![]()
Post
#14
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
@tomilipin: filter_var sprawdza czy dany URL jest technicznie poprawny, i faktycznie działa on jedynie w zakresie znaków US-ASCII. To dopiero pierwszy etap sprawdzania poprawności. Później powinieneś skorzystać z parse_url i sprawdzić czy poszczególnego części URL-a są przez Ciebie akceptowalne. Na przykład czy protokół to HTTP(S), albo czy host jest sensowną domeną/IP-kiem.
|
|
|
![]()
Post
#15
|
|
Grupa: Zarejestrowani Postów: 124 Pomógł: 22 Dołączył: 10.01.2014 Ostrzeżenie: (0%) ![]() ![]() |
Pozwole się wtrącić w waszą dyskusję.
Dlaczego próbujecie napisać metodę perfekcyjną do sprawdzenia poprawności adresu url ? Według mnie każdy ma inne potrzeby i robi portal dla innych ludzi. Jednemu będą pasowały linki z konkretnej domeny, innemu z całego świata (wystarczy że serwer odpowie) itd. Według mnie trzeba iść tropem dania narzędzia które w drobnym stopniu pomoże zwalidować adres jednak nie ograniczy programisty (nie wiem jak wy ale ja tych regexpów na pierwszy rzut oka nawet nie rozumiem). Osobiście skłaniałbym się w kierunku prostej klasy która tak jak u @sowiq'a sprawdzi poprawność domen i protokołów, a resztę pozostawi do decyzji użytkownika. Według mnie sposób @timon27 jest dobry do określonych sytuacji (osobiście bym chciał aby linki na moim serwisie nie prowadziły do 404..). I nie powiniście go wykluczać całkowicie. Poniżej zamieszczam link do repo w którym daje swoje rozwiazanie. Na 100% nie jest idealne jednak wydaje mi się że jak komuś czegoś będzie w nim brakować to sobie zdziedziczy po mojej klasie / dopisze helper i po sprawie. https://svn.code.sf.net/p/urlvalidate/code/...k/YourFrog/Url/ Zamieściłem przykładowe testy z informacja czy przechodzą czy nie więc łatwiej można sprawdzić poprawnośc. |
|
|
![]()
Post
#16
|
|
Grupa: Zarejestrowani Postów: 70 Pomógł: 0 Dołączył: 28.01.2004 Skąd: że znowu ლ(ಠ益ಠლ Ostrzeżenie: (0%) ![]() ![]() |
Cześć,
znowu zacząłem grzebać w tym kodzie (IMG:style_emoticons/default/smile.gif) Kilka osób sugerowało sprawdzanie poprawności samej domeny (TLD) - taki sposób odpada, gdyż nie przepuści adresów typu http://142.42.1.1 czy http://例子.测试 Wyrażenie regularne autorstwa @diegoperini, wspomniane wcześniej, nie jest idealne, gdyż nie sprawdza poprawności podanych domen i przepuszcza adresy typu http://asd.aaaaaaaaaaaaa Innym pomysłem było użycie filter_var i parse_url - patrz pierwszy post i zapoznaj się z opisem tych funkcji w manualu. Żeby sprawdzić czy "host jest sensowną domeną/IP-kiem" i tak trzeba użyć wyrażeń regularnych, nie widzę więc sensu dodatkowego użycia innych funkcji, skoro można to załatwić jedną linijką kodu. YourFrog, myślę, że masz dużo racji. Idąc Twoim tokiem myślenia, poczyniłem już pewne kroki. Nie są mi potrzebne chińskie krzaki w nazwach TLD, więc pozbyłem się tej funkjonalności. Adresy, które będę walidował to strony producentów żywności, a nie sądzę, żeby którykolwiek reklamował się pod adresem IP, zatem nie jest mi potrzebna walidacja IPków (jednak zostwiłem ją na wszelki wypadek). Chcę mieć istniejącą domenę na końcu, więc dodałem listę akceptowanych przeze mnie nazw TLD. Nie pinguję serwera, bo w przypadku chwilowego braku odpowiedzi mój kod odrzuciłby poprawny adres. Oczywiście nie chcę, żeby linki prowadziły do 404, więc dopiero po walidacji całego adresu można sobie to sprawdzić. Doszedłem więc do takiego regexpa: Kod _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z]{2}|com|org|net|inne_domeny_tutaj_wpisz)))(?::\d{2,5})?(?:/\S*)?$_iuS ten rzeczywiście nie jest idealny, bo nie akceptuje poprawnych domen zapisanych chińskimi czy arabskimi krzakami, ale odpowiada moim potrzebom. Co sądzicie? |
|
|
![]() ![]() |
![]() |
Aktualny czas: 23.08.2025 - 12:17 |