-
Notifications
You must be signed in to change notification settings - Fork 6
/
headers.h
244 lines (224 loc) · 8.16 KB
/
headers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/* *********************************************************************
* This Original Work is copyright of 51 Degrees Mobile Experts Limited.
* Copyright 2023 51 Degrees Mobile Experts Limited, Davidson House,
* Forbury Square, Reading, Berkshire, United Kingdom RG1 3EU.
*
* This Original Work is licensed under the European Union Public Licence
* (EUPL) v.1.2 and is subject to its terms as set out below.
*
* If a copy of the EUPL was not distributed with this file, You can obtain
* one at https://opensource.org/licenses/EUPL-1.2.
*
* The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
* amended by the European Commission) shall be deemed incompatible for
* the purposes of the Work and the provisions of the compatibility
* clause in Article 5 of the EUPL shall not apply.
*
* If using the Work as, or as part of, a network application, by
* including the attribution notice(s) required under Article 5 of the EUPL
* in the end user terms of the application under an appropriate heading,
* such notice(s) shall fulfill the requirements of that article.
* ********************************************************************* */
#ifndef FIFTYONE_DEGREES_HEADERS_H_INCLUDED
#define FIFTYONE_DEGREES_HEADERS_H_INCLUDED
/**
* @ingroup FiftyOneDegreesCommon
* @defgroup FiftyOneDegreesHeaders Headers
*
* Common form of evidence in 51Degrees engines.
*
* ## Introduction
*
* HTTP headers are a common form of evidence, so required headers have their
* own structure and methods. By storing the unique id of headers, storing
* duplicates of the same header can be avoided. Duplicates can occur as a
* result of different cases or prefixes e.g. `User-Agent`, `user-agent` and
* `HTTP_user-agent` are all the same header.
*
* ## Creation
*
* A header structure is created using the #fiftyoneDegreesHeadersCreate
* method. This takes a state and a method used to extract the unique headers
* from the state. See the method description for more details.
*
* ## Get
*
* A header can be fetched using it's unique id with the
* #fiftyoneDegreesHeadersGetHeaderFromUniqueId method.
*
* The index of a header in the unique headers structure can also be fetched
* using the #fiftyoneDegreesHeaderGetIndex method.
*
* ## Free
*
* Once a headers structure is finished with, it is released using the
* #fiftyoneDegreesHeadersFree method.
*
* ## Usage Example
*
* ```
* fiftyoneDegreesHeadersGetMethod getHeaderId;
* void *state;
*
* // Create the headers structure
* fiftyoneDegreesHeaders *headers = fiftyoneDegreesHeadersCreate(
* false,
* state,
* getHeaderId);
*
* // Get the index of a header
* int index = fiftyoneDegreesHeaderGetIndex(
* headers,
* "user-agent",
* strlen("user-agent"));
*
* // Check that the header exists in the structure
* if (index >= 0) {
*
* // Do something with the header
* // ...
* }
*
* // Free the headers structure
* fiftyoneDegreesHeadersFree(headers);
* ```
*
* @{
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef _MSC_FULL_VER
#include <string.h>
#else
#include <strings.h>
#define _stricmp strcasecmp
#define _strnicmp strncasecmp
#endif
#include "list.h"
#include "evidence.h"
#include "array.h"
#include "common.h"
/**
* Null or PSEUDO_HEADER_SEP terminated string segment within a header.
*/
typedef struct fiftyone_degrees_header_segment_t {
const char* segment; /**< Segment in the name string */
size_t length; /**< Length of the segment in the name strings without the
terminating character */
} fiftyoneDegreesHeaderSegment;
FIFTYONE_DEGREES_ARRAY_TYPE(
fiftyoneDegreesHeaderSegment,
);
typedef uint32_t fiftyoneDegreesHeaderID;
/**
* Header structure to identify a header that either comes directly from the
* data set, or one that forms a pseudo header.
*/
typedef struct fiftyone_degrees_header_t {
const char* name; /**< Name of the header or pseudo header field as a
null terminated string */
size_t nameLength; /**< Length of the name string excluding the
terminating null */
fiftyoneDegreesHeaderSegmentArray* segments; /**< Segments within the
name */
bool isDataSet; /**< True if the header originates from the data set */
fiftyoneDegreesHeaderID uniqueId; /** < Unique id provided by the data set */
} fiftyoneDegreesHeader;
#define FIFTYONE_DEGREES_HEADERS_MEMBERS \
bool expectUpperPrefixedHeaders; /**< True if the headers structure should
expect input header to be prefixed with
'HTTP_' */ \
uint32_t pseudoHeadersCount; /**< Count of the number of pseudo headers */
FIFTYONE_DEGREES_ARRAY_TYPE(
fiftyoneDegreesHeader,
FIFTYONE_DEGREES_HEADERS_MEMBERS);
/**
* Array of headers used to easily access and track the size of the array.
*/
typedef fiftyoneDegreesHeaderArray fiftyoneDegreesHeaders;
/**
* Gets the unique id and name of the header at the requested index.
* @param state pointer to data used by the method
* @param index of the header to get
* @param nameItem pointer to the collection item to populate with the name of
* the header
* @return unique id of the header
*/
typedef long(*fiftyoneDegreesHeadersGetMethod)(
void *state,
uint32_t index,
fiftyoneDegreesCollectionItem *nameItem);
/**
* Returns the number of bytes that will be allocated for a headers structure
* created using the #fiftyoneDegreesHeadersCreate method.
* @param count number of headers in the structure
* @return number of bytes needed
*/
EXTERNAL size_t fiftyoneDegreesHeadersSize(int count);
/**
* Check if a header is a pseudo header.
* @param headerName name of the header
* @return whether a header is a pseudo header.
*/
EXTERNAL bool fiftyoneDegreesHeadersIsPseudo(const char *headerName);
/**
* Creates a new headers instance configured with the unique HTTP names needed
* from evidence. If the useUpperPrefixedHeaders flag is true then checks for
* the presence of HTTP headers will also include checking for HTTP_ as a
* prefix to the header key. If header is a pseudo header, the indices of
* actual headers that form this header will be constructed.
*
* @param useUpperPrefixedHeaders true if HTTP_ prefixes should be checked
* @param state pointer used by getHeaderMethod to retrieve the header integer
* @param get used to return the HTTP header unique integer
* @return a new instance of #fiftyoneDegreesHeaders ready to be used to filter
* HTTP headers.
*/
EXTERNAL fiftyoneDegreesHeaders* fiftyoneDegreesHeadersCreate(
bool useUpperPrefixedHeaders,
void *state,
fiftyoneDegreesHeadersGetMethod get);
/**
* Provides the integer index of the HTTP header name.
* @param headers structure created by #fiftyoneDegreesHeadersCreate
* @param httpHeaderName of the header whose index is required
* @param length number of characters in httpHeaderName
* @return the index of the HTTP header name, or -1 if the name does not exist
*/
EXTERNAL int fiftyoneDegreesHeaderGetIndex(
fiftyoneDegreesHeaders *headers,
const char* httpHeaderName,
size_t length);
/**
* Gets a pointer to the header in the headers structure with a unique id
* matching the one provided. If the headers structure does not contain a
* header with the unique id, NULL will be returned.
* This method assumes that the headers in the structure are unique, if they
* are not, then the first matching header will be returned.
* @param headers pointer to the headers structure to search
* @param uniqueId id to search for
* @return pointer to the matching header, or NULL
*/
EXTERNAL fiftyoneDegreesHeader* fiftyoneDegreesHeadersGetHeaderFromUniqueId(
fiftyoneDegreesHeaders *headers,
fiftyoneDegreesHeaderID uniqueId);
/**
* Frees the memory allocated by the #fiftyoneDegreesHeadersCreate method.
*
* @param headers structure created by #fiftyoneDegreesHeadersCreate
*/
EXTERNAL void fiftyoneDegreesHeadersFree(fiftyoneDegreesHeaders *headers);
/**
* Determines if the key of an evidence pair is an HTTP header.
* @param state results instance to check against
* @param pair the evidence pair to be checked
* @return true if the evidence relates to an HTTP header, otherwise false.
*/
EXTERNAL bool fiftyoneDegreesHeadersIsHttp(
void *state,
fiftyoneDegreesEvidenceKeyValuePair *pair);
/**
* @}
*/
#endif