]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesProtocol.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / HttpUtilitiesDxe / HttpUtilitiesProtocol.c
1 /** @file
2 Implementation of EFI_HTTP_PROTOCOL protocol interfaces.
3
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "HttpUtilitiesDxe.h"
11
12 EFI_HTTP_UTILITIES_PROTOCOL mHttpUtilitiesProtocol = {
13 HttpUtilitiesBuild,
14 HttpUtilitiesParse
15 };
16
17 /**
18 Create HTTP header based on a combination of seed header, fields
19 to delete, and fields to append.
20
21 The Build() function is used to manage the headers portion of an
22 HTTP message by providing the ability to add, remove, or replace
23 HTTP headers.
24
25 @param[in] This Pointer to EFI_HTTP_UTILITIES_PROTOCOL instance.
26 @param[in] SeedMessageSize Size of the initial HTTP header. This can be zero.
27 @param[in] SeedMessage Initial HTTP header to be used as a base for
28 building a new HTTP header. If NULL,
29 SeedMessageSize is ignored.
30 @param[in] DeleteCount Number of null-terminated HTTP header field names
31 in DeleteList.
32 @param[in] DeleteList List of null-terminated HTTP header field names to
33 remove from SeedMessage. Only the field names are
34 in this list because the field values are irrelevant
35 to this operation.
36 @param[in] AppendCount Number of header fields in AppendList.
37 @param[in] AppendList List of HTTP headers to populate NewMessage with.
38 If SeedMessage is not NULL, AppendList will be
39 appended to the existing list from SeedMessage in
40 NewMessage.
41 @param[out] NewMessageSize Pointer to number of header fields in NewMessage.
42 @param[out] NewMessage Pointer to a new list of HTTP headers based on.
43
44 @retval EFI_SUCCESS Add, remove, and replace operations succeeded.
45 @retval EFI_OUT_OF_RESOURCES Could not allocate memory for NewMessage.
46 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
47 This is NULL.
48 **/
49 EFI_STATUS
50 EFIAPI
51 HttpUtilitiesBuild (
52 IN EFI_HTTP_UTILITIES_PROTOCOL *This,
53 IN UINTN SeedMessageSize,
54 IN VOID *SeedMessage OPTIONAL,
55 IN UINTN DeleteCount,
56 IN CHAR8 *DeleteList[] OPTIONAL,
57 IN UINTN AppendCount,
58 IN EFI_HTTP_HEADER *AppendList[] OPTIONAL,
59 OUT UINTN *NewMessageSize,
60 OUT VOID **NewMessage
61 )
62 {
63 EFI_STATUS Status;
64 EFI_HTTP_HEADER *SeedHeaderFields;
65 UINTN SeedFieldCount;
66 UINTN Index;
67 EFI_HTTP_HEADER *TempHeaderFields;
68 UINTN TempFieldCount;
69 EFI_HTTP_HEADER *NewHeaderFields;
70 UINTN NewFieldCount;
71 EFI_HTTP_HEADER *HttpHeader;
72 UINTN StrLength;
73 UINT8 *NewMessagePtr;
74
75 SeedHeaderFields = NULL;
76 SeedFieldCount = 0;
77 TempHeaderFields = NULL;
78 TempFieldCount = 0;
79 NewHeaderFields = NULL;
80 NewFieldCount = 0;
81
82 HttpHeader = NULL;
83 StrLength = 0;
84 NewMessagePtr = NULL;
85 *NewMessageSize = 0;
86 Status = EFI_SUCCESS;
87
88 if (This == NULL) {
89 return EFI_INVALID_PARAMETER;
90 }
91
92 if (SeedMessage != NULL) {
93 Status = This->Parse (
94 This,
95 SeedMessage,
96 SeedMessageSize,
97 &SeedHeaderFields,
98 &SeedFieldCount
99 );
100 if (EFI_ERROR (Status)) {
101 goto ON_EXIT;
102 }
103 }
104
105 //
106 // Handle DeleteList
107 //
108 if ((SeedFieldCount != 0) && (DeleteCount != 0)) {
109 TempHeaderFields = AllocateZeroPool (SeedFieldCount * sizeof (EFI_HTTP_HEADER));
110 if (TempHeaderFields == NULL) {
111 Status = EFI_OUT_OF_RESOURCES;
112 goto ON_EXIT;
113 }
114
115 for (Index = 0, TempFieldCount = 0; Index < SeedFieldCount; Index++) {
116 //
117 // Check whether each SeedHeaderFields member is in DeleteList
118 //
119 if (HttpIsValidHttpHeader (DeleteList, DeleteCount, SeedHeaderFields[Index].FieldName)) {
120 Status = HttpSetFieldNameAndValue (
121 &TempHeaderFields[TempFieldCount],
122 SeedHeaderFields[Index].FieldName,
123 SeedHeaderFields[Index].FieldValue
124 );
125 if (EFI_ERROR (Status)) {
126 goto ON_EXIT;
127 }
128
129 TempFieldCount++;
130 }
131 }
132 } else {
133 TempHeaderFields = SeedHeaderFields;
134 TempFieldCount = SeedFieldCount;
135 }
136
137 //
138 // Handle AppendList
139 //
140 NewHeaderFields = AllocateZeroPool ((TempFieldCount + AppendCount) * sizeof (EFI_HTTP_HEADER));
141 if (NewHeaderFields == NULL) {
142 Status = EFI_OUT_OF_RESOURCES;
143 goto ON_EXIT;
144 }
145
146 for (Index = 0; Index < TempFieldCount; Index++) {
147 Status = HttpSetFieldNameAndValue (
148 &NewHeaderFields[Index],
149 TempHeaderFields[Index].FieldName,
150 TempHeaderFields[Index].FieldValue
151 );
152 if (EFI_ERROR (Status)) {
153 goto ON_EXIT;
154 }
155 }
156
157 NewFieldCount = TempFieldCount;
158
159 for (Index = 0; Index < AppendCount; Index++) {
160 HttpHeader = HttpFindHeader (NewFieldCount, NewHeaderFields, AppendList[Index]->FieldName);
161 if (HttpHeader != NULL) {
162 Status = HttpSetFieldNameAndValue (
163 HttpHeader,
164 AppendList[Index]->FieldName,
165 AppendList[Index]->FieldValue
166 );
167 if (EFI_ERROR (Status)) {
168 goto ON_EXIT;
169 }
170 } else {
171 Status = HttpSetFieldNameAndValue (
172 &NewHeaderFields[NewFieldCount],
173 AppendList[Index]->FieldName,
174 AppendList[Index]->FieldValue
175 );
176 if (EFI_ERROR (Status)) {
177 goto ON_EXIT;
178 }
179
180 NewFieldCount++;
181 }
182 }
183
184 //
185 // Calculate NewMessageSize, then build NewMessage
186 //
187 for (Index = 0; Index < NewFieldCount; Index++) {
188 HttpHeader = &NewHeaderFields[Index];
189
190 StrLength = AsciiStrLen (HttpHeader->FieldName);
191 *NewMessageSize += StrLength;
192
193 StrLength = sizeof (": ") - 1;
194 *NewMessageSize += StrLength;
195
196 StrLength = AsciiStrLen (HttpHeader->FieldValue);
197 *NewMessageSize += StrLength;
198
199 StrLength = sizeof ("\r\n") - 1;
200 *NewMessageSize += StrLength;
201 }
202
203 StrLength = sizeof ("\r\n") - 1;
204 *NewMessageSize += StrLength;
205
206 *NewMessage = AllocateZeroPool (*NewMessageSize);
207 if (*NewMessage == NULL) {
208 Status = EFI_OUT_OF_RESOURCES;
209 goto ON_EXIT;
210 }
211
212 NewMessagePtr = (UINT8 *)(*NewMessage);
213
214 for (Index = 0; Index < NewFieldCount; Index++) {
215 HttpHeader = &NewHeaderFields[Index];
216
217 StrLength = AsciiStrLen (HttpHeader->FieldName);
218 CopyMem (NewMessagePtr, HttpHeader->FieldName, StrLength);
219 NewMessagePtr += StrLength;
220
221 StrLength = sizeof (": ") - 1;
222 CopyMem (NewMessagePtr, ": ", StrLength);
223 NewMessagePtr += StrLength;
224
225 StrLength = AsciiStrLen (HttpHeader->FieldValue);
226 CopyMem (NewMessagePtr, HttpHeader->FieldValue, StrLength);
227 NewMessagePtr += StrLength;
228
229 StrLength = sizeof ("\r\n") - 1;
230 CopyMem (NewMessagePtr, "\r\n", StrLength);
231 NewMessagePtr += StrLength;
232 }
233
234 StrLength = sizeof ("\r\n") - 1;
235 CopyMem (NewMessagePtr, "\r\n", StrLength);
236 NewMessagePtr += StrLength;
237
238 ASSERT (*NewMessageSize == (UINTN)NewMessagePtr - (UINTN)(*NewMessage));
239
240 //
241 // Free allocated buffer
242 //
243 ON_EXIT:
244 if (SeedHeaderFields != NULL) {
245 HttpFreeHeaderFields (SeedHeaderFields, SeedFieldCount);
246 }
247
248 if (TempHeaderFields != NULL) {
249 HttpFreeHeaderFields (TempHeaderFields, TempFieldCount);
250 }
251
252 if (NewHeaderFields != NULL) {
253 HttpFreeHeaderFields (NewHeaderFields, NewFieldCount);
254 }
255
256 return Status;
257 }
258
259 /**
260 Parses HTTP header and produces an array of key/value pairs.
261
262 The Parse() function is used to transform data stored in HttpHeader
263 into a list of fields paired with their corresponding values.
264
265 @param[in] This Pointer to EFI_HTTP_UTILITIES_PROTOCOL instance.
266 @param[in] HttpMessage Contains raw unformatted HTTP header string.
267 @param[in] HttpMessageSize Size of HTTP header.
268 @param[out] HeaderFields Array of key/value header pairs.
269 @param[out] FieldCount Number of headers in HeaderFields.
270
271 @retval EFI_SUCCESS Allocation succeeded.
272 @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been
273 initialized.
274 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
275 This is NULL.
276 HttpMessage is NULL.
277 HeaderFields is NULL.
278 FieldCount is NULL.
279 **/
280 EFI_STATUS
281 EFIAPI
282 HttpUtilitiesParse (
283 IN EFI_HTTP_UTILITIES_PROTOCOL *This,
284 IN CHAR8 *HttpMessage,
285 IN UINTN HttpMessageSize,
286 OUT EFI_HTTP_HEADER **HeaderFields,
287 OUT UINTN *FieldCount
288 )
289 {
290 EFI_STATUS Status;
291 CHAR8 *TempHttpMessage;
292 CHAR8 *Token;
293 CHAR8 *NextToken;
294 CHAR8 *FieldName;
295 CHAR8 *FieldValue;
296 UINTN Index;
297 UINTN HttpBufferSize;
298
299 Status = EFI_SUCCESS;
300 TempHttpMessage = NULL;
301 Token = NULL;
302 NextToken = NULL;
303 FieldName = NULL;
304 FieldValue = NULL;
305 Index = 0;
306
307 if ((This == NULL) || (HttpMessage == NULL) || (HeaderFields == NULL) || (FieldCount == NULL)) {
308 return EFI_INVALID_PARAMETER;
309 }
310
311 //
312 // Append the http response string along with a Null-terminator.
313 //
314 HttpBufferSize = HttpMessageSize + 1;
315 TempHttpMessage = AllocatePool (HttpBufferSize);
316 if (TempHttpMessage == NULL) {
317 return EFI_OUT_OF_RESOURCES;
318 }
319
320 CopyMem (TempHttpMessage, HttpMessage, HttpMessageSize);
321 *(TempHttpMessage + HttpMessageSize) = '\0';
322
323 //
324 // Get header number
325 //
326 *FieldCount = 0;
327 Token = TempHttpMessage;
328 while (TRUE) {
329 FieldName = NULL;
330 FieldValue = NULL;
331 NextToken = HttpGetFieldNameAndValue (Token, &FieldName, &FieldValue);
332 Token = NextToken;
333 if ((FieldName == NULL) || (FieldValue == NULL)) {
334 break;
335 }
336
337 (*FieldCount)++;
338 }
339
340 if (*FieldCount == 0) {
341 Status = EFI_INVALID_PARAMETER;
342 goto ON_EXIT;
343 }
344
345 //
346 // Allocate buffer for header
347 //
348 *HeaderFields = AllocateZeroPool ((*FieldCount) * sizeof (EFI_HTTP_HEADER));
349 if (*HeaderFields == NULL) {
350 *FieldCount = 0;
351 Status = EFI_OUT_OF_RESOURCES;
352 goto ON_EXIT;
353 }
354
355 CopyMem (TempHttpMessage, HttpMessage, HttpMessageSize);
356
357 //
358 // Set Field and Value to each header
359 //
360 Token = TempHttpMessage;
361 while (Index < *FieldCount) {
362 FieldName = NULL;
363 FieldValue = NULL;
364 NextToken = HttpGetFieldNameAndValue (Token, &FieldName, &FieldValue);
365 Token = NextToken;
366 if ((FieldName == NULL) || (FieldValue == NULL)) {
367 break;
368 }
369
370 Status = HttpSetFieldNameAndValue (&(*HeaderFields)[Index], FieldName, FieldValue);
371 if (EFI_ERROR (Status)) {
372 *FieldCount = 0;
373 HttpFreeHeaderFields (*HeaderFields, Index);
374 goto ON_EXIT;
375 }
376
377 Index++;
378 }
379
380 //
381 // Free allocated buffer
382 //
383 ON_EXIT:
384 if (TempHttpMessage != NULL) {
385 FreePool (TempHttpMessage);
386 }
387
388 return Status;
389 }