Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

php 4.3 url encoding - kodowanie linków ASCII UTF-8

377 views
Skip to first unread message

Andrzej P

unread,
Jan 9, 2008, 5:35:07 AM1/9/08
to
Witam serdecznie.

Mam problem z konwersją kodowania polskich znaków w linkach PHP 4.3.11.

Opiszę problem, może ktoś zna rozwiązanie, bo funkcje konwersji
kodowania nie działają w tym przypadku.

Pliki PDF i DOC są tworzone w MS Windows (XP) i przesyłane przez FTP na
serwer Apache.
Pliki mają być dostępne do pobrania i indeksowane przez wyszukiwarki,
jako artykuły na stronie, i mają zawierać w nazwach polskie znaki (nie
ustalałem tego, tylko implementuję).

Może wkleję najpierw cały fragment kodu:
***
<?php
if ($handle = opendir('./folder'))
{
while (false !== ($file = readdir($handle)))
{
echo (mb_detect_encoding($file) . "-orig, ");
$file_utf = $file;
$file_utf = mb_convert_encoding($file_utf, "UTF-8", "ASCII");
echo ("A-UTF: " . mb_detect_encoding($file_utf));
$file_url = $file;
$file_url = rawurlencode($file_url);
echo (", A->RawURLencoded: " . mb_detect_encoding($file_url));
if ($file != "." && $file != "..") && (strstr($file, '.') !=
'.php'))
{
echo "<li><a href=\"./folder/" . $file_url . "\">" .
$file_utf . "</a></li>\n";
}
}
closedir($handle);
}
?>
***


Aby iterować po plikach w katalogu, użyłem funkcji
readdir($handle)))

Gdy sprawdzam kodowanie zmiennej $file z nazwą pliku, dostaję ASCII:

echo (mb_detect_encoding($file));

Kopiuję jej zawartość

(tu może leżeć problem, bo w zmiennej zapewne nie jest nazwa, ale
odniesienie do pliku, więc tak tego nie skonwertuję)

do nowej zmiennej i aby zmienić ją na UTF 8, którego używa moja strona,
konwertuję za pomocą
$file_utf = mb_convert_encoding($file, "UTF-8", "ASCII");

ale po detekcji nadal jest kodowanie ASCII...

Jedyne, co udaje mi się osiągnąć, to zakodowanie url:

$file_url = rawurlencode($file_url);

jednak nie tylko linki są zakodowane, ale także nazwa pliku przy
zapisywaniu go jest "zakrzaczona" w stylu
"[...]/Za%BF%F3%B3%E6%20g%EA%9Cl%B9%20ja%9F%F1%20-%20_.pdf" jako "Zażółć
gęśłą jaźń - _.pdf", ale link działa i można pobrać plik - jedyny
problem to niezrozumiała nazwa.

Na dostępnym serwerze dopiero za półtora miesiąca może zostać
przeprowadzone uaktualnienie PHP, więc będę bardzo wdzięczny za
wskazówki, jak poprawnie wyświetlić polskie znaki w adresach linków i w
treści linków, aby nazwa przy zapisie była poprawna.

Dzięki z góry za wskazówkę.
--
Pozdrawiam, /Greetings,
Andrzej

lukasz....@wp.pl

unread,
Jan 9, 2008, 8:57:59 AM1/9/08
to

uzyj funkcji, ktora bedzie dekodowac "/Za%BF%F3%B3%E6%20g%EA%9Cl
%B9%20ja%9F%F1%20-%20_.pdf" do czytelnej nazwy. Nie wiem, czy php 4
ma wbudowana takowa, ale jesli by cos dalej zle sie konwertowalo to
napisz wlasna funkcje, ktora odpowiednie znaczki bedzie podmieniac na
polskie literki tzn.
"%BF" => "ż"

Artur Muszyński

unread,
Jan 9, 2008, 11:52:08 AM1/9/08
to
Andrzej P pisze:

> Gdy sprawdzam kodowanie zmiennej $file z nazwą pliku, dostaję ASCII:
>
> echo (mb_detect_encoding($file));

Detekcja jest zawodna. ASCII to kodowanie, które na pewno nie nadaje się
do polskich znaków. Jakie jest, to zależy od systemu operacyjnego.

> (tu może leżeć problem, bo w zmiennej zapewne nie jest nazwa, ale
> odniesienie do pliku, więc tak tego nie skonwertuję)

Ale czemu takie domysły?

artur

Andrzej P

unread,
Jan 10, 2008, 5:26:27 AM1/10/08
to
lukasz....@wp.pl, @ 2008-01-09 14:57:
> uzyj funkcji, ktora bedzie dekodowac "/Za%BF%F3%B3%E6%20g%EA%9Cl
> %B9%20ja%9F%F1%20-%20_.pdf" do czytelnej nazwy. Nie wiem, czy php 4
> ma wbudowana takowa, ale jesli by cos dalej zle sie konwertowalo to
> napisz wlasna funkcje, ktora odpowiednie znaczki bedzie podmieniac na
> polskie literki tzn.
> "%BF" => "ż"

Mogę podmienić poszczególne litery, ale jeśli robię to w url po stronie
serwera - link przestaje działać.
Udało mi się zmusić linki do działania (skryptem powyżej), ale przy
próbie pobrania (Zapisz jako), nazwa pliku zawiera wszystkie te
procenty, czyli znaki zakodowane url.

Patrząc na wikipedię w Firefox zauważyłem, że wyrażenie "strona główna"
w adresie jest zakodowane inaczej, niż przykład powyżej, jest to tzw.
Unicode w transformacji UTF-8. Pierwszy raz spotykam takie określenie.

OK, skoro już najniższy poziom abstrakcji, to na razie próbuję różnych
wariantów zapisu, np. wielkie Ą:
"%a5" powinienem zamienić na dwa bajty C4 84, ale sprawdzam w jaki
sposób zapisane: "%C4%84", "#C4#84", "&#C4;&#84;"

Jeśli ktoś bawił się w kodowanie na poziomie bajtów - będę wdzięczny za
podpowiedź. To musi się dać zrobić, nie wiem tylko, czy przy użyciu
bezpośrednich linków do plików.

--
Pozdrawiam,
Andrzej

Andrzej P

unread,
Jan 10, 2008, 6:43:03 AM1/10/08
to
Artur Muszyński, @ 2008-01-09 17:52:

Nie wiem, rzeczywiście głupio palnąłem. :/
To jak wiarygodnie sprawdzić kodowanie nazwy pliku?
Chodzi o pliki powstałe w polskim Windows XP umieszczone na linuksie.

--
Pozdrawiam,
Andrzej

Tomasz Śledź

unread,
Jan 9, 2008, 6:05:21 AM1/9/08
to

To ze sie tak link wyswietla to jest jak najbardziej poprawnie. Nie powino sie
stosować znakow narodowych w linkach (nazwach plikow), dlatego tez sa one
dekodowane, bo jaką masz pewnosc, ze np w przegladarce rosyjskiej w pasku
adresu pojawią się polskie znaki (ąśćłęó) ???
Popatrz sobie np na wikipedie, znajdz jakies haslo, a potem przelacz sie na
inna wersje jezykowa np rosyjska ..

Jesli nie chcesz takich krzakow to nie podawaj nazwy pliku w linku tylko
powiedzmy id tego pliku z np bazy (moze to byc nawet numer linii w pliku z
nazwami), co jest bezpieczniejsze niz podawanie nazwy pliku, bo ciekawi mnei
czy jesli zastapie ta nazwe takim ciagiem '/etc/passwd' to tez mi zwrocisz
plik ???

--
Archiwum grupy: http://niusy.onet.pl/pl.comp.lang.php

Andrzej P

unread,
Jan 11, 2008, 7:22:51 AM1/11/08
to
Tomasz Śledź, @ 2008-01-09 12:05:

>> Aby iterować po plikach w katalogu, użyłem funkcji
>> readdir($handle)))
>>
>> Gdy sprawdzam kodowanie zmiennej $file z nazwą pliku, dostaję ASCII:
>>
>> echo (mb_detect_encoding($file));
>>
>> Kopiuję jej zawartość
>> do nowej zmiennej i aby zmienić ją na UTF 8, którego używa moja strona,
>> konwertuję za pomocą
>> $file_utf = mb_convert_encoding($file, "UTF-8", "ASCII");

działa też iconv("Windows-1250", "UTF-8", $file);

>> ale po detekcji nadal jest kodowanie ASCII...
>>
>> Jedyne, co udaje mi się osiągnąć, to zakodowanie url:
>>
>> $file_url = rawurlencode($file_url);
>>
>> jednak nie tylko linki są zakodowane, ale także nazwa pliku przy
>> zapisywaniu go jest "zakrzaczona" w stylu
>> "[...]/Za%BF%F3%B3%E6%20g%EA%9Cl%B9%20ja%9F%F1%20-%20_.pdf" jako "Zażółć
>> gęśłą jaźń - _.pdf", ale link działa i można pobrać plik - jedyny
>> problem to niezrozumiała nazwa.
>

> To ze sie tak link wyswietla to jest jak najbardziej poprawnie. Nie powino sie
> stosować znakow narodowych w linkach (nazwach plikow), dlatego tez sa one
> dekodowane, bo jaką masz pewnosc, ze np w przegladarce rosyjskiej w pasku
> adresu pojawią się polskie znaki (ąśćłęó) ???
> Popatrz sobie np na wikipedie, znajdz jakies haslo, a potem przelacz sie na
> inna wersje jezykowa np rosyjska ..

Rozumiem, że linki muszą być zakodowane, aby uniknąć błędów i ataków
związanych z różnymi stronami kodowymi.

Wchodząc na http://pl.wikipedia.org/
- w Firefox widzę adres http://pl.wikipedia.org/wiki/Strona_g%C5%82%C3%B3wna
- natomiast Opera pokazuje http://pl.wikipedia.org/wiki/Strona_główna
i po przełączeniu na ru.wikipedia.org także, korzystając w dobrodziejstw
unikodu widzimy poprawne litery cyrylicy:
http://ru.wikipedia.org/wiki/Заглавная_страница
Oczywiście, można powiedzieć, że bezpieczniej jest, gdy widać te
procenty, bo to jest, hmm... internationally-human-readable.
Np. adres rosyjskiej strony głównej wygląda wtedy tak:
http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0

Ale u mnie problem jest nieco inny, bo chodzi nie o adresy stron, ale
plików stworzonych w Windows XP, więc kodowanych CP-1250 (Windows-1250).

Litera "ł" w Wikipedii, to %C5%82, w działającym linku u mnie, to %B3.
Wiki używa według artykułu
http://pl.wikipedia.org/wiki/Sposób_kodowania_polskich_znaków
"Unicode w transformacji UTF-8",
a ja: "CP1250 (Windows EE)", skonwertowanego rawurlencode().

Wiem, że "plików nie nazywa się używając polskich znaków, bo są z tym
problemy". Interesuje mnie tylko, czy mając takie pliki, linkowanie do
nich jest niemożliwe bez utraty "miłej" nazwy pliku podczas pobierania.

Jest coś takiego, jak iconv, ale dla mnie niewystarczająco
udokumentowane, więc nie wiem, czy można przy jego pomocy, przekazując
do Apache'a link w Unicode - UTF-8, sprawić, by odniósł go do pliku ze
stroną kodową z klątwą Redmond.
(Na marginesie, uważam, że to, iż w Windows XP nie ma standardowego
kodowania znaków, jest gorsze, niż sprawy, za które autorzy mają kary
antymonopolowe. Ciekawe, jakie kodowanie ma system plików w Vista...)

Piszę stronę www dla osoby z pokolenia "before computer", więc upload
artykułów PDF i DOC odbywa się przez FTP i strona nie używa bazy danych,
bo *ma nie być metadanych, o ile to tylko możliwe*. Zatem chcę się
upewnić, czy to niemożliwe.

Czy załatwiłby sprawę skrypt PHP, do którego odwoływać się będą linki z
nazwami zakodowanymi w UTF-8, a który będzie je transformował na nazwy
CP-1250 i przesyłał plik klientowi (inicjował transfer)? Gdzie szukać,
jak to zrobić? Bo chyba kodowanie pliku pobieranego może różnić się od
kodowania strony?

Czy też cała idea jest niewłaściwa? Może muszę zrobić to po stronie
użytkownika w javascript? (Bo baza danych nie pomoże mi, jeśli pobierane
pliki mają zachować ładne nazwy. Ale jeśli mają się brzydko nazywać,
potrzebuję już metadanych, czyli proste uploadowanie szlag jasny trafi.
A prostota jest tu kluczowa.

> Jesli nie chcesz takich krzakow to nie podawaj nazwy pliku w linku tylko
> powiedzmy id tego pliku z np bazy (moze to byc nawet numer linii w pliku z
> nazwami), co jest bezpieczniejsze niz podawanie nazwy pliku, bo ciekawi mnei
> czy jesli zastapie ta nazwe takim ciagiem '/etc/passwd' to tez mi zwrocisz
> plik ???

Serwer jest zabezpieczony przez hosting, bez indexów pliki się nie
wyświetlają, nie ma dostępu poza katalog html, więc internauta nie
dostanie takiego pliku.

Wielkie dzięki za cierpliwość, przeczytanie, komentarze i wskazówki. :)
--
Pozdrawiam,
Andrzej

Artur Muszyński

unread,
Jan 11, 2008, 7:42:38 AM1/11/08
to
Andrzej P pisze:

> Ale u mnie problem jest nieco inny, bo chodzi nie o adresy stron, ale
> plików stworzonych w Windows XP, więc kodowanych CP-1250 (Windows-1250).

Masz rację - kodowanie URL, a kodowanie nazw plików na lokalnym
filesystemie to zupełnie różne sprawy.

> Wiem, że "plików nie nazywa się używając polskich znaków, bo są z tym
> problemy". Interesuje mnie tylko, czy mając takie pliki, linkowanie do
> nich jest niemożliwe bez utraty "miłej" nazwy pliku podczas pobierania.

W skrócie - używanie znaków spoza US-ASCII w URL nie jest możliwe (jest
przy specyficznej konfiguracji przeglądarki i to nie każdej).

> Jest coś takiego, jak iconv, ale dla mnie niewystarczająco
> udokumentowane, więc nie wiem, czy można przy jego pomocy, przekazując
> do Apache'a link w Unicode - UTF-8, sprawić, by odniósł go do pliku ze
> stroną kodową z klątwą Redmond.

Korzystanie z iconv jest proste jak drut. Zrobiłeś to bez problemu,
tylko najpierw musisz poczytać nieco o kodowaniu znaków w ogóle.

> (Na marginesie, uważam, że to, iż w Windows XP nie ma standardowego
> kodowania znaków, jest gorsze, niż sprawy, za które autorzy mają kary
> antymonopolowe. Ciekawe, jakie kodowanie ma system plików w Vista...)

To już nie na temat i nie ma wiele wspólnego z twoim problemem.

> Piszę stronę www dla osoby z pokolenia "before computer", więc upload
> artykułów PDF i DOC odbywa się przez FTP i strona nie używa bazy danych,
> bo *ma nie być metadanych, o ile to tylko możliwe*. Zatem chcę się
> upewnić, czy to niemożliwe.

Przez FTP można popsuć bardzo dużo. FTP nie rozróżnia kodowania znaków w
ogóle.

> Czy załatwiłby sprawę skrypt PHP, do którego odwoływać się będą linki z
> nazwami zakodowanymi w UTF-8, a który będzie je transformował na nazwy
> CP-1250 i przesyłał plik klientowi (inicjował transfer)? Gdzie szukać,
> jak to zrobić? Bo chyba kodowanie pliku pobieranego może różnić się od
> kodowania strony?

Stronę masz w UTF-8, dlaczego chcesz przekształcać na W1250? O kodowaniu
URL już pisałem.

> Czy też cała idea jest niewłaściwa? Może muszę zrobić to po stronie
> użytkownika w javascript? (Bo baza danych nie pomoże mi, jeśli pobierane
> pliki mają zachować ładne nazwy. Ale jeśli mają się brzydko nazywać,
> potrzebuję już metadanych, czyli proste uploadowanie szlag jasny trafi.
> A prostota jest tu kluczowa.

O ładnych nazwach zapomnij. Tak dla wszystkich będzie najlepiej.

artur

Andrzej P

unread,
Jan 11, 2008, 8:28:18 AM1/11/08
to
Tomasz Śledź, @ 2008-01-11 14:02:
> Friday 11 of January 2008 13:42:38 Artur Muszyński napisał(a):
>> Andrzej P pisze:

>>> Czy też cała idea jest niewłaściwa? Może muszę zrobić to po stronie
>>> użytkownika w javascript? (Bo baza danych nie pomoże mi, jeśli pobierane
>>> pliki mają zachować ładne nazwy. Ale jeśli mają się brzydko nazywać,
>>> potrzebuję już metadanych, czyli proste uploadowanie szlag jasny trafi.
>>> A prostota jest tu kluczowa.
>> O ładnych nazwach zapomnij. Tak dla wszystkich będzie najlepiej.
>
> Eee dlaczego??
> Ładne nazwy mogą być, tylko trzeba inaczej podejść do problemu.
> Przecież mozna sobie ładnie wygenerować wszytko przy pomocy funkcji header(),
> można wtedy podać "ładną" nazwę pliku. Oczywiście wtedy nie ma linku
> bezpośrednio do pliku, a skrypt musi taki plik wczytać i "wypluć".
>
> A wogóle to trzeba inaczej rozwiązać problem. Kolega usilnie probuje dorobić
> coś do istniejącego rozwiązania ("ładna" nazwa w linku). Może nie robić tego
> w ten sposób: mam program i on musi działać tak, i tak. Powinno się chyba
> podejśc do problemu: Jak napisać program który będzie tak a tak działał. Wg
> mojego rozumowania tak naprawde to nie chcesz mieć ładnej nazwy w linku tylko
> ładną nazwę pliku podczas lokalnego zapisu. Nazwa pliku przesyłanego do usera
> przez przeglądarke nie musi być w żaden posób powiązana z nazwą pliku na
> serwerze.
>

Dokładnie - link może mieć krzaki, byle po pobraniu, przy zapisie na
lokalny dysk był plik z czytelną nazwą.
W zamierzeniu autora artykułów PDF, mają się one także dać czytać
on-line przez plugin w oknie przeglądarki.

(ja tak nie przeglądam treści, bo plugin nie zamyka się dobrze jak
korzystam z opery i mam po zamknięciu kilku plików kilka instancji
uruchomionych. Generalnie się zraziłem.)

Zatem rozumiem, że jakiś jeden skrypt fasadowy server-side do obsługi
transferu plików jest tym, czego potrzebuję, tak? Może nawet ktoś już to
kiedyś napisał ;)
--
Pozdrawiam,
Andrzej

Andrzej P

unread,
Jan 11, 2008, 3:43:33 PM1/11/08
to
Artur Muszyński, @ 2008-01-11 13:42:
> Andrzej P pisze:

>> Piszę stronę www dla osoby z pokolenia "before computer", więc upload
>> artykułów PDF i DOC odbywa się przez FTP i strona nie używa bazy
>> danych, bo *ma nie być metadanych, o ile to tylko możliwe*. Zatem chcę
>> się upewnić, czy to niemożliwe.
>
> Przez FTP można popsuć bardzo dużo. FTP nie rozróżnia kodowania znaków w
> ogóle.

Czyli jednak dopisać formularz do uploadowania plików? Zaznaczam, na
danym koncie hostingowym baza SQL nie wchodzi w grę.

>> Czy załatwiłby sprawę skrypt PHP, do którego odwoływać się będą linki
>> z nazwami zakodowanymi w UTF-8, a który będzie je transformował na
>> nazwy CP-1250 i przesyłał plik klientowi (inicjował transfer)? Gdzie
>> szukać, jak to zrobić? Bo chyba kodowanie pliku pobieranego może
>> różnić się od kodowania strony?
>
> Stronę masz w UTF-8, dlaczego chcesz przekształcać na W1250? O kodowaniu
> URL już pisałem.

Tylko dlatego, by wskazać na odpowiednią nazwę pliku.
Przecież jeśli po stronie klienta link będzie ładny w UTF-8, a po
kliknięciu skrypt go po stronie serwera przetworzy na CP-1250, wszystko
będzie grało. Czy źle to rozumiem?
Potrzebuję tylko fasadę, która przechwyci wszystkie linki download w
UTF-8, zamieni na kodowanie faktyczne plików i odeśle je z powrotem.

>
>> Czy też cała idea jest niewłaściwa? Może muszę zrobić to po stronie
>> użytkownika w javascript? (Bo baza danych nie pomoże mi, jeśli
>> pobierane pliki mają zachować ładne nazwy. Ale jeśli mają się brzydko
>> nazywać, potrzebuję już metadanych, czyli proste uploadowanie szlag
>> jasny trafi. A prostota jest tu kluczowa.
>
> O ładnych nazwach zapomnij. Tak dla wszystkich będzie najlepiej.
>
> artur

Zobaczę jeszcze. Ale thx za feedback. Powiem, jak to rozpykam ;)

--
Pozdrawiam,
Andrzej

0 new messages