Home | History | Annotate | Download | only in HttpUtilitiesDxe
      1 /** @file
      2   The functions for HttpUtilities driver.
      3 
      4   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "HttpUtilitiesDxe.h"
     17 
     18 
     19 /**
     20   Get the next string, which is distinguished by specified seperator.
     21 
     22   @param[in]  String             Pointer to the string.
     23   @param[in]  Seperator          Specified seperator used to distinguish where is the beginning
     24                                  of next string.
     25 
     26   @return     Pointer to the next string.
     27   @return     NULL if not find or String is NULL.
     28 
     29 **/
     30 CHAR8 *
     31 AsciiStrGetNextToken (
     32   IN CONST CHAR8 *String,
     33   IN       CHAR8 Seperator
     34   )
     35 {
     36   CONST CHAR8 *Token;
     37 
     38   Token = String;
     39   while (TRUE) {
     40     if (*Token == 0) {
     41       return NULL;
     42     }
     43     if (*Token == Seperator) {
     44       return (CHAR8 *)(Token + 1);
     45     }
     46     Token++;
     47   }
     48 }
     49 
     50 
     51 /**
     52   Free existing HeaderFields.
     53 
     54   @param[in]  HeaderFields       Pointer to array of key/value header pairs waitting for free.
     55   @param[in]  FieldCount         The number of header pairs in HeaderFields.
     56 
     57 **/
     58 VOID
     59 FreeHeaderFields (
     60   IN  EFI_HTTP_HEADER  *HeaderFields,
     61   IN  UINTN            FieldCount
     62   )
     63 {
     64   UINTN                       Index;
     65 
     66   if (HeaderFields != NULL) {
     67     for (Index = 0; Index < FieldCount; Index++) {
     68       if (HeaderFields[Index].FieldName != NULL) {
     69         FreePool (HeaderFields[Index].FieldName);
     70       }
     71       if (HeaderFields[Index].FieldValue != NULL) {
     72         FreePool (HeaderFields[Index].FieldValue);
     73       }
     74     }
     75 
     76     FreePool (HeaderFields);
     77   }
     78 }
     79 
     80 
     81 /**
     82   Find required header field in HeaderFields.
     83 
     84   @param[in]  HeaderFields        Pointer to array of key/value header pairs.
     85   @param[in]  FieldCount          The number of header pairs.
     86   @param[in]  FieldName           Pointer to header field's name.
     87 
     88   @return     Pointer to the queried header field.
     89   @return     NULL if not find this required header field.
     90 
     91 **/
     92 EFI_HTTP_HEADER *
     93 FindHttpHeader (
     94   IN  EFI_HTTP_HEADER  *HeaderFields,
     95   IN  UINTN            FieldCount,
     96   IN  CHAR8            *FieldName
     97   )
     98 {
     99   UINTN                       Index;
    100 
    101   for (Index = 0; Index < FieldCount; Index++) {
    102     if (AsciiStrCmp (FieldName, HeaderFields[Index].FieldName) == 0) {
    103       //
    104       // Find the required header field.
    105       //
    106       return &HeaderFields[Index];
    107     }
    108   }
    109   return NULL;
    110 }
    111 
    112 
    113 /**
    114   Check whether header field called FieldName is in DeleteList.
    115 
    116   @param[in]  DeleteList        Pointer to array of key/value header pairs.
    117   @param[in]  DeleteCount       The number of header pairs.
    118   @param[in]  FieldName         Pointer to header field's name.
    119 
    120   @return     TRUE if FieldName is not in DeleteList, that means this header field is valid.
    121   @return     FALSE if FieldName is in DeleteList, that means this header field is invalid.
    122 
    123 **/
    124 BOOLEAN
    125 IsValidHttpHeader (
    126   IN  CHAR8            *DeleteList[],
    127   IN  UINTN            DeleteCount,
    128   IN  CHAR8            *FieldName
    129   )
    130 {
    131   UINTN                       Index;
    132 
    133   for (Index = 0; Index < DeleteCount; Index++) {
    134     if (AsciiStrCmp (FieldName, DeleteList[Index]) == 0) {
    135       return FALSE;
    136     }
    137   }
    138 
    139   return TRUE;
    140 }
    141 
    142 
    143 /**
    144   Set FieldName and FieldValue into specified HttpHeader.
    145 
    146   @param[in]  HttpHeader          Specified HttpHeader.
    147   @param[in]  FieldName           FieldName of this HttpHeader.
    148   @param[in]  FieldValue          FieldValue of this HttpHeader.
    149 
    150 
    151   @retval EFI_SUCCESS             The FieldName and FieldValue are set into HttpHeader successfully.
    152   @retval EFI_OUT_OF_RESOURCES    Failed to allocate resources.
    153 
    154 **/
    155 EFI_STATUS
    156 SetFieldNameAndValue (
    157   IN  EFI_HTTP_HEADER     *HttpHeader,
    158   IN  CHAR8               *FieldName,
    159   IN  CHAR8               *FieldValue
    160   )
    161 {
    162   UINTN                       FieldNameSize;
    163   UINTN                       FieldValueSize;
    164 
    165   if (HttpHeader->FieldName != NULL) {
    166     FreePool (HttpHeader->FieldName);
    167   }
    168   if (HttpHeader->FieldValue != NULL) {
    169     FreePool (HttpHeader->FieldValue);
    170   }
    171 
    172   FieldNameSize = AsciiStrSize (FieldName);
    173   HttpHeader->FieldName = AllocateZeroPool (FieldNameSize);
    174   if (HttpHeader->FieldName == NULL) {
    175     return EFI_OUT_OF_RESOURCES;
    176   }
    177   CopyMem (HttpHeader->FieldName, FieldName, FieldNameSize);
    178   HttpHeader->FieldName[FieldNameSize - 1] = 0;
    179 
    180   FieldValueSize = AsciiStrSize (FieldValue);
    181   HttpHeader->FieldValue = AllocateZeroPool (FieldValueSize);
    182   if (HttpHeader->FieldValue == NULL) {
    183     return EFI_OUT_OF_RESOURCES;
    184   }
    185   CopyMem (HttpHeader->FieldValue, FieldValue, FieldValueSize);
    186   HttpHeader->FieldValue[FieldValueSize - 1] = 0;
    187 
    188   return EFI_SUCCESS;
    189 }
    190 
    191 
    192 /**
    193   Get one key/value header pair from the raw string.
    194 
    195   @param[in]  String             Pointer to the raw string.
    196   @param[out] FieldName          Pointer to header field's name.
    197   @param[out] FieldValue         Pointer to header field's value.
    198 
    199   @return     Pointer to the next raw string.
    200   @return     NULL if no key/value header pair from this raw string.
    201 
    202 **/
    203 CHAR8 *
    204 GetFieldNameAndValue (
    205   IN  CHAR8   *String,
    206   OUT CHAR8   **FieldName,
    207   OUT CHAR8   **FieldValue
    208   )
    209 {
    210   CHAR8  *FieldNameStr;
    211   CHAR8  *FieldValueStr;
    212   CHAR8  *StrPtr;
    213 
    214   if (String == NULL || FieldName == NULL || FieldValue == NULL) {
    215     return NULL;
    216   }
    217 
    218   *FieldName    = NULL;
    219   *FieldValue   = NULL;
    220   FieldNameStr  = NULL;
    221   FieldValueStr = NULL;
    222   StrPtr        = NULL;
    223 
    224   //
    225   // Each header field consists of a name followed by a colon (":") and the field value.
    226   //
    227   FieldNameStr = String;
    228   FieldValueStr = AsciiStrGetNextToken (FieldNameStr, ':');
    229   if (FieldValueStr == NULL) {
    230     return NULL;
    231   }
    232 
    233   //
    234   // Replace ':' with 0
    235   //
    236   *(FieldValueStr - 1) = 0;
    237 
    238   //
    239   // The field value MAY be preceded by any amount of LWS, though a single SP is preferred.
    240   //
    241   while (TRUE) {
    242     if (*FieldValueStr == ' ' || *FieldValueStr == '\t') {
    243       FieldValueStr ++;
    244     } else if (*FieldValueStr == '\r' && *(FieldValueStr + 1) == '\n' &&
    245                (*(FieldValueStr + 2) == ' ' || *(FieldValueStr + 2) == '\t')) {
    246       FieldValueStr = FieldValueStr + 3;
    247     } else {
    248       break;
    249     }
    250   }
    251 
    252   //
    253   // Header fields can be extended over multiple lines by preceding each extra
    254   // line with at least one SP or HT.
    255   //
    256   StrPtr = FieldValueStr;
    257   do {
    258     StrPtr = AsciiStrGetNextToken (StrPtr, '\r');
    259     if (StrPtr == NULL || *StrPtr != '\n') {
    260       return NULL;
    261     }
    262 
    263     StrPtr++;
    264   } while (*StrPtr == ' ' || *StrPtr == '\t');
    265 
    266   //
    267   // Replace '\r' with 0
    268   //
    269   *(StrPtr - 2) = 0;
    270 
    271   //
    272   // Get FieldName and FieldValue.
    273   //
    274   *FieldName = FieldNameStr;
    275   *FieldValue = FieldValueStr;
    276 
    277   return StrPtr;
    278 }
    279 
    280