]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/DxeHttpLib/DxeHttpLib.c
MdeModulePkg/DxeHttpLib: Refine some coding style.
[mirror_edk2.git] / MdeModulePkg / Library / DxeHttpLib / DxeHttpLib.c
index 662c40c644b1e8f69f97f46915e0dff01b6ce4ea..9774670d7c8f2632646586ca2eaf77fc04caa2f9 100644 (file)
@@ -2,7 +2,7 @@
   This library is used to share code between UEFI network stack modules.\r
   It provides the helper routines to parse the HTTP message byte stream.\r
 \r
-Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
@@ -56,7 +56,8 @@ UriPercentDecode (
   HexStr[2] = '\0';\r
   while (Index < BufferLength) {\r
     if (Buffer[Index] == '%') {\r
-      if (!NET_IS_HEX_CHAR (Buffer[Index+1]) || !NET_IS_HEX_CHAR (Buffer[Index+2])) {\r
+      if (Index + 1 >= BufferLength || Index + 2 >= BufferLength || \r
+          !NET_IS_HEX_CHAR (Buffer[Index+1]) || !NET_IS_HEX_CHAR (Buffer[Index+2])) {\r
         return EFI_INVALID_PARAMETER;\r
       }\r
       HexStr[0] = Buffer[Index+1];\r
@@ -155,7 +156,7 @@ NetHttpParseAuthorityChar (
   @param[in, out]  UrlParser      Pointer to the buffer of the parse result.\r
 \r
   @retval EFI_SUCCESS             Successfully parse the authority.\r
-  @retval Other                   Error happened.\r
+  @retval EFI_INVALID_PARAMETER   The Url is invalid to parse the authority component.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -372,6 +373,8 @@ HttpParseUrl (
   BOOLEAN               FoundAt;\r
   EFI_STATUS            Status;\r
   HTTP_URL_PARSER       *Parser;\r
+\r
+  Parser = NULL;\r
   \r
   if (Url == NULL || Length == 0 || UrlParser == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -396,12 +399,13 @@ HttpParseUrl (
   FoundAt = FALSE;\r
   for (Char = Url; Char < Url + Length; Char++) {\r
     //\r
-    // Update state machine accoring to next char.\r
+    // Update state machine according to next char.\r
     //\r
     State = NetHttpParseUrlChar (*Char, State);\r
 \r
     switch (State) {\r
     case UrlParserStateMax:\r
+      FreePool (Parser);\r
       return EFI_INVALID_PARAMETER;\r
       \r
     case UrlParserSchemeColon:\r
@@ -464,6 +468,7 @@ HttpParseUrl (
   if ((Parser->FieldBitMap & BIT (HTTP_URI_FIELD_AUTHORITY)) != 0) {\r
     Status = NetHttpParseAuthority (Url, FoundAt, Parser);\r
     if (EFI_ERROR (Status)) {\r
+      FreePool (Parser);\r
       return Status;\r
     }\r
   }\r
@@ -505,7 +510,7 @@ HttpUrlGetHostName (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Parser = (HTTP_URL_PARSER*) UrlParser;\r
+  Parser = (HTTP_URL_PARSER *) UrlParser;\r
 \r
   if ((Parser->FieldBitMap & BIT (HTTP_URI_FIELD_HOST)) == 0) {\r
     return EFI_NOT_FOUND;\r
@@ -523,6 +528,7 @@ HttpUrlGetHostName (
              &ResultLength\r
              );\r
   if (EFI_ERROR (Status)) {\r
+    FreePool (Name);\r
     return Status;\r
   }\r
 \r
@@ -564,10 +570,10 @@ HttpUrlGetIp4 (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Parser = (HTTP_URL_PARSER*) UrlParser;\r
+  Parser = (HTTP_URL_PARSER *) UrlParser;\r
 \r
   if ((Parser->FieldBitMap & BIT (HTTP_URI_FIELD_HOST)) == 0) {\r
-    return EFI_INVALID_PARAMETER;\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
   Ip4String = AllocatePool (Parser->FieldData[HTTP_URI_FIELD_HOST].Length + 1);\r
@@ -582,6 +588,7 @@ HttpUrlGetIp4 (
              &ResultLength\r
              );\r
   if (EFI_ERROR (Status)) {\r
+    FreePool (Ip4String);\r
     return Status;\r
   }\r
 \r
@@ -626,10 +633,10 @@ HttpUrlGetIp6 (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Parser = (HTTP_URL_PARSER*) UrlParser;\r
+  Parser = (HTTP_URL_PARSER *) UrlParser;\r
 \r
   if ((Parser->FieldBitMap & BIT (HTTP_URI_FIELD_HOST)) == 0) {\r
-    return EFI_INVALID_PARAMETER;\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
   //\r
@@ -657,6 +664,7 @@ HttpUrlGetIp6 (
              &ResultLength\r
              );\r
   if (EFI_ERROR (Status)) {\r
+    FreePool (Ip6String);\r
     return Status;\r
   }\r
   \r
@@ -690,19 +698,24 @@ HttpUrlGetPort (
      OUT  UINT16             *Port\r
   )\r
 {\r
-  CHAR8         *PortString;\r
-  EFI_STATUS    Status;\r
-  UINT32        ResultLength;\r
+  CHAR8                *PortString;\r
+  EFI_STATUS           Status;\r
+  UINTN                Index;\r
+  UINTN                Data;\r
+  UINT32               ResultLength;\r
   HTTP_URL_PARSER      *Parser;\r
 \r
   if (Url == NULL || UrlParser == NULL || Port == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Parser = (HTTP_URL_PARSER*) UrlParser;\r
+  *Port = 0;\r
+  Index = 0;\r
+\r
+  Parser = (HTTP_URL_PARSER *) UrlParser;\r
 \r
   if ((Parser->FieldBitMap & BIT (HTTP_URI_FIELD_PORT)) == 0) {\r
-    return EFI_INVALID_PARAMETER;\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
   PortString = AllocatePool (Parser->FieldData[HTTP_URI_FIELD_PORT].Length + 1);\r
@@ -717,13 +730,31 @@ HttpUrlGetPort (
              &ResultLength\r
              );\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto ON_EXIT;\r
   }\r
 \r
   PortString[ResultLength] = '\0';\r
-  *Port = (UINT16) AsciiStrDecimalToUintn (Url + Parser->FieldData[HTTP_URI_FIELD_PORT].Offset);\r
 \r
-  return  EFI_SUCCESS;\r
+  while (Index < ResultLength) {\r
+    if (!NET_IS_DIGIT (PortString[Index])) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+    Index ++;\r
+  }\r
+\r
+  Status =  AsciiStrDecimalToUintnS (Url + Parser->FieldData[HTTP_URI_FIELD_PORT].Offset, (CHAR8 **) NULL, &Data);\r
+\r
+  if (Data > HTTP_URI_PORT_MAX_NUM) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  *Port = (UINT16) Data;\r
+\r
+ON_EXIT:\r
+  FreePool (PortString);\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -759,7 +790,7 @@ HttpUrlGetPath (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Parser = (HTTP_URL_PARSER*) UrlParser;\r
+  Parser = (HTTP_URL_PARSER *) UrlParser;\r
 \r
   if ((Parser->FieldBitMap & BIT (HTTP_URI_FIELD_PATH)) == 0) {\r
     return EFI_NOT_FOUND;\r
@@ -777,6 +808,7 @@ HttpUrlGetPath (
              &ResultLength\r
              );\r
   if (EFI_ERROR (Status)) {\r
+    FreePool (PathStr);\r
     return Status;\r
   }\r
 \r
@@ -932,8 +964,7 @@ HttpIoParseContentLengthHeader (
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  *ContentLength = AsciiStrDecimalToUintn (Header->FieldValue);\r
-  return EFI_SUCCESS;\r
+  return AsciiStrDecimalToUintnS (Header->FieldValue, (CHAR8 **) NULL, ContentLength);\r
 }\r
 \r
 /**\r
@@ -1103,7 +1134,8 @@ HttpInitMsgParser (
 \r
   @retval EFI_SUCCESS                Successfully parse the message-body.\r
   @retval EFI_INVALID_PARAMETER      MsgParser is NULL or Body is NULL or BodyLength is 0.\r
-  @retval Others                     Operation aborted.\r
+  @retval EFI_ABORTED                Operation aborted.\r
+  @retval Other                      Error happened while parsing message body.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1128,17 +1160,17 @@ HttpParseMessageBody (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Parser = (HTTP_BODY_PARSER*) MsgParser;\r
+  Parser = (HTTP_BODY_PARSER *) MsgParser;\r
 \r
   if (Parser->IgnoreBody) {\r
     Parser->State = BodyParserComplete;\r
     if (Parser->Callback != NULL) {\r
       Status = Parser->Callback (\r
-                 BodyParseEventOnComplete,\r
-                 Body,\r
-                 0,\r
-                 Parser->Context\r
-                 );\r
+                         BodyParseEventOnComplete,\r
+                         Body,\r
+                         0,\r
+                         Parser->Context\r
+                         );\r
       if (EFI_ERROR (Status)) {\r
         return Status;\r
       }\r
@@ -1170,11 +1202,11 @@ HttpParseMessageBody (
       //\r
       if (Parser->Callback != NULL) {\r
         Status = Parser->Callback (\r
-                   BodyParseEventOnData,\r
-                   Char,\r
-                   MIN (BodyLength, Parser->ContentLength - Parser->ParsedBodyLength),\r
-                   Parser->Context\r
-                   );\r
+                           BodyParseEventOnData,\r
+                           Char,\r
+                           MIN (BodyLength, Parser->ContentLength - Parser->ParsedBodyLength),\r
+                           Parser->Context\r
+                           );\r
         if (EFI_ERROR (Status)) {\r
           return Status;\r
         }\r
@@ -1185,11 +1217,11 @@ HttpParseMessageBody (
         Parser->State = BodyParserComplete;\r
         if (Parser->Callback != NULL) {\r
           Status = Parser->Callback (\r
-                     BodyParseEventOnComplete,\r
-                     Char,\r
-                     0,\r
-                     Parser->Context\r
-                     );\r
+                             BodyParseEventOnComplete,\r
+                             Char,\r
+                             0,\r
+                             Parser->Context\r
+                             );\r
           if (EFI_ERROR (Status)) {\r
             return Status;\r
           }\r
@@ -1274,11 +1306,11 @@ HttpParseMessageBody (
         Char++;\r
         if (Parser->Callback != NULL) {\r
           Status = Parser->Callback (\r
-                     BodyParseEventOnComplete,\r
-                     Char,\r
-                     0,\r
-                     Parser->Context\r
-                     );\r
+                             BodyParseEventOnComplete,\r
+                             Char,\r
+                             0,\r
+                             Parser->Context\r
+                             );\r
           if (EFI_ERROR (Status)) {\r
             return Status;\r
           }\r
@@ -1304,11 +1336,11 @@ HttpParseMessageBody (
       LengthForCallback = MIN (Parser->CurrentChunkSize - Parser->CurrentChunkParsedSize, RemainderLengthInThis);\r
       if (Parser->Callback != NULL) {\r
         Status = Parser->Callback (\r
-                   BodyParseEventOnData,\r
-                   Char,\r
-                   LengthForCallback,\r
-                   Parser->Context\r
-                   );\r
+                           BodyParseEventOnData,\r
+                           Char,\r
+                           LengthForCallback,\r
+                           Parser->Context\r
+                           );\r
         if (EFI_ERROR (Status)) {\r
           return Status;\r
         }\r
@@ -1369,7 +1401,11 @@ HttpIsMessageComplete (
 {\r
   HTTP_BODY_PARSER      *Parser;\r
 \r
-  Parser = (HTTP_BODY_PARSER*) MsgParser;\r
+  if (MsgParser == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  Parser = (HTTP_BODY_PARSER *) MsgParser;\r
 \r
   if (Parser->State == BodyParserComplete) {\r
     return TRUE;\r
@@ -1403,7 +1439,7 @@ HttpGetEntityLength (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Parser = (HTTP_BODY_PARSER*) MsgParser;\r
+  Parser = (HTTP_BODY_PARSER *) MsgParser;\r
 \r
   if (!Parser->ContentLengthIsValid) {\r
     return EFI_NOT_READY;\r
@@ -1430,10 +1466,10 @@ HttpFreeMsgParser (
 \r
 \r
 /**\r
-  Get the next string, which is distinguished by specified seperator.\r
+  Get the next string, which is distinguished by specified separator.\r
 \r
   @param[in]  String             Pointer to the string.\r
-  @param[in]  Seperator          Specified seperator used to distinguish where is the beginning\r
+  @param[in]  Separator          Specified separator used to distinguish where is the beginning\r
                                  of next string.\r
 \r
   @return     Pointer to the next string.\r
@@ -1441,10 +1477,9 @@ HttpFreeMsgParser (
 \r
 **/\r
 CHAR8 *\r
-EFIAPI\r
 AsciiStrGetNextToken (\r
   IN CONST CHAR8 *String,\r
-  IN       CHAR8 Seperator\r
+  IN       CHAR8 Separator\r
   )\r
 {\r
   CONST CHAR8 *Token;\r
@@ -1454,7 +1489,7 @@ AsciiStrGetNextToken (
     if (*Token == 0) {\r
       return NULL;\r
     }\r
-    if (*Token == Seperator) {\r
+    if (*Token == Separator) {\r
       return (CHAR8 *)(Token + 1);\r
     }\r
     Token++;\r
@@ -1470,6 +1505,7 @@ AsciiStrGetNextToken (
 \r
 \r
   @retval EFI_SUCCESS             The FieldName and FieldValue are set into HttpHeader successfully.\r
+  @retval EFI_INVALID_PARAMETER   The parameter is invalid.\r
   @retval EFI_OUT_OF_RESOURCES    Failed to allocate resources.\r
 \r
 **/\r
@@ -1484,6 +1520,10 @@ HttpSetFieldNameAndValue (
   UINTN                       FieldNameSize;\r
   UINTN                       FieldValueSize;\r
 \r
+  if (HttpHeader == NULL || FieldName == NULL || FieldValue == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   if (HttpHeader->FieldName != NULL) {\r
     FreePool (HttpHeader->FieldName);\r
   }\r
@@ -1502,6 +1542,7 @@ HttpSetFieldNameAndValue (
   FieldValueSize = AsciiStrSize (FieldValue);\r
   HttpHeader->FieldValue = AllocateZeroPool (FieldValueSize);\r
   if (HttpHeader->FieldValue == NULL) {\r
+    FreePool (HttpHeader->FieldName);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   CopyMem (HttpHeader->FieldValue, FieldValue, FieldValueSize);\r
@@ -1532,6 +1573,7 @@ HttpGetFieldNameAndValue (
   CHAR8  *FieldNameStr;\r
   CHAR8  *FieldValueStr;\r
   CHAR8  *StrPtr;\r
+  CHAR8  *EndofHeader;\r
 \r
   if (String == NULL || FieldName == NULL || FieldValue == NULL) {\r
     return NULL;\r
@@ -1542,6 +1584,16 @@ HttpGetFieldNameAndValue (
   FieldNameStr  = NULL;\r
   FieldValueStr = NULL;\r
   StrPtr        = NULL;\r
+  EndofHeader   = NULL;\r
+\r
+\r
+  //\r
+  // Check whether the raw HTTP header string is valid or not.\r
+  //\r
+  EndofHeader = AsciiStrStr (String, "\r\n\r\n");\r
+  if (EndofHeader == NULL) {\r
+    return NULL;\r
+  }\r
 \r
   //\r
   // Each header field consists of a name followed by a colon (":") and the field value.\r
@@ -1559,13 +1611,32 @@ HttpGetFieldNameAndValue (
 \r
   //\r
   // The field value MAY be preceded by any amount of LWS, though a single SP is preferred.\r
+  // Note: LWS  = [CRLF] 1*(SP|HT), it can be '\r\n ' or '\r\n\t' or ' ' or '\t'.\r
+  //       CRLF = '\r\n'.\r
+  //       SP   = ' '.\r
+  //       HT   = '\t' (Tab).\r
   //\r
   while (TRUE) {\r
     if (*FieldValueStr == ' ' || *FieldValueStr == '\t') {\r
+      //\r
+      // Boundary condition check. \r
+      //\r
+      if ((UINTN) EndofHeader - (UINTN) FieldValueStr < 1) {\r
+        return NULL;  \r
+      }\r
+      \r
       FieldValueStr ++;\r
-    } else if (*FieldValueStr == '\r' && *(FieldValueStr + 1) == '\n' &&\r
-               (*(FieldValueStr + 2) == ' ' || *(FieldValueStr + 2) == '\t')) {\r
-      FieldValueStr = FieldValueStr + 3;\r
+    } else if (*FieldValueStr == '\r') {\r
+      //\r
+      // Boundary condition check. \r
+      //\r
+      if ((UINTN) EndofHeader - (UINTN) FieldValueStr < 3) {\r
+        return NULL;  \r
+      }\r
+\r
+      if (*(FieldValueStr + 1) == '\n' && (*(FieldValueStr + 2) == ' ' || *(FieldValueStr + 2) == '\t')) {\r
+        FieldValueStr = FieldValueStr + 3;\r
+      }\r
     } else {\r
       break;\r
     }\r
@@ -1630,24 +1701,33 @@ HttpFreeHeaderFields (
 }\r
 \r
 /**\r
-  Generate HTTP request string.\r
+  Generate HTTP request message.\r
+\r
+  This function will allocate memory for the whole HTTP message and generate a\r
+  well formatted HTTP Request message in it, include the Request-Line, header\r
+  fields and also the message body. It is the caller's responsibility to free\r
+  the buffer returned in *RequestMsg.\r
 \r
-  @param[in]   Message            Pointer to storage containing HTTP message data.\r
+  @param[in]   Message            Pointer to the EFI_HTTP_MESSAGE structure which\r
+                                  contains the required information to generate\r
+                                  the HTTP request message.\r
   @param[in]   Url                The URL of a remote host.\r
-  @param[out]  RequestString      Pointer to the created HTTP request string.\r
+  @param[out]  RequestMsg         Pointer to the created HTTP request message.\r
                                   NULL if any error occured.\r
+  @param[out]  RequestMsgSize     Size of the RequestMsg (in bytes).\r
 \r
-  @return EFI_SUCCESS             If HTTP request string was created successfully\r
+  @retval EFI_SUCCESS             If HTTP request string was created successfully.\r
   @retval EFI_OUT_OF_RESOURCES    Failed to allocate resources.\r
-  @retval EFI_INVALID_PARAMETER   The input arguments are invalid\r
+  @retval EFI_INVALID_PARAMETER   The input arguments are invalid.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-HttpGenRequestString (\r
+HttpGenRequestMessage (\r
   IN     CONST EFI_HTTP_MESSAGE        *Message,\r
   IN     CONST CHAR8                   *Url,\r
-     OUT CHAR8                         **Request\r
+     OUT CHAR8                         **RequestMsg,\r
+     OUT UINTN                         *RequestMsgSize\r
   )\r
 {\r
   EFI_STATUS                       Status;\r
@@ -1661,150 +1741,191 @@ HttpGenRequestString (
   UINTN                            Index;\r
   EFI_HTTP_UTILITIES_PROTOCOL      *HttpUtilitiesProtocol;\r
 \r
-\r
-  ASSERT (Message != NULL);\r
-\r
-  *Request = NULL;\r
-  MsgSize = 0;\r
-  Success = FALSE;\r
-  HttpHdr = NULL;\r
-  AppendList = NULL;\r
+  Status                = EFI_SUCCESS;\r
+  HttpHdrSize           = 0;\r
+  MsgSize               = 0;\r
+  Success               = FALSE;\r
+  HttpHdr               = NULL;\r
+  AppendList            = NULL;\r
   HttpUtilitiesProtocol = NULL;\r
 \r
   //\r
-  // Locate the HTTP_UTILITIES protocol.\r
+  // 1. If we have a Request, we cannot have a NULL Url\r
+  // 2. If we have a Request, HeaderCount can not be non-zero\r
+  // 3. If we do not have a Request, HeaderCount should be zero\r
+  // 4. If we do not have Request and Headers, we need at least a message-body\r
   //\r
-  Status = gBS->LocateProtocol (\r
-                  &gEfiHttpUtilitiesProtocolGuid,\r
-                  NULL,\r
-                  (VOID **)&HttpUtilitiesProtocol\r
-                  );\r
+  if ((Message == NULL || RequestMsg == NULL || RequestMsgSize == NULL) || \r
+      (Message->Data.Request != NULL && Url == NULL) ||\r
+      (Message->Data.Request != NULL && Message->HeaderCount == 0) ||\r
+      (Message->Data.Request == NULL && Message->HeaderCount != 0) ||\r
+      (Message->Data.Request == NULL && Message->HeaderCount == 0 && Message->BodyLength == 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR,"Failed to locate Http Utilities protocol. Status = %r.\n", Status));\r
-    return Status;\r
+  if (Message->HeaderCount != 0) {\r
+    //\r
+    // Locate the HTTP_UTILITIES protocol.\r
+    //\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiHttpUtilitiesProtocolGuid,\r
+                    NULL,\r
+                    (VOID **) &HttpUtilitiesProtocol\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR,"Failed to locate Http Utilities protocol. Status = %r.\n", Status));\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Build AppendList to send into HttpUtilitiesBuild\r
+    //\r
+    AppendList = AllocateZeroPool (sizeof (EFI_HTTP_HEADER *) * (Message->HeaderCount));\r
+    if (AppendList == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    for(Index = 0; Index < Message->HeaderCount; Index++){\r
+      AppendList[Index] = &Message->Headers[Index];\r
+    }\r
+\r
+    //\r
+    // Build raw HTTP Headers\r
+    //\r
+    Status = HttpUtilitiesProtocol->Build (\r
+                                      HttpUtilitiesProtocol,\r
+                                      0,\r
+                                      NULL,\r
+                                      0,\r
+                                      NULL,\r
+                                      Message->HeaderCount,\r
+                                      AppendList,\r
+                                      &HttpHdrSize,\r
+                                      &HttpHdr\r
+                                      );\r
+\r
+    FreePool (AppendList);\r
+\r
+    if (EFI_ERROR (Status) || HttpHdr == NULL){\r
+      return Status;\r
+    }\r
   }\r
 \r
   //\r
-  // Build AppendList to send into HttpUtilitiesBuild\r
+  // If we have headers to be sent, account for it.\r
   //\r
-  AppendList = AllocateZeroPool (sizeof (EFI_HTTP_HEADER *) * (Message->HeaderCount));\r
-  if (AppendList == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  for(Index = 0; Index < Message->HeaderCount; Index++){\r
-    AppendList[Index] = &Message->Headers[Index];\r
+  if (Message->HeaderCount != 0) {\r
+    MsgSize = HttpHdrSize;\r
   }\r
 \r
   //\r
-  // Build raw HTTP Headers\r
+  // If we have a request line, account for the fields.\r
   //\r
-  Status = HttpUtilitiesProtocol->Build (\r
-              HttpUtilitiesProtocol,\r
-              0,\r
-              NULL,\r
-              0,\r
-              NULL,\r
-              Message->HeaderCount,\r
-              AppendList,\r
-              &HttpHdrSize,\r
-              &HttpHdr\r
-              );\r
-\r
-  if (AppendList != NULL) {\r
-    FreePool (AppendList);\r
+  if (Message->Data.Request != NULL) {\r
+    MsgSize += HTTP_METHOD_MAXIMUM_LEN + AsciiStrLen (HTTP_VERSION_CRLF_STR) + AsciiStrLen (Url);\r
   }\r
 \r
-  if (EFI_ERROR (Status) || HttpHdr == NULL){\r
-    return Status;\r
-  }\r
 \r
   //\r
-  // Calculate HTTP message length.\r
+  // If we have a message body to be sent, account for it.\r
   //\r
-  MsgSize = Message->BodyLength + HTTP_METHOD_MAXIMUM_LEN + AsciiStrLen (Url) +\r
-            AsciiStrLen (HTTP_VERSION_CRLF_STR) + HttpHdrSize;\r
+  MsgSize += Message->BodyLength;\r
 \r
-\r
-  *Request = AllocateZeroPool (MsgSize);\r
-  if (*Request == NULL) {\r
+  //\r
+  // memory for the string that needs to be sent to TCP\r
+  //\r
+  *RequestMsg = NULL;\r
+  *RequestMsg = AllocateZeroPool (MsgSize);\r
+  if (*RequestMsg == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto Exit;\r
   }\r
 \r
-  RequestPtr = *Request;\r
+  RequestPtr = *RequestMsg;\r
   //\r
   // Construct header request\r
   //\r
-  switch (Message->Data.Request->Method) {\r
-  case HttpMethodGet:\r
-    StrLength = sizeof (HTTP_METHOD_GET) - 1;\r
-    CopyMem (RequestPtr, HTTP_METHOD_GET, StrLength);\r
-    RequestPtr += StrLength;\r
-    break;\r
-  case HttpMethodPut:\r
-    StrLength = sizeof (HTTP_METHOD_PUT) - 1;\r
-    CopyMem (RequestPtr, HTTP_METHOD_PUT, StrLength);\r
-    RequestPtr += StrLength;\r
-    break;\r
-  case HttpMethodPatch:\r
-    StrLength = sizeof (HTTP_METHOD_PATCH) - 1;\r
-    CopyMem (RequestPtr, HTTP_METHOD_PATCH, StrLength);\r
-    RequestPtr += StrLength;\r
-    break;\r
-  case HttpMethodPost:\r
-    StrLength = sizeof (HTTP_METHOD_POST) - 1;\r
-    CopyMem (RequestPtr, HTTP_METHOD_POST, StrLength);\r
-    RequestPtr += StrLength;\r
-    break;\r
-  case HttpMethodHead:\r
-    StrLength = sizeof (HTTP_METHOD_HEAD) - 1;\r
-    CopyMem (RequestPtr, HTTP_METHOD_HEAD, StrLength);\r
-    RequestPtr += StrLength;\r
-    break;\r
-  case HttpMethodDelete:\r
-    StrLength = sizeof (HTTP_METHOD_DELETE) - 1;\r
-    CopyMem (RequestPtr, HTTP_METHOD_DELETE, StrLength);\r
+  if (Message->Data.Request != NULL) {\r
+    switch (Message->Data.Request->Method) {\r
+    case HttpMethodGet:\r
+      StrLength = sizeof (HTTP_METHOD_GET) - 1;\r
+      CopyMem (RequestPtr, HTTP_METHOD_GET, StrLength);\r
+      RequestPtr += StrLength;\r
+      break;\r
+    case HttpMethodPut:\r
+      StrLength = sizeof (HTTP_METHOD_PUT) - 1;\r
+      CopyMem (RequestPtr, HTTP_METHOD_PUT, StrLength);\r
+      RequestPtr += StrLength;\r
+      break;\r
+    case HttpMethodPatch:\r
+      StrLength = sizeof (HTTP_METHOD_PATCH) - 1;\r
+      CopyMem (RequestPtr, HTTP_METHOD_PATCH, StrLength);\r
+      RequestPtr += StrLength;\r
+      break;\r
+    case HttpMethodPost:\r
+      StrLength = sizeof (HTTP_METHOD_POST) - 1;\r
+      CopyMem (RequestPtr, HTTP_METHOD_POST, StrLength);\r
+      RequestPtr += StrLength;\r
+      break;\r
+    case HttpMethodHead:\r
+      StrLength = sizeof (HTTP_METHOD_HEAD) - 1;\r
+      CopyMem (RequestPtr, HTTP_METHOD_HEAD, StrLength);\r
+      RequestPtr += StrLength;\r
+      break;\r
+    case HttpMethodDelete:\r
+      StrLength = sizeof (HTTP_METHOD_DELETE) - 1;\r
+      CopyMem (RequestPtr, HTTP_METHOD_DELETE, StrLength);\r
+      RequestPtr += StrLength;\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Exit;\r
+    }\r
+\r
+    StrLength = AsciiStrLen(EMPTY_SPACE);\r
+    CopyMem (RequestPtr, EMPTY_SPACE, StrLength);\r
     RequestPtr += StrLength;\r
-    break;\r
-  default:\r
-    ASSERT (FALSE);\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto Exit;\r
-  }\r
 \r
-  StrLength = AsciiStrLen(EMPTY_SPACE);\r
-  CopyMem (RequestPtr, EMPTY_SPACE, StrLength);\r
-  RequestPtr += StrLength;\r
+    StrLength = AsciiStrLen (Url);\r
+    CopyMem (RequestPtr, Url, StrLength);\r
+    RequestPtr += StrLength;\r
 \r
-  StrLength = AsciiStrLen (Url);\r
-  CopyMem (RequestPtr, Url, StrLength);\r
-  RequestPtr += StrLength;\r
+    StrLength = sizeof (HTTP_VERSION_CRLF_STR) - 1;\r
+    CopyMem (RequestPtr, HTTP_VERSION_CRLF_STR, StrLength);\r
+    RequestPtr += StrLength;\r
 \r
-  StrLength = sizeof (HTTP_VERSION_CRLF_STR) - 1;\r
-  CopyMem (RequestPtr, HTTP_VERSION_CRLF_STR, StrLength);\r
-  RequestPtr += StrLength;\r
+    if (HttpHdr != NULL) {\r
+      //\r
+      // Construct header\r
+      //\r
+      CopyMem (RequestPtr, HttpHdr, HttpHdrSize);\r
+      RequestPtr += HttpHdrSize;\r
+    }\r
+  }\r
 \r
   //\r
-  // Construct header\r
+  // Construct body\r
   //\r
-  CopyMem (RequestPtr, HttpHdr, HttpHdrSize);\r
-  RequestPtr += HttpHdrSize;\r
+  if (Message->Body != NULL) {\r
+    CopyMem (RequestPtr, Message->Body, Message->BodyLength);\r
+    RequestPtr += Message->BodyLength;\r
+  }\r
 \r
   //\r
   // Done\r
   //\r
-  *RequestPtr = 0;\r
+  (*RequestMsgSize) = (UINTN)(RequestPtr) - (UINTN)(*RequestMsg);\r
   Success     = TRUE;\r
 \r
 Exit:\r
 \r
   if (!Success) {\r
-    if (*Request != NULL) {\r
-      FreePool (*Request);\r
+    if (*RequestMsg != NULL) {\r
+      FreePool (*RequestMsg);\r
     }\r
-    *Request = NULL;\r
+    *RequestMsg = NULL;\r
     return Status;\r
   }\r
 \r
@@ -1850,7 +1971,7 @@ HttpMappingToStatusCode (
   case 206:\r
     return HTTP_STATUS_206_PARTIAL_CONTENT;\r
   case 300:\r
-    return HTTP_STATUS_300_MULTIPLE_CHIOCES;\r
+    return HTTP_STATUS_300_MULTIPLE_CHOICES;\r
   case 301:\r
     return HTTP_STATUS_301_MOVED_PERMANENTLY;\r
   case 302:\r
@@ -1863,6 +1984,8 @@ HttpMappingToStatusCode (
     return HTTP_STATUS_305_USE_PROXY;\r
   case 307:\r
     return HTTP_STATUS_307_TEMPORARY_REDIRECT;\r
+  case 308:\r
+    return HTTP_STATUS_308_PERMANENT_REDIRECT;\r
   case 400:\r
     return HTTP_STATUS_400_BAD_REQUEST;\r
   case 401:\r
@@ -1938,7 +2061,15 @@ HttpIsValidHttpHeader (
 {\r
   UINTN                       Index;\r
 \r
+  if (FieldName == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
   for (Index = 0; Index < DeleteCount; Index++) {\r
+    if (DeleteList[Index] == NULL) {\r
+      continue;\r
+    }\r
+    \r
     if (AsciiStrCmp (FieldName, DeleteList[Index]) == 0) {\r
       return FALSE;\r
     }\r