It provides the helper routines to parse the HTTP message byte stream.\r
\r
Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>\r
-(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+(C) Copyright 2016 - 2020 Hewlett Packard Enterprise Development LP<BR>\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
CHAR8 *Char;\r
UINTN RemainderLengthInThis;\r
UINTN LengthForCallback;\r
+ UINTN PortionLength;\r
EFI_STATUS Status;\r
HTTP_BODY_PARSER *Parser;\r
\r
//\r
// Identity transfer-coding, just notify user to save the body data.\r
//\r
+ PortionLength = MIN (\r
+ BodyLength,\r
+ Parser->ContentLength - Parser->ParsedBodyLength\r
+ );\r
+ if (PortionLength == 0) {\r
+ //\r
+ // Got BodyLength, but no ContentLength. Use BodyLength.\r
+ //\r
+ PortionLength = BodyLength;\r
+ Parser->ContentLength = PortionLength;\r
+ }\r
+\r
if (Parser->Callback != NULL) {\r
Status = Parser->Callback (\r
BodyParseEventOnData,\r
Char,\r
- MIN (BodyLength, Parser->ContentLength - Parser->ParsedBodyLength),\r
+ PortionLength,\r
Parser->Context\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
}\r
- Char += MIN (BodyLength, Parser->ContentLength - Parser->ParsedBodyLength);\r
- Parser->ParsedBodyLength += MIN (BodyLength, Parser->ContentLength - Parser->ParsedBodyLength);\r
+ Char += PortionLength;\r
+ Parser->ParsedBodyLength += PortionLength;\r
if (Parser->ParsedBodyLength == Parser->ContentLength) {\r
Parser->State = BodyParserComplete;\r
if (Parser->Callback != NULL) {\r
/**\r
Free existing HeaderFields.\r
\r
- @param[in] HeaderFields Pointer to array of key/value header pairs waitting for free.\r
+ @param[in] HeaderFields Pointer to array of key/value header pairs waiting for free.\r
@param[in] FieldCount The number of header pairs in HeaderFields.\r
\r
**/\r
the HTTP request message.\r
@param[in] Url The URL of a remote host.\r
@param[out] RequestMsg Pointer to the created HTTP request message.\r
- NULL if any error occured.\r
+ NULL if any error occurred.\r
@param[out] RequestMsgSize Size of the RequestMsg (in bytes).\r
\r
@retval EFI_SUCCESS If HTTP request string was created successfully.\r
return TRUE;\r
}\r
\r
+\r
+/**\r
+ Create a HTTP_IO_HEADER to hold the HTTP header items.\r
+\r
+ @param[in] MaxHeaderCount The maximun number of HTTP header in this holder.\r
+\r
+ @return A pointer of the HTTP header holder or NULL if failed.\r
+\r
+**/\r
+HTTP_IO_HEADER *\r
+HttpIoCreateHeader (\r
+ UINTN MaxHeaderCount\r
+ )\r
+{\r
+ HTTP_IO_HEADER *HttpIoHeader;\r
+\r
+ if (MaxHeaderCount == 0) {\r
+ return NULL;\r
+ }\r
+\r
+ HttpIoHeader = AllocateZeroPool (sizeof (HTTP_IO_HEADER) + MaxHeaderCount * sizeof (EFI_HTTP_HEADER));\r
+ if (HttpIoHeader == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ HttpIoHeader->MaxHeaderCount = MaxHeaderCount;\r
+ HttpIoHeader->Headers = (EFI_HTTP_HEADER *) (HttpIoHeader + 1);\r
+\r
+ return HttpIoHeader;\r
+}\r
+\r
+/**\r
+ Destroy the HTTP_IO_HEADER and release the resources.\r
+\r
+ @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed.\r
+\r
+**/\r
+VOID\r
+HttpIoFreeHeader (\r
+ IN HTTP_IO_HEADER *HttpIoHeader\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ if (HttpIoHeader != NULL) {\r
+ if (HttpIoHeader->HeaderCount != 0) {\r
+ for (Index = 0; Index < HttpIoHeader->HeaderCount; Index++) {\r
+ FreePool (HttpIoHeader->Headers[Index].FieldName);\r
+ ZeroMem (HttpIoHeader->Headers[Index].FieldValue, AsciiStrSize (HttpIoHeader->Headers[Index].FieldValue));\r
+ FreePool (HttpIoHeader->Headers[Index].FieldValue);\r
+ }\r
+ }\r
+ FreePool (HttpIoHeader);\r
+ }\r
+}\r
+\r
+/**\r
+ Set or update a HTTP header with the field name and corresponding value.\r
+\r
+ @param[in] HttpIoHeader Point to the HTTP header holder.\r
+ @param[in] FieldName Null terminated string which describes a field name.\r
+ @param[in] FieldValue Null terminated string which describes the corresponding field value.\r
+\r
+ @retval EFI_SUCCESS The HTTP header has been set or updated.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation.\r
+ @retval Other Unexpected error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpIoSetHeader (\r
+ IN HTTP_IO_HEADER *HttpIoHeader,\r
+ IN CHAR8 *FieldName,\r
+ IN CHAR8 *FieldValue\r
+ )\r
+{\r
+ EFI_HTTP_HEADER *Header;\r
+ UINTN StrSize;\r
+ CHAR8 *NewFieldValue;\r
+\r
+ if (HttpIoHeader == NULL || FieldName == NULL || FieldValue == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Header = HttpFindHeader (HttpIoHeader->HeaderCount, HttpIoHeader->Headers, FieldName);\r
+ if (Header == NULL) {\r
+ //\r
+ // Add a new header.\r
+ //\r
+ if (HttpIoHeader->HeaderCount >= HttpIoHeader->MaxHeaderCount) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Header = &HttpIoHeader->Headers[HttpIoHeader->HeaderCount];\r
+\r
+ StrSize = AsciiStrSize (FieldName);\r
+ Header->FieldName = AllocatePool (StrSize);\r
+ if (Header->FieldName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (Header->FieldName, FieldName, StrSize);\r
+ Header->FieldName[StrSize -1] = '\0';\r
+\r
+ StrSize = AsciiStrSize (FieldValue);\r
+ Header->FieldValue = AllocatePool (StrSize);\r
+ if (Header->FieldValue == NULL) {\r
+ FreePool (Header->FieldName);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (Header->FieldValue, FieldValue, StrSize);\r
+ Header->FieldValue[StrSize -1] = '\0';\r
+\r
+ HttpIoHeader->HeaderCount++;\r
+ } else {\r
+ //\r
+ // Update an existing one.\r
+ //\r
+ StrSize = AsciiStrSize (FieldValue);\r
+ NewFieldValue = AllocatePool (StrSize);\r
+ if (NewFieldValue == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (NewFieldValue, FieldValue, StrSize);\r
+ NewFieldValue[StrSize -1] = '\0';\r
+\r
+ if (Header->FieldValue != NULL) {\r
+ FreePool (Header->FieldValue);\r
+ }\r
+ Header->FieldValue = NewFieldValue;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r