уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Буквально на днях, разрабатывая небольшой компонент по работе с web-страничками столкнулся с проблемой — функция InternetCrackURL всё время выдавала false,  несмотря на то, что выполняла свое назначение — разбор URL на составляющие части.

Если Вы столкнулись с тем же, т.е. GetLastError все время выдает номера 87, 12006, 122 и пр., то эта статья поможет Вам от этих ошибок избавиться.

Например, если вспомнить тему про Captcha, то там вроде бы все работало «на ура», а вот такой код Delphi:

if InternetCrackUrl(PChar(aURL), Length(aURL), 0, aURLC) then
  begin
    FDomain:=aURLC.lpszHostName;
    Delete(FDomain,pos(aURLC.lpszUrlPath,aURLC.lpszHostName),length(aURLC.lpszUrlPath));
    if (Length(FURL)=0)or(pos(FDomain,FURL)=0) then
      SetURL(FDomain)
  end
else
  MessageBox(0, PChar('Ошибка WinInet #'+IntToStr(GetLastError)),'Ошибка', MB_OK);

всё время выдавал ошибки. Причем если сравнить два фрагмента (представленный выше и из темы про Captcha), то Вы можете убедиться, что различий практически нет. А ошибки есть. Вот я и решил немного разобраться и довести-таки работу с этой функцией до ума.

Итак, обратимся вначале к первоисточнику, посмотрим, что говорит про функцию MSDN:

InternetCrackURL разделяет URL на составные части

Возвращает TRUE в случае успеха. Чтобы получить дополнительную информацию об ошибке, вызовите GetLastError.

Параметр lpszUrl содержит указатель на строку, содержащую канонический URL для разборки

Параметр dwFlags может быть двух видов: ICU_DECODE и ICU_ESCAPE

Собственно ничего нового, делаем всё вроде бы правильно, а на выходе получаем ошибки с кодами: 87, 12006 и пр. В общем всё, кроме положительного результата.

Единственное, что остается делать — это разобраться, чем отличается канонический URL от неканонического? Хотя зачем лишний раз ломать голову, если есть функция InternetCanonicalizeUrl. Смотрим её описание:

Каноникализирует URL, преобразовывая небезопасные символы и пробелы в управляющие последовательности.

Воспользоваться функцией можно следующим образом:

var lencurl: cardinal;
    aURL: string;
begin
  lencurl:=INTERNET_MAX_URL_LENGTH;
  SetLength(aURL, lencurl);
  InternetCanonicalizeUrl(PChar(cURL),PChar(aURL),lencurl,ICU_BROWSER_MODE);
end;

где переменная cURL — это URL, который надо каноникализировать, а на выходе получим необходимый нам URL в переменной aURL. Для более подробного изучения параметров этой функции можете почитать справку MSDN, а нам и этого фрагмента будет достаточно.

Теперь дополняем нашу функцию по разбору URL следующим образом:

....
lencurl:=INTERNET_MAX_URL_LENGTH;
SetLength(aURL, lencurl);
InternetCanonicalizeUrl(PChar(cURL),PChar(aURL),lencurl,ICU_BROWSER_MODE);
if InternetCrackUrl(PChar(aURL), Length(aURL), 0, aURLC) then
  begin
    FDomain:=aURLC.lpszHostName;
    Delete(FDomain,pos(aURLC.lpszUrlPath,aURLC.lpszHostName),length(aURLC.lpszUrlPath));
    if (Length(FURL)=0)or(pos(FDomain,FURL)=0) then
      SetURL(FDomain)
  end
else
  MessageBox(0, PChar('Ошибка WinInet #'+IntToStr(GetLastError)),'Ошибка', MB_OK);
....

т.е. передаем в InternetCrackURL явно каноникализированный URL и всё — функция работает как надо, без всяких непредвиденных ошибок.  Я не знаю специально ли или нет разработчики Microsoft не включили в тело функции InternetCrackURL проверку на каноничность URL, но как бы там ни было, без связки с InternetCanonicalizeUrl она работает некорректно, даже если вы будете ей «скармливать» адреса типа http://webdelphi.ru (без всяких пробелов и не безопасных символов).
Ну, и конечно, не забывайте проверять свой URL на наличие подстроки «http://» либо явно указывайте схему URL’а.

0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
6 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
sbseo
sbseo
25/09/2009 03:59

А нет ли какого юнита или компонента, для реализаций этих функций без привязки к WinIntet, уж больно это глючная библиотека.

Alex - CyberMake
30/09/2011 21:05

Все гораздо проще, неужели никто не заклядывал внутрь синапса?
Используйте просто библиотеку synautil.pas
Функция ParseURL, напишите небольшую прослойку на нее, чтобы не вызывать каждый раз кучу параметров, а давать на функцию всего 2 парметра: URL и тип возвращаемого юрл (Host, Path, Para) и все готово.
Выдает следующие параемтры: URL, Prot, User, Pass, Host, Port, Path, Para
Причем парсит быстро и без багов и без WinIntet !

Alex - CyberMake
29/11/2011 03:24

Vlad, я отвечал на этот вопрос:

sbseo пишет:
25 Сен 2009 в 3:59 дп

А нет ли какого юнита или компонента, для реализаций этих функций без привязки к WinIntet, уж больно это глючная библиотека.

  Разве я на него не ответил? И зачем вы мне это пишите куда я смотрел или не смотрел и удаляете мои посты?