static ParsedContentRange parseContentRangeInHeader(const HTTPHeaderMap& headers) { String contentRangeValue = headers.get(HTTPHeaderName::ContentRange); if (contentRangeValue.isEmpty()) return ParsedContentRange(); return ParsedContentRange(contentRangeValue); }
NPError PluginView::handlePost(const char* url, const char* target, uint32 len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders) { if (!url || !len || !buf) return NPERR_INVALID_PARAM; FrameLoadRequest frameLoadRequest; HTTPHeaderMap headerFields; Vector<char> buffer; if (file) { NPError readResult = handlePostReadFile(buffer, len, buf); if(readResult != NPERR_NO_ERROR) return readResult; } else { buffer.resize(len); memcpy(buffer.data(), buf, len); } const char* postData = buffer.data(); int postDataLength = buffer.size(); if (allowHeaders) { if (startsWithBlankLine(buffer)) { postData++; postDataLength--; } else { int location = locationAfterFirstBlankLine(buffer); if (location != -1) { // If the blank line is somewhere in the middle of the buffer, everything before is the header headerFields = parseRFC822HeaderFields(buffer, location); unsigned dataLength = buffer.size() - location; // Sometimes plugins like to set Content-Length themselves when they post, // but WebFoundation does not like that. So we will remove the header // and instead truncate the data to the requested length. String contentLength = headerFields.get("Content-Length"); if (!contentLength.isNull()) dataLength = min(contentLength.toInt(), (int)dataLength); headerFields.remove("Content-Length"); postData += location; postDataLength = dataLength; } } } frameLoadRequest.resourceRequest().setHTTPMethod("POST"); frameLoadRequest.resourceRequest().setURL(makeURL(m_baseURL, url)); frameLoadRequest.resourceRequest().addHTTPHeaderFields(headerFields); frameLoadRequest.resourceRequest().setHTTPBody(FormData::create(postData, postDataLength)); frameLoadRequest.setFrameName(target); return load(frameLoadRequest, sendNotification, notifyData); }
static std::optional<std::chrono::system_clock::time_point> parseDateValueInHeader(const HTTPHeaderMap& headers, HTTPHeaderName headerName) { String headerValue = headers.get(headerName); if (headerValue.isEmpty()) return { }; // This handles all date formats required by RFC2616: // Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format return parseHTTPDate(headerValue); }
static NPError parsePostBuffer(bool isFile, const char *buffer, uint32_t length, bool parseHeaders, HTTPHeaderMap& headerFields, Vector<uint8_t>& bodyData) { RefPtr<SharedBuffer> fileContents; const char* postBuffer = 0; uint32_t postBufferSize = 0; if (isFile) { fileContents = SharedBuffer::createWithContentsOfFile(String::fromUTF8(buffer)); if (!fileContents) return NPERR_FILE_NOT_FOUND; postBuffer = fileContents->data(); postBufferSize = fileContents->size(); // FIXME: The NPAPI spec states that the file should be deleted here. } else { postBuffer = buffer; postBufferSize = length; } if (parseHeaders) { if (startsWithBlankLine(postBuffer, postBufferSize)) { postBuffer++; postBufferSize--; } else { int location = locationAfterFirstBlankLine(postBuffer, postBufferSize); if (location != -1) { // If the blank line is somewhere in the middle of the buffer, everything before is the header headerFields = parseRFC822HeaderFields(postBuffer, location); unsigned dataLength = postBufferSize - location; // Sometimes plugins like to set Content-Length themselves when they post, // but WebFoundation does not like that. So we will remove the header // and instead truncate the data to the requested length. String contentLength = headerFields.get("Content-Length"); if (!contentLength.isNull()) dataLength = min(contentLength.toInt(), (int)dataLength); headerFields.remove("Content-Length"); postBuffer += location; postBufferSize = dataLength; } } } ASSERT(bodyData.isEmpty()); bodyData.append(postBuffer, postBufferSize); return NPERR_NO_ERROR; }
static double parseDateValueInHeader(const HTTPHeaderMap& headers, const AtomicString& headerName) { const AtomicString& headerValue = headers.get(headerName); if (headerValue.isEmpty()) return std::numeric_limits<double>::quiet_NaN(); // This handles all date formats required by RFC2616: // Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format double dateInMilliseconds = parseDate(headerValue); if (!std::isfinite(dateInMilliseconds)) return std::numeric_limits<double>::quiet_NaN(); return dateInMilliseconds / 1000; }
static HTTPHeaderMap parseRFC822HeaderFields(const char* bytes, unsigned length) { String lastHeaderKey; HTTPHeaderMap headerFields; // Loop over lines until we're past the header, or we can't find any more end-of-lines while (const char* endOfLine = findEndOfLine(bytes, length)) { const char* line = bytes; int lineLength = endOfLine - bytes; // Move bytes to the character after the terminator as returned by findEndOfLine. bytes = endOfLine + 1; if ((*endOfLine == '\r') && (*bytes == '\n')) bytes++; // Safe since findEndOfLine won't return a spanning CRLF. length -= (bytes - line); if (!lineLength) { // Blank line; we're at the end of the header break; } if (*line == ' ' || *line == '\t') { // Continuation of the previous header if (lastHeaderKey.isNull()) { // malformed header; ignore it and continue continue; } // Merge the continuation of the previous header String currentValue = headerFields.get(lastHeaderKey); String newValue(line, lineLength); headerFields.set(lastHeaderKey, currentValue + newValue); } else { // Brand new header const char* colon = line; while (*colon != ':' && colon != endOfLine) colon++; if (colon == endOfLine) { // malformed header; ignore it and continue continue; } lastHeaderKey = capitalizeRFC822HeaderFieldName(String(line, colon - line)); String value; for (colon++; colon != endOfLine; colon++) { if (*colon != ' ' && *colon != '\t') break; } if (colon == endOfLine) value = ""; else value = String(colon, endOfLine - colon); String oldValue = headerFields.get(lastHeaderKey); if (!oldValue.isNull()) value = oldValue + ", " + value; headerFields.set(lastHeaderKey, value); } } return headerFields; }
static inline HTTPHeaderMap parseRFC822HeaderFields(const Vector<char>& buffer, unsigned length) { const char* bytes = buffer.data(); const char* eol; String lastKey; HTTPHeaderMap headerFields; // Loop ove rlines until we're past the header, or we can't find any more end-of-lines while ((eol = findEOL(bytes, length))) { const char* line = bytes; int lineLength = eol - bytes; // Move bytes to the character after the terminator as returned by findEOL. bytes = eol + 1; if ((*eol == '\r') && (*bytes == '\n')) bytes++; // Safe since findEOL won't return a spanning CRLF. length -= (bytes - line); if (lineLength == 0) // Blank line; we're at the end of the header break; else if (*line == ' ' || *line == '\t') { // Continuation of the previous header if (lastKey.isNull()) { // malformed header; ignore it and continue continue; } else { // Merge the continuation of the previous header String currentValue = headerFields.get(lastKey); String newValue(line, lineLength); headerFields.set(lastKey, currentValue + newValue); } } else { // Brand new header const char* colon; for (colon = line; *colon != ':' && colon != eol; colon++) { // empty loop } if (colon == eol) // malformed header; ignore it and continue continue; else { lastKey = capitalizeRFC822HeaderFieldName(String(line, colon - line)); String value; for (colon++; colon != eol; colon++) { if (*colon != ' ' && *colon != '\t') break; } if (colon == eol) value = ""; else value = String(colon, eol - colon); String oldValue = headerFields.get(lastKey); if (!oldValue.isNull()) { String tmp = oldValue; tmp += ", "; tmp += value; value = tmp; } headerFields.set(lastKey, value); } } } return headerFields; }