BOOL HttpProtocol::GetContent(std::map<std::string , std::string> & mapContent) { INT32 nLength = GetContentLength(); std::string strContent = GetContent(); while (strContent.size() > 0) { size_t pos = strContent.find('='); size_t posNext = strContent.find('&'); if (std::string::npos != pos) { std::string strKey = strContent.substr(0, pos); std::string strVal = ""; if (posNext != std::string::npos) { strVal = strContent.substr(pos + 1, posNext - pos - 1); strContent = strContent.substr(posNext + 1, nLength - posNext - 1); } else { strContent = ""; } mapContent.insert(std::make_pair(strKey , strVal)); } else { strContent = ""; } } return TRUE; }
shared_ptr<MimeBody> MimeBody::LoadEncapsulatedMessage() const { // try to generate a file name using the message subject. shared_ptr<MimeBody> pEncapsulatedMessage = shared_ptr<MimeBody>(new MimeBody); int iLength = GetContentLength(); char *pData = new char[iLength+1]; strncpy(pData, (const char*) GetContent(), iLength); int index = 0; pEncapsulatedMessage->Load(pData, iLength, index); delete [] pData; return pEncapsulatedMessage; }
static void LoadCallback(void *user_data, int32_t result) { int32_t len; responseInfo = loader_->GetResponseInfo(loader); loader_status = responseInfo_->GetProperty(responseInfo, PP_URLRESPONSEPROPERTY_HEADERS); len = GetContentLength(loader_status); sprintf(buffer, "len: %d\n", (int)len); Log(buffer); if (len > 0) { file = malloc(len); Log (file ? "file buffer allocated\n" : "allocation failed\n"); loader_->ReadResponseBody(loader, file, len, ReadCompletionCallback); } }
QuviMedia::QuviMedia(std::wstring&& url) : QuviMediaInfo(std::move(url)) , m_curlsh(curl_share_init()) { assert(m_curlsh); // TODO: throw exception curl_share_setopt(m_curlsh, CURLSHOPT_LOCKFUNC, CurlShareLockFunction); curl_share_setopt(m_curlsh, CURLSHOPT_UNLOCKFUNC, CurlShareUnlockFunction); curl_share_setopt(m_curlsh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); curl_share_setopt(m_curlsh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt(m_curlsh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); curl_share_setopt(m_curlsh, CURLSHOPT_USERDATA, &m_curlshLock); curl_easy_setopt(m_curl, CURLOPT_SHARE, m_curlsh); // TODO: ensure that cookies are properly inherited if (GetContentType() == "video/vnd.mpeg.dash.mpd") { std::string murl = GetMultibyteUrl(); if (murl.empty()) throw 1; // TODO: replace with some sensible exception std::unique_ptr<dash::IDASHManager> manager(CreateDashManager()); if (!manager) throw 1; // TODO: replace with some sensible exception std::unique_ptr<dash::mpd::IMPD> mpd(manager->Open(&murl[0])); if (!mpd) throw 1; // TODO: replace with some sensible exception const auto& period = mpd->GetPeriods().front(); for (const auto& adaptationSet : period->GetAdaptationSets()) { const auto& representation = adaptationSet->GetRepresentation().back(); enum class DashRepresentationType { Base, Template, List, }; auto determineType = [](const dash::mpd::IPeriod* period, const dash::mpd::IAdaptationSet* adaptationSet, const dash::mpd::IRepresentation* representation) -> DashRepresentationType { assert(representation && adaptationSet && period); if (representation->GetSegmentList()) return DashRepresentationType::List; if (representation->GetSegmentTemplate()) return DashRepresentationType::Template; if (representation->GetSegmentBase() || !representation->GetBaseURLs().empty()) return DashRepresentationType::Base; if (adaptationSet->GetSegmentList()) return DashRepresentationType::List; if (adaptationSet->GetSegmentTemplate()) return DashRepresentationType::Template; if (adaptationSet->GetSegmentBase()) return DashRepresentationType::Base; if (period->GetSegmentList()) return DashRepresentationType::List; if (period->GetSegmentTemplate()) return DashRepresentationType::Template; if (period->GetSegmentBase()) return DashRepresentationType::Base; throw 1; // TODO: replace with some sensible exception }; const DashRepresentationType type = determineType(period, adaptationSet, representation); if (type != DashRepresentationType::Base) // TODO: support other stream types throw 1; // TODO: replace with some sensible exception // TODO: support compound urls std::unique_ptr<dash::network::IChunk> chunk(representation->GetBaseURLs()[0]->ToMediaSegment({})); if (!chunk) throw 1; // TODO: replace with some sensible exception auto& uri = chunk->AbsoluteURI(); if (uri.empty()) throw 1; // TODO: replace with some sensible exception curl_easy_setopt(m_curl, CURLOPT_URL, &uri[0]); curl_easy_setopt(m_curl, CURLOPT_NOBODY, 1L); CURLcode cc = curl_easy_perform(m_curl); if (cc != CURLE_OK) throw 1; // TODO: replace with some sensible exception // TODO: use return codes long code = 0, proxycode = 0; curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &code); curl_easy_getinfo(m_curl, CURLINFO_HTTP_CONNECTCODE, &proxycode); double size = 0; curl_easy_getinfo(m_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &size); curl_easy_setopt(m_curl, CURLOPT_HTTPGET, 1L); m_backends.emplace_back(std::make_unique<QuviSimpleStreamBackend>((uint64_t)size, m_curl, m_curlsh)); } } else { assert(m_backends.empty()); m_backends.emplace_back(std::make_unique<QuviSimpleStreamBackend>(GetContentLength(), m_curl, m_curlsh)); } }
BUF *HttpRequestEx2(URL_DATA *data, INTERNET_SETTING *setting, UINT timeout_connect, UINT timeout_comm, UINT *error_code, bool check_ssl_trust, char *post_data, WPC_RECV_CALLBACK *recv_callback, void *recv_callback_param, void *sha1_cert_hash, bool *cancel, UINT max_recv_size, char *header_name, char *header_value) { WPC_CONNECT con; SOCK *s; HTTP_HEADER *h; bool use_http_proxy = false; char target[MAX_SIZE * 4]; char *send_str; BUF *send_buf; BUF *recv_buf; UINT http_error_code; char len_str[100]; UINT content_len; void *socket_buffer; UINT socket_buffer_size = WPC_RECV_BUF_SIZE; UINT num_continue = 0; INTERNET_SETTING wt_setting; // Validate arguments if (data == NULL) { return NULL; } if (setting == NULL) { Zero(&wt_setting, sizeof(wt_setting)); setting = &wt_setting; } if (error_code == NULL) { static UINT ret = 0; error_code = &ret; } if (timeout_comm == 0) { timeout_comm = WPC_TIMEOUT; } // Connection Zero(&con, sizeof(con)); StrCpy(con.HostName, sizeof(con.HostName), data->HostName); con.Port = data->Port; con.ProxyType = setting->ProxyType; StrCpy(con.ProxyHostName, sizeof(con.ProxyHostName), setting->ProxyHostName); con.ProxyPort = setting->ProxyPort; StrCpy(con.ProxyUsername, sizeof(con.ProxyUsername), setting->ProxyUsername); StrCpy(con.ProxyPassword, sizeof(con.ProxyPassword), setting->ProxyPassword); if (setting->ProxyType != PROXY_HTTP || data->Secure) { use_http_proxy = false; StrCpy(target, sizeof(target), data->Target); } else { use_http_proxy = true; CreateUrl(target, sizeof(target), data); } if (use_http_proxy == false) { // If the connection is not via HTTP Proxy, or is a SSL connection even via HTTP Proxy s = WpcSockConnectEx(&con, error_code, timeout_connect, cancel); } else { // If the connection is not SSL via HTTP Proxy s = TcpConnectEx3(con.ProxyHostName, con.ProxyPort, timeout_connect, cancel, NULL, true, NULL, false, false, NULL); if (s == NULL) { *error_code = ERR_PROXY_CONNECT_FAILED; } } if (s == NULL) { return NULL; } if (data->Secure) { // Start the SSL communication if (StartSSLEx(s, NULL, NULL, true, 0, NULL) == false) { // SSL connection failed *error_code = ERR_PROTOCOL_ERROR; Disconnect(s); ReleaseSock(s); return NULL; } if (sha1_cert_hash != NULL) { UCHAR hash[SHA1_SIZE]; Zero(hash, sizeof(hash)); GetXDigest(s->RemoteX, hash, true); if (Cmp(hash, sha1_cert_hash, SHA1_SIZE) != 0) { // Destination certificate hash mismatch *error_code = ERR_CERT_NOT_TRUSTED; Disconnect(s); ReleaseSock(s); return NULL; } } } // Timeout setting SetTimeout(s, timeout_comm); // Generate a request h = NewHttpHeader(data->Method, target, use_http_proxy ? "HTTP/1.0" : "HTTP/1.1"); AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE)); AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive")); AddHttpValue(h, NewHttpValue("Accept-Language", "ja")); AddHttpValue(h, NewHttpValue("User-Agent", WPC_USER_AGENT)); AddHttpValue(h, NewHttpValue("Pragma", "no-cache")); AddHttpValue(h, NewHttpValue("Cache-Control", "no-cache")); AddHttpValue(h, NewHttpValue("Host", data->HeaderHostName)); if (IsEmptyStr(header_name) == false && IsEmptyStr(header_value) == false) { AddHttpValue(h, NewHttpValue(header_name, header_value)); } if (IsEmptyStr(data->Referer) == false) { AddHttpValue(h, NewHttpValue("Referer", data->Referer)); } if (StrCmpi(data->Method, WPC_HTTP_POST_NAME) == 0) { ToStr(len_str, StrLen(post_data)); AddHttpValue(h, NewHttpValue("Content-Type", "application/x-www-form-urlencoded")); AddHttpValue(h, NewHttpValue("Content-Length", len_str)); } if (IsEmptyStr(data->AdditionalHeaderName) == false && IsEmptyStr(data->AdditionalHeaderValue) == false) { AddHttpValue(h, NewHttpValue(data->AdditionalHeaderName, data->AdditionalHeaderValue)); } if (use_http_proxy) { AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive")); if (IsEmptyStr(setting->ProxyUsername) == false || IsEmptyStr(setting->ProxyPassword) == false) { char auth_tmp_str[MAX_SIZE], auth_b64_str[MAX_SIZE * 2]; char basic_str[MAX_SIZE * 2]; // Generate the authentication string Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s", setting->ProxyUsername, setting->ProxyPassword); // Base64 encode Zero(auth_b64_str, sizeof(auth_b64_str)); Encode64(auth_b64_str, auth_tmp_str); Format(basic_str, sizeof(basic_str), "Basic %s", auth_b64_str); AddHttpValue(h, NewHttpValue("Proxy-Authorization", basic_str)); } } send_str = HttpHeaderToStr(h); FreeHttpHeader(h); send_buf = NewBuf(); WriteBuf(send_buf, send_str, StrLen(send_str)); Free(send_str); // Append to the sending data in the case of POST if (StrCmpi(data->Method, WPC_HTTP_POST_NAME) == 0) { WriteBuf(send_buf, post_data, StrLen(post_data)); } // Send if (SendAll(s, send_buf->Buf, send_buf->Size, s->SecureMode) == false) { Disconnect(s); ReleaseSock(s); FreeBuf(send_buf); *error_code = ERR_DISCONNECTED; return NULL; } FreeBuf(send_buf); CONT: // Receive h = RecvHttpHeader(s); if (h == NULL) { Disconnect(s); ReleaseSock(s); *error_code = ERR_DISCONNECTED; return NULL; } http_error_code = 0; if (StrLen(h->Method) == 8) { if (Cmp(h->Method, "HTTP/1.", 7) == 0) { http_error_code = ToInt(h->Target); } } *error_code = ERR_NO_ERROR; switch (http_error_code) { case 401: case 407: // Proxy authentication error *error_code = ERR_PROXY_AUTH_FAILED; break; case 404: // 404 File Not Found *error_code = ERR_OBJECT_NOT_FOUND; break; case 100: // Continue num_continue++; if (num_continue >= 10) { goto DEF; } FreeHttpHeader(h); goto CONT; case 200: // Success break; default: // Protocol error DEF: *error_code = ERR_PROTOCOL_ERROR; break; } if (*error_code != ERR_NO_ERROR) { // An error has occured Disconnect(s); ReleaseSock(s); FreeHttpHeader(h); return NULL; } // Get the length of the content content_len = GetContentLength(h); if (max_recv_size != 0) { content_len = MIN(content_len, max_recv_size); } FreeHttpHeader(h); socket_buffer = Malloc(socket_buffer_size); // Receive the content recv_buf = NewBuf(); while (true) { UINT recvsize = MIN(socket_buffer_size, content_len - recv_buf->Size); UINT size; if (recv_callback != NULL) { if (recv_callback(recv_callback_param, content_len, recv_buf->Size, recv_buf) == false) { // Cancel the reception *error_code = ERR_USER_CANCEL; goto RECV_CANCEL; } } if (recvsize == 0) { break; } size = Recv(s, socket_buffer, recvsize, s->SecureMode); if (size == 0) { // Disconnected *error_code = ERR_DISCONNECTED; RECV_CANCEL: FreeBuf(recv_buf); Free(socket_buffer); Disconnect(s); ReleaseSock(s); return NULL; } WriteBuf(recv_buf, socket_buffer, size); } SeekBuf(recv_buf, 0, 0); Free(socket_buffer); Disconnect(s); ReleaseSock(s); // Transmission return recv_buf; }
PRInt32 nsMailboxProtocol::ReadMessageResponse(nsIInputStream * inputStream, PRUint32 sourceOffset, PRUint32 length) { char *line = nsnull; PRUint32 status = 0; nsresult rv = NS_OK; mCurrentProgress += length; // if we are doing a move or a copy, forward the data onto the copy handler... // if we want to display the message then parse the incoming data... if (m_channelListener) { // just forward the data we read in to the listener... rv = m_channelListener->OnDataAvailable(this, m_channelContext, inputStream, sourceOffset, length); } else { PRBool pauseForMoreData = PR_FALSE; PRBool canonicalLineEnding = PR_FALSE; nsCOMPtr<nsIMsgMessageUrl> msgurl = do_QueryInterface(m_runningUrl); if (msgurl) msgurl->GetCanonicalLineEnding(&canonicalLineEnding); do { char *saveLine; saveLine = line = m_lineStreamBuffer->ReadNextLine(inputStream, status, pauseForMoreData); if (!line || (line[0] == '.' && line[1] == 0)) { // we reached the end of the message! ClearFlag(MAILBOX_PAUSE_FOR_READ); } // otherwise process the line else { if (line[0] == '.') line++; // skip over the '.' /* When we're sending this line to a converter (ie, it's a message/rfc822) use the local line termination convention, not CRLF. This makes text articles get saved with the local line terminators. Since SMTP and NNTP mandate the use of CRLF, it is expected that the local system will convert that to the local line terminator as it is read. */ // mscott - the firstline hack is aimed at making sure we don't write // out the dummy header when we are trying to display the message. // The dummy header is the From line with the date tag on it. if (m_msgFileOutputStream && TestFlag(MAILBOX_MSG_PARSE_FIRST_LINE)) { PRUint32 count = 0; if (line) rv = m_msgFileOutputStream->Write(line, PL_strlen(line), &count); if (NS_FAILED(rv)) break; if (canonicalLineEnding) rv = m_msgFileOutputStream->Write(CRLF, 2, &count); else rv = m_msgFileOutputStream->Write(MSG_LINEBREAK, MSG_LINEBREAK_LEN, &count); if (NS_FAILED(rv)) break; } else SetFlag(MAILBOX_MSG_PARSE_FIRST_LINE); } PR_Free(saveLine); } while (line && !pauseForMoreData); } SetFlag(MAILBOX_PAUSE_FOR_READ); // wait for more data to become available... if (mProgressEventSink) { PRInt32 contentLength = 0; GetContentLength(&contentLength); // XXX 64-bit mProgressEventSink->OnProgress(this, m_channelContext, nsUint64(mCurrentProgress), nsUint64(contentLength)); } if (NS_FAILED(rv)) return -1; return 0; }
//////////////////////////////////////////////////////////////////////////////////////////// /// Extract the data fields from the header buffer and populate the member data fields. /// \param pReceiveBuffer The input data /// \return True if suucess, False if fail. //////////////////////////////////////////////////////////////////////////////////////////// bool HTTPRequestHeader::ExtractHeaderData(char* pReceiveBuffer) { char* pos = NULL; char* context = NULL; //////////////////////////////////////////////////////////////////////// // tokenize the buffer for method pos = strtok_s(pReceiveBuffer, " ", &context); if (pos == NULL) { Log(logERROR, "Failed to tokenize HTTPHeader for method\n"); return false; } // get the method (GET or POST) size_t methodLen = strlen(pos); if (methodLen > SMALL_BUFFER_SIZE) { Log(logERROR, "HTTP method is larger than buffer: %u > %u\n", methodLen, SMALL_BUFFER_SIZE); return false; } strncpy_s(m_httpHeaderData.method, SMALL_BUFFER_SIZE, pos, SMALL_BUFFER_SIZE); //////////////////////////////////////////////////////////////////////// //tokenize the buffer for url pos = strtok_s(NULL, " ", &context); if (pos == NULL) { Log(logERROR, "Failed to tokenize HTTPHeader for url\n"); return false; } // get the url size_t urlLen = strlen(pos); if (urlLen > COMM_MAX_URL_SIZE) { Log(logERROR, "HTTP url is larger than buffer: %u > %u\n", urlLen, COMM_MAX_URL_SIZE); return false; } strncpy_s(m_httpHeaderData.url, COMM_MAX_URL_SIZE, pos, COMM_MAX_URL_SIZE); //////////////////////////////////////////////////////////////////////// // tokenize the buffer for version pos = strtok_s(NULL, "\r", &context); if (pos == NULL) { Log(logERROR, "Failed to tokenize HTTPHeader for version\n"); return false; } // get the version size_t verLen = strlen(pos); if (verLen > SMALL_BUFFER_SIZE) { Log(logERROR, "HTTP version string is larger than buffer: %u > %u\n", verLen, SMALL_BUFFER_SIZE); return false; } strncpy_s(m_httpHeaderData.httpversion, SMALL_BUFFER_SIZE, pos, SMALL_BUFFER_SIZE); //////////////////////////////////////////////////////////////////////// // tokenize the buffer for content pos = strtok_s(NULL, "\r", &context); if (pos == NULL) { Log(logERROR, "Failed to tokenize HTTPHeader for Content-Type\n"); return false; } // Currently we do nothing with content type. //////////////////////////////////////////////////////////////////////// // tokenize the buffer for Host pos = strtok_s(NULL, "\r", &context); if (pos == NULL) { Log(logERROR, "Failed to tokenize HTTPHeader for Host\n"); return false; } // Currently we do nothing with Host. //////////////////////////////////////////////////////////////////////// // Check to see if POST method is being used to send anay data. if (strcmp(m_httpHeaderData.method, "POST") == 0) { // If so, record how much data is being sent. m_httpHeaderData.nPostDataSize = GetContentLength(context); } return true; }
//============================================================================= // Build Header //----------------------------------------------------------------------------- // RFC 2616 / 6 Response (Header) // // The first line of a Response message is the Status-Line, consisting // of the protocol version followed by a numeric status code and its // associated textual phrase, with each element separated by SP // characters. No CR or LF is allowed except in the final CRLF sequence. // // Response =Status-Line ; generated by SendHeader // *(( general-header // | response-header // | entity-header ) CRLF) // CRLF ; generated by SendHeader // [ message-body ] ; by HOOK Handling Loop or Sendfile // // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF ; generated by SendHeader // // general-header = Cache-Control ; not implemented // | Connection ; implemented // | Date ; implemented // | Pragma ; not implemented // | Trailer ; not implemented // | Transfer-Encoding ; not implemented // | Upgrade ; not implemented // | Via ; not implemented // | Warning ; not implemented // // response-header = Accept-Ranges ; not implemented // | Age ; not implemented // | ETag ; not implemented // | Location ; implemented (redirection / Object moved) // | Proxy-Authenticate ; not implemented // | Retry-After ; not implemented // | Server ; implemented // | Vary ; not implemented // | WWW-Authenticate ; implemented (by mod_auth and SendHeader) // // entity-header = Allow ; not implemented // | Content-Encoding ; not implemented // | Content-Language ; not implemented // | Content-Length ; implemented // | Content-Location ; not implemented // | Content-MD5 ; not implemented // | Content-Range ; not implemented // | Content-Type ; implemented // | Expires ; not implemented // | Last-Modified ; implemented for static files // | extension-header // // extension-header = message-header //============================================================================= std::string CyhookHandler::BuildHeader(bool cache) { std::string result = ""; const char *responseString = ""; const char *infoString = 0; // get Info Index for (unsigned int i = 0; i < (sizeof(httpResponseNames) / sizeof(httpResponseNames[0])); i++) if (httpResponseNames[i].type == httpStatus) { responseString = httpResponseNames[i].name; infoString = httpResponseNames[i].info; break; } // print Status-line result = string_printf(HTTP_PROTOCOL " %d %s\r\nContent-Type: %s\r\n",httpStatus, responseString, ResponseMimeType.c_str()); log_level_printf(2, "Respose: HTTP/1.1 %d %s\r\nContent-Type: %s\r\n", httpStatus, responseString, ResponseMimeType.c_str()); switch (httpStatus) { case HTTP_UNAUTHORIZED: result += "WWW-Authenticate: Basic realm=\""; result += AUTH_NAME_MSG "\r\n"; break; case HTTP_MOVED_TEMPORARILY: case HTTP_MOVED_PERMANENTLY: // Status HTTP_*_TEMPORARILY (redirection) result += string_printf("Location: %s\r\n", NewURL.c_str()); // NO break HERE !!! default: time_t timer = time(0); char timeStr[80]; // cache if (!cache && (HookVarList["CacheCategory"]).empty()) result += "Cache-Control: no-cache\r\n"; else { time_t x_time = time(NULL); struct tm *ptm = gmtime(&x_time); ptm->tm_mday += 1; x_time = mktime(ptm); strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&x_time)); result += string_printf("Expires: %s\r\n", timeStr); } result += "Server: " WEBSERVERNAME "\r\n"; // actual date strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer)); result += string_printf("Date: %s\r\n", timeStr); // connection type #ifdef Y_CONFIG_FEATURE_KEEP_ALIVE if(keep_alive) result += "Connection: keep-alive\r\n"; else result += "Connection: close\r\n"; #else result += "Connection: close\r\n"; #endif // gzipped ? if (UrlData["fileext"] == "gz") result += "Content-Encoding: gzip\r\n"; // content-len, last-modified if (httpStatus == HTTP_NOT_MODIFIED || httpStatus == HTTP_NOT_FOUND) result += "Content-Length: 0\r\n"; else if (GetContentLength() > 0) { time_t mod_time = time(NULL); if (LastModified != (time_t) - 1) mod_time = LastModified; strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&mod_time)); result += string_printf( "Last-Modified: %s\r\nContent-Length: %ld\r\n", timeStr, GetContentLength()); } result += "\r\n"; // End of Header break; } // Body if (Method != M_HEAD) switch (httpStatus) { case HTTP_OK: case HTTP_NOT_MODIFIED: case HTTP_CONTINUE: case HTTP_ACCEPTED: case HTTP_NO_CONTENT: case HTTP_NOT_FOUND: case HTTP_INTERNAL_SERVER_ERROR: break; case HTTP_MOVED_TEMPORARILY: case HTTP_MOVED_PERMANENTLY: result += "<html><head><title>Object moved</title></head><body>"; result += string_printf( "302 : Object moved.<br/>If you dont get redirected click <a href=\"%s\">here</a></body></html>\n", NewURL.c_str()); break; default: // Error pages break; } return result; }