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 *
AsciiStrGetNextToken(IN CONST CHAR8 * String,IN CHAR8 Seperator)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
FreeHeaderFields(IN EFI_HTTP_HEADER * HeaderFields,IN UINTN FieldCount)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 *
FindHttpHeader(IN EFI_HTTP_HEADER * HeaderFields,IN UINTN FieldCount,IN CHAR8 * FieldName)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
IsValidHttpHeader(IN CHAR8 * DeleteList[],IN UINTN DeleteCount,IN CHAR8 * FieldName)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
SetFieldNameAndValue(IN EFI_HTTP_HEADER * HttpHeader,IN CHAR8 * FieldName,IN CHAR8 * FieldValue)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 *
GetFieldNameAndValue(IN CHAR8 * String,OUT CHAR8 ** FieldName,OUT CHAR8 ** FieldValue)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