Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Delphi предпочтительно-7, Indy 10, получить код https-страницы  (Прочитано 1755 раз)
0 Пользователей и 1 Гость смотрят эту тему.
NeferSky
Участник

ru
Offline Offline
Бессмертный


« : 26-10-2016 08:48 » 

Доброго всем дня.
Знаю, вопрос избитый донельзя. Но я уже перелопатил кучу информации по теме, а понятнее не стало.
Собственно, вопрос: а как бы так получить код https-страницы с сайта? Сейчас пытаюсь делать это так:
Код:
procedure TForm1.Button1Click(Sender: TObject);
const
  URL = 'https://www.cbr.ru/currency_base/dynamics.aspx?VAL_NM_RQ=R01010&date_req1=19.10.2016&date_req2=26.10.2016&rt=1&mode=1';
var
  IdHTTP1: TIdHTTP;
  IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL1;
  S: String;
begin
  IdHTTP1 := TIdHTTP.Create(Form1);
  IdHTTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Form1);
  try
    S := IdHTTP1.Get(URL);
  except
    S := WhichFailedToLoad();
  end;
  Memo1.Lines.Add(S);
end;

Получается все фигня какая-то... В сети полно информации, о том, что надо правильные библиотеки OpenSSL для каждой версии Indy. Перепробовал целый вагон уже. Логи моих изысканий тут:
Логи изысканий
ОС: Windows 7 x86
IDE: Delphi XE8
Indy: 10.6.2.5263
Рекомендованная версия OpenSSL: v0.9.8a or later
Версия OpenSSLРезультат WhichFailedToLoad()
indy_openssl096Failed to load libeay32.dll
openssl-0.9.8e-i386-win32Failed to load libeay32.dll
openssl-0.9.8h-i386-win32-Indy-IntraWebEditionFailed to load libeay32.dll
openssl-0.9.8h-i386-win32Failed to load libeay32.dll
openssl-1.0.2j-i386-win32Failed to load libeay32.dll

ОС: Windows 10 x64
IDE: Delphi 7
Indy: 10.6.2.0
Рекомендованная версия OpenSSL: v0.9.8a or later
Версия OpenSSLРезультат WhichFailedToLoad()
indy_openssl096SSL_SESSION_get_id,DES_set_odd_parity,DES_set_key,DES_ecb_encrypt,ERR_peek_last_error,EVP_des_cfb64,EVP_MD_CTX_init,EVP_DigestInit_ex,EVP_DigestFinal_ex,EVP_MD_type,EVP_MD_size,EVP_MD_block_size,EVP_MD_CTX_md,EVP_CIPHER_flags,EVP_CIPHER_CTX_cipher,EVP_CIPHER_CTX_get_app_data,EVP_CIPHER_CTX_set_app_data,EVP_CIPHER_CTX_flags,HMAC_CTX_init,HMAC_Init_ex,HMAC_CTX_cleanup
indy_openssl096bSSL_SESSION_get_id,DES_set_odd_parity,DES_set_key,DES_ecb_encrypt,ERR_peek_last_error,EVP_des_cfb64,EVP_MD_CTX_init,EVP_DigestInit_ex,EVP_DigestFinal_ex,EVP_MD_type,EVP_MD_size,EVP_MD_block_size,EVP_MD_CTX_md,EVP_CIPHER_flags,EVP_CIPHER_CTX_cipher,EVP_CIPHER_CTX_get_app_data,EVP_CIPHER_CTX_set_app_data,EVP_CIPHER_CTX_flags,HMAC_CTX_init,HMAC_Init_ex,HMAC_CTX_cleanup
openssl-0.9.8e-i386-win32Socket error # 10054 Connection reset by peer (в модуле IdStack)
openssl-0.9.8h-i386-win32-Indy-IntraWebEditionSocket error # 10054 Connection reset by peer (в модуле IdStack)
openssl-0.9.8h-i386-win32Socket error # 10054 Connection reset by peer (в модуле IdStack)
openssl-0.9.8h-x64_86-win64Failed to load ssleay32.dll
openssl-1.0.2j-i386-win32Socket error # 10054 Connection reset by peer (в модуле IdStack)
openssl-1.0.2j-x64_86-win64Failed to load ssleay32.dll
Win32OpenSSL_Light-1.0.2jSocket error # 10054 Connection reset by peer (в модуле IdStack)
Win64OpenSSL_Light-1.0.2jFailed to load ssleay32.dll

ОС: Windows 10 x64
IDE: Delphi 7
Indy: 9.00.10
Рекомендованная версия OpenSSL: специальные сборки OpenSSL для Indy
Версия OpenSSLРезультат WhichFailedToLoad()
indy_openssl096EVP_md5 X509_digest X509_NAME_hash
indy_openssl096bEVP_md5 X509_digest X509_NAME_hash
openssl-0.9.8e-i386-win32EVP_md5 X509_digest X509_NAME_hash SSL_CTX_set_info_callback_indy X509_STORE_CTX_get_app_data_indy X509_get_notBefore_indy X509_get_notAfter_indy SSL_SESSION_get_id_indy SSL_SESSION_get_id_ctx_indy SSL_CTX_get_version_indy SSL_CTX_set_options_indy des_set_odd_parity des_set_key des_ecb_encrypt
openssl-0.9.8h-i386-win32-Indy-IntraWebEditionEVP_md5 X509_digest X509_NAME_hash des_set_odd_parity des_set_key des_ecb_encrypt
openssl-0.9.8h-i386-win32EVP_md5 X509_digest X509_NAME_hash des_set_odd_parity des_set_key des_ecb_encrypt
openssl-1.0.2j-i386-win32EVP_md5 X509_digest X509_NAME_hash SSL_CTX_set_info_callback_indy X509_STORE_CTX_get_app_data_indy X509_get_notBefore_indy X509_get_notAfter_indy SSL_SESSION_get_id_indy SSL_SESSION_get_id_ctx_indy SSL_CTX_get_version_indy SSL_CTX_set_options_indy des_set_odd_parity des_set_key des_ecb_encrypt
Win32OpenSSL_Light-1.0.2jFailed to load ssleay32.dll

Найденные на форумах решения успеха не принесли. Наиболее близкие решения, что мне удалось найти:
- на одном форуме приводится текст, автор которого приводит пример "прекрасно работает связка indy 10.5.8 + openssl 1.0.1 (самые новые на момент создания темы)". Indy 10.5.8 я не нашел. Можно, конечно, скачать репозиторий, откатить его на тот релиз и скомпилить - но это уже изврат какой-то.
- еще на одном форуме приводится выдержка с форума Embarcadero, что "Later Indy 10 versions switched to the official OpenSSL DLLs" и "You really should upgrade to a modern Indy 10 release, and then you can use the latest OpenSSL DLLs". Но latest то и это у меня работать вместе отказались.
- также предлагалось решение, принудительно вызвать Load() из IdSSLOpenSSLHeaders, и анализировать результат GetLastError(). Но GetLastError() у меня 0 во всех случаях.

Может, у меня руки из ж я что-то делаю не так?
« Последнее редактирование: 26-10-2016 09:41 от NeferSky » Записан

Не тронь налаженный механизм, и он тебя не подведет.
Делать надо хорошо, а плохо - само получится.
zubr
Модератор

by
Offline Offline
Пол: Мужской

« Ответ #1 : 27-10-2016 07:09 » 

Порой на изучение всяких Delphi-компонент уходит гораздо больше времени, чем изучить матчасть напрямую. Касаемо данной проблемы - получить код https-страницы легко решается использованием, к примеру, стандартного WinHTTP, который хорошо описан в MSDN.
Записан
..::SCRIBE::..
Помогающий

ua
Offline Offline
Пол: Мужской
не путайте банальность с ленью=)


« Ответ #2 : 27-10-2016 13:31 » 

Первое что в глаза бросилось, это ссылка, начинается с "http". Хм.. Или и так работать должно?
Также рекомендуют не путать х32 и х64 версии Open SSL Indy.
« Последнее редактирование: 27-10-2016 13:34 от ..::SCRIBE::.. » Записан
NeferSky
Участник

ru
Offline Offline
Бессмертный


« Ответ #3 : 27-10-2016 22:44 » 

Первое что в глаза бросилось, это ссылка, начинается с "http". Хм.. Или и так работать должно?
Также рекомендуют не путать х32 и х64 версии Open SSL Indy.
Эээ... где 'http'? У меня везде 'https' указано, он мне и нужен.
По поводу х32-х64 версий - ну, это, какбэ, само собой... Хотя, я во всех вариациях попробовал, в первом посте под спойлером можете посмотреть результаты попыток - со старыми версиями openssl, с новыми, со специально-индийскими, 32, 64, на разных ПК, ОСях, делфях...


Порой на изучение всяких Delphi-компонент уходит гораздо больше времени, чем изучить матчасть напрямую. Касаемо данной проблемы - получить код https-страницы легко решается использованием, к примеру, стандартного WinHTTP, который хорошо описан в MSDN.
Спасибо за указание направления, благодаря Вашей подсказке задачу решил. Получилось как-то так:

Код:
procedure TForm1.Button1Click(Sender: TObject);
const
  S_WIN_INET_ERROR = 'Îøèáêà ïîäêëþ÷åíèÿ';

var
  Site: PAnsiChar;
  PagePath: PAnsiChar;
  PageText: String;
  Internet: HINTERNET;
  Session: HINTERNET;
  Request: HINTERNET;
  CountToRead: Cardinal;
  CountReaded: Cardinal;

begin
  //www.cbr.ru
  Site := PAnsiChar(edtSite.Text);
  //currency_base/dynamics.aspx?VAL_NM_RQ=R01010&date_req1=21.10.2016&date_req2=28.10.2016&rt=1&mode=1
  PagePath := PAnsiChar(edtPagePath.Text);
  Memo1.Clear;

  try
    begin
      Internet := InternetOpen('{164E3C3E-E4AF-4AE8-8644-CCBFEFC9ABD1}',
        INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
      if Internet = nil then raise Exception.Create(S_WIN_INET_ERROR);

      Session := InternetConnect(Internet, Site, INTERNET_DEFAULT_HTTP_PORT {INTERNET_DEFAULT_HTTPS_PORT},
        nil, nil, INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 0);
      if Session = nil then
        raise Exception.Create(S_WIN_INET_ERROR);

      Request := HttpOpenRequest(Session, 'GET', PagePath, nil, nil, nil,
        INTERNET_FLAG_RELOAD {or INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS} {or INTERNET_FLAG_SECURE}, 0);
      if Request = nil then
        raise Exception.Create(S_WIN_INET_ERROR);

      if not HttpSendRequest(Request, '', 0, nil, 0) then
        raise Exception.Create(S_WIN_INET_ERROR);

      while InternetQueryDataAvailable(Request, CountToRead, 0, 0) and (CountToRead > 0) do
        begin
          SetLength(PageText, CountToRead);
          InternetReadFile(Request, @PageText[1], CountToRead, CountReaded);
          Memo1.Text := Memo1.Text + PageText;
        end;
    end;

  finally
    begin
      if Request <> nil then InternetCloseHandle(Request);
      if Session <> nil then InternetCloseHandle(Session);
      if Internet <> nil then InternetCloseHandle(Internet);
    end;
  end;
end;

В заключение несколько вопросов по WinInet можно?
1) Я ведь получаю страницу с https-сайта, стало быть, мне нужно использовать https-порт. Но если указать в InternetConnect() порт 443 - INTERNET_DEFAULT_HTTPS_PORT - то сервер отвечает '400 Bad Request, The plain HTTP request was sent to HTTPS port'. А если указывать 80 - INTERNET_DEFAULT_HTTP_PORT - то все работает как ожидается... Почему же тогда у меня порты наоборот? Сайт, на самом деле, доступен на 443 порту, а на 80 - нет, там все честно.
2) В функции HttpOpenRequest() флаг INTERNET_FLAG_SECURE - должен, вроде бы, запускать работу SSL. Но если его добавить - приложение отправить реквест не может. А без него - отправляет, вполне себе хорошо.
3) В функции HttpOpenRequest() флаг INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS - как именно его интерпретировать? MSDN: 'Disables detection of this special type of redirect. When this flag is used, WinINet transparently allow redirects from HTTP to HTTPS URLs.' Так если флаг выставлять - он "ignore" перенаправление в каком смысле - что он его "disables" (выключает и пофиг все) или он его "allow" (разрешает перенаправлять все подряд)? А черт его знает...
ЗЫ: Основываясь на собственных вопросах - а правда, может, сайт SSL не использует, а просто придуряется?
Записан

Не тронь налаженный механизм, и он тебя не подведет.
Делать надо хорошо, а плохо - само получится.
zubr
Модератор

by
Offline Offline
Пол: Мужской

« Ответ #4 : 28-10-2016 08:27 » 

Твой сайт действительно прекрасно работает на http. Замени в своем урле https на http - все равно загрузится. Плюс посмотри в снифере - там будет обмен по http, если в урле будет указан http. Почему не хочет работать через WinInet с данным сайтом по HTTPS - надо разбираться. Попробуй к примеру на яндекс зайти по https - должно загрузиться с параметрами INTERNET_DEFAULT_HTTPS_PORT.
Еще вариант - использовать IE, то есть загрузить страницу из компонета WebBrowser и получить по событию DocumentDownload контент.
Записан
NeferSky
Участник

ru
Offline Offline
Бессмертный


« Ответ #5 : 28-10-2016 09:05 » new

Твой сайт действительно прекрасно работает на http. Замени в своем урле https на http - все равно загрузится. Плюс посмотри в снифере - там будет обмен по http, если в урле будет указан http. Почему не хочет работать через WinInet с данным сайтом по HTTPS - надо разбираться. Попробуй к примеру на яндекс зайти по https - должно загрузиться с параметрами INTERNET_DEFAULT_HTTPS_PORT.
Еще вариант - использовать IE, то есть загрузить страницу из компонета WebBrowser и получить по событию DocumentDownload контент.

Хорошо, буду разбираться. Спасибо)
Вопрос решен, тему можно считать закрытой)
Записан

Не тронь налаженный механизм, и он тебя не подведет.
Делать надо хорошо, а плохо - само получится.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines