]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c
NetworkPkg/DxeHttpLib: Migrate HTTP header manipulation APIs
[mirror_edk2.git] / NetworkPkg / Library / DxeHttpLib / DxeHttpLib.c
index 8b74554cd96157b2cb788b1c32f9c50a6664ef9f..0bbe0fc5d7ce1fa61dcedc853a96b68a280a05eb 100644 (file)
@@ -3,7 +3,7 @@
   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
@@ -1122,6 +1122,7 @@ HttpParseMessageBody (
   CHAR8                 *Char;\r
   UINTN                 RemainderLengthInThis;\r
   UINTN                 LengthForCallback;\r
+  UINTN                 PortionLength;\r
   EFI_STATUS            Status;\r
   HTTP_BODY_PARSER      *Parser;\r
 \r
@@ -1173,19 +1174,31 @@ HttpParseMessageBody (
       //\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
@@ -1677,7 +1690,7 @@ HttpGetFieldNameAndValue (
 /**\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
@@ -1717,7 +1730,7 @@ HttpFreeHeaderFields (
                                   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
@@ -2082,3 +2095,135 @@ HttpIsValidHttpHeader (
   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