#ifndef flagNOSSL #include "WebSSL.h" namespace Upp { extern bool HttpClient_Trace__; #ifdef _DEBUG #define LLOG(x) if(HttpClient_Trace__) RLOG(x); else; #else #define LLOG(x) #endif HttpsClient::HttpsClient() { secure = true; } bool HttpsClient::ProxyConnect() { if(use_proxy) { int start_time = msecs(); int end_time = msecs() + timeout_msecs; while(!socket.PeekWrite(1000)) { int time = msecs(); if(time >= end_time) { error = NFormat(t_("%s:%d: connecting to host timed out"), socket_host, socket_port); Close(); return false; } } String host_port = host; if(port) host_port << ':' << port; else host_port << ":443"; String request; request << "CONNECT " << host_port << " HTTP/1.1\r\n" << "Host: " << host_port << "\r\n"; if(!IsNull(proxy_username)) request << "Proxy-Authorization: Basic " << Base64Encode(proxy_username + ':' + proxy_password) << "\r\n"; request << "\r\n"; LLOG(request); int written = 0; while(msecs() - end_time < 0) { int nwrite = socket.WriteWait(request.GetIter(written), min(request.GetLength() - written, 1000), 1000); if(socket.IsError()) { error = Socket::GetErrorText(); Close(); return false; } if((written += nwrite) >= request.GetLength()) break; } if(written < request.GetLength()) { error = NFormat(t_("%s:%d: timed out sending request to server"), host, port); Close(); return false; } String line = ReadUntilProgress('\n', start_time, end_time, false); LLOG("P< " << line); if(socket.IsError()) { error = Socket::GetErrorText(); Close(); return false; } if(!line.StartsWith("HTTP") || line.Find(" 2") < 0) { error = "Invalid proxy reply: " + line; Close(); return false; } while(line.GetCount()) { line = ReadUntilProgress('\n', start_time, end_time, false); if(*line.Last() == '\r') line.Trim(line.GetCount() - 1); LLOG("P< " << line << " len " << line.GetCount()); if(socket.IsError()) { error = Socket::GetErrorText(); Close(); return false; } } use_proxy = false; while(!socket.PeekWrite(1000)) { int time = msecs(); if(time >= end_time) { error = NFormat(t_("%s:%d: connecting to host timed out"), socket_host, socket_port); Close(); return false; } } } return true; } bool HttpsClient::IsSecure() { return secure; } bool HttpsClient::CreateClientSocket() { if(!secure) return HttpClient::CreateClientSocket(); if(!ssl_context) { ssl_context = new SSLContext; if(!ssl_context->Create(const_cast(SSLv3_client_method()))) { error = t_("Error creating SSL context."); return false; } } if(!SSLClientSocketUnsecured(socket, *ssl_context, socket_host, socket_port ? socket_port : DEFAULT_HTTPS_PORT, true, NULL, 0, false)) { error = Socket::GetErrorText(); return false; } socket.Linger(0); if(!ProxyConnect()) return false; SSLSecureSocket(socket); return true; } } #endif