Буквально на днях, разрабатывая небольшой компонент по работе с 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’а.
А нет ли какого юнита или компонента, для реализаций этих функций без привязки к WinIntet, уж больно это глючная библиотека.
Можно конечно и без WinInet, но по-моему глюков от этого не убавится (если таковые есть). Да, и в принципе, из WinInet всего 2 функции используются.
Все гораздо проще, неужели никто не заклядывал внутрь синапса?
Используйте просто библиотеку synautil.pas
Функция ParseURL, напишите небольшую прослойку на нее, чтобы не вызывать каждый раз кучу параметров, а давать на функцию всего 2 парметра: URL и тип возвращаемого юрл (Host, Path, Para) и все готово.
Выдает следующие параемтры: URL, Prot, User, Pass, Host, Port, Path, Para
Причем парсит быстро и без багов и без WinIntet !
Alex – CyberMake, неужели вы не смотрели дальше этого поста? =) Synapse уже давным давно расписан вдоль и поперек в этом блоге, в том числе и модуль sunautil.pas. А случаи бывают разные — кто-то работает с Synapse, а кому-то WinInet подавай
Vlad, я отвечал на этот вопрос:
sbseo пишет:
25 Сен 2009 в 3:59 дп
А нет ли какого юнита или компонента, для реализаций этих функций без привязки к WinIntet, уж больно это глючная библиотека.
Разве я на него не ответил? И зачем вы мне это пишите куда я смотрел или не смотрел и удаляете мои посты?
Alex – CyberMakeб всегда отвечаете на комментарии 2 (двух)-летней давности? И какие посты я удаляю?