Strona 3 z 3

Re: Kodowanie tekstu -> "URLEncode"

Nowy postNapisane: czwartek, 25 lutego 2010, 21:52
przez Cyfrowy Baron
Sam natrafiłem na przypadek gdy funkcja nie zadziała. można to oczywiście poprawić:

Kod: Zaznacz cały
string url_encode(const String sUrl)
{
int p = sUrl.AnsiPos("&q=");
string s1, s2;
string baseUrl;
if(p > 0 || sUrl.SubString(1, 4).LowerCase() != "http")
{
  baseUrl = (sUrl.SubString(1, p + 2)).c_str();
  s1   = (sUrl.SubString(p + 3, sUrl.Length())).c_str();

  char tmp[] = "%XX";

  for(string::const_iterator i = s1.begin(); i != s1.end(); ++i)
  {

        if((*i < 'a' || *i > 'z') && (*i < 'A' || *i > 'Z') &&
          (*i < '0' || *i > '9') && !strchr("-_", *i))
        {
                sprintf(tmp + 1,"%02X",(unsigned char)*i);
            s2 += tmp;
        }
        else s2 += *i;
  }
}
else return sUrl.c_str();

return baseUrl + s2;
}


ale to takie ciągłe łatanie funkcji.
Musiałbym to spokojnie przemyśleć i znaleźć jakieś uniwersalne rozwiązanie. Funkcja z INDY działa niezależnie od tego czy jest to cały adres czy tylko zapytanie, więc jest to do zrobienia.

Re: Kodowanie tekstu -> "URLEncode"

Nowy postNapisane: czwartek, 25 lutego 2010, 22:16
przez polymorphism
Nie rozumiem co chciałeś mi tym kodem udowodnić.

To chciałem udowodnić, że jeśli zamiast CP1250 będzie coś innego, coś wymagającego zakodowania, to twoja funkcja nie zadziała. Przyjąłeś bardzo naiwne założenie, że "&q=" zawsze wystąpi jako pierwsze, a nikt tego nie powiedział. Ba! nawet to q nie musi wystąpić.

Czasami ma znaczenie. Wysyłając np. zapytanie do wyszukiwarki filmweb.pl z hasłem: gość (...)

No dobra, ale to nie wina funkcji, tylko złego kodowania, którego użyłeś do komunikacji z serwerem filmweb'u. Daj jej gość w utf-8 i wszystko będzie jak trzeba.

Re: Kodowanie tekstu -> "URLEncode"

Nowy postNapisane: czwartek, 25 lutego 2010, 22:40
przez polymorphism
Funkcja z INDY działa niezależnie od tego czy jest to cały adres czy tylko zapytanie, więc jest to do zrobienia.

Oczywiście, że jest, tylko trzeba by dokonać analizy URL-a, nawet nie musiałaby być zbyt wnikliwa. Choć według mnie jest to zbyteczne, bo na ogół składasz URL-e z gotowych elementów i wiesz, które elementy musisz zakodować - przykład z google dobrze to pokazuje.


p.s. a jak INDY daje sobie radę w teście z ampersandem, czyli:

http://www.google.com/search?q=&&ie=CP1250


:?:

Re: Kodowanie tekstu -> "URLEncode"

Nowy postNapisane: piątek, 26 lutego 2010, 10:17
przez Cyfrowy Baron
p.s. a jak INDY daje sobie radę w teście z ampersandem, czyli:


Nie tłumaczy tego adresu, ale z tym adresem wklejonym w pasek adresu to nawet przeglądarka Firefox sobie nie radzi, gdyż tłumaczy go na:


http://www.google.com/webhp?ie=CP1250



Jak widać brak kodowania w UTF-8 sprawia, że nie można wysłać zapytania ze znakami && gdyż są zastępowane znakiem zastępczym. Nawet w C++Builder 2010 INDY nie tłumaczy tych znaków na %26, co więcej odkryłem, że funkcja URLEncode musi zawierał cały adres, gdyż przy samym zapytaniu wyskakuje błąd. Właściwie to z nazwy funkcji powinienem wywnioskować, że służy ona do enkodowania całych adresów. Istnieje jednak inna funkcja ParamsEncode:

Kod: Zaznacz cały
// kod dla C++Builder 2010
#include <IdURI.hpp>
void __fastcall TForm1::Button3Click(TObject *Sender)
{

String Url = "http://www.google.com/search?q=&&ie=CP1250";

TIdURI *idUrl = new TIdURI("");

Edit1->Text = idUrl->ParamsEncode(Url); /* dla C++Builder poniżej wersji 2010:  idUrl->ParamsEncode(__classid(TIdURI), Url); */
delete idUrl;
}
//---------------------------------------------------------------------------


Tłumacząca zarówno całe adresy jak i tylko same zapytania, ale i ta funkcja nie tłumaczy znaków zarezerwowanych, czyli: "-_;/?:@=&.". To ograniczenie w enkodowaniu może być czasami przeszkodą.

Idealnym rozwiązaniem była by wiec funkcja, która potrafiłaby oddzielić adres URL od zapytania. W mojej modyfikacji za punkt podziału przyjąłem &p=, ale trzeba by zawrzeć w niej wszystkie możliwe punkty podziału. Modyfikacja przewiduje wystąpienie na początku łańcucha znaków frazy http, może jednak wystąpić sytuacja, gdy pojawi się adres bez tego przedrostka z całym adresem bez zapytania, lub z zapytaniem, funkcja zadziała prawidłowo.



Jak w string zastąpić funkcje AnsiPos i SubString, bez dokonywania konwersji typu string na AnsiString czy też UnicodeString?

Re: Kodowanie tekstu -> "URLEncode"

Nowy postNapisane: sobota, 27 lutego 2010, 23:32
przez polymorphism
---- Z małym opóźnieniem, bo nie dostałem powiadomienia... dziwne :| ----

Nie tłumaczy tego adresu (...)

Ha, no widzisz. Funkcje do wszystkiego zawsze mają słabe punkty.

Jak widać brak kodowania w UTF-8 sprawia, że nie można wysłać zapytania ze znakami && gdyż są zastępowane znakiem zastępczym.
Kodowanie UTF-8 nie ma tu żadnego znaczenia, bo dwa ampersandy w tym kodowaniu to takie same dwa ampersandy jak w kodowaniu ASCII - ten znak nie podlega konwersji ascii -> unikod.

(...) ale z tym adresem wklejonym w pasek adresu to nawet przeglądarka Firefox sobie nie radzi

No nie radzi, bo podobnie jak INDY ma problem z tym znakiem - traktuje go jako separator, a nie jako wartość. I właśnie po to jest to kodowanie, żeby nie było tych niejednoznaczności.

W mojej modyfikacji za punkt podziału przyjąłem &p=, ale trzeba by zawrzeć w niej wszystkie możliwe punkty podziału.

Wszystkie możliwe?! Jest ich nieskończenie wiele, bo p to tylko nazwa, a ta może być dowolnie długim ciągiem znakowym. Zamiast kombinować na ślepo, zajrzyj do specyfikacji, przeczytaj jak skonstruowany jest adres URL, z jakich elementów się składa.

W każdym razie, co byś nie wymyślił, problemu znaku & łatwo nie ominiesz.

Jak w string zastąpić funkcje AnsiPos i SubString (...)

A dokumentacja od czego jest? ;) find_first_of i substr/assign.