]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | ||
25 | // | |
26 | // headermap - represent Internet-standard headers | |
27 | // | |
28 | #include "headermap.h" | |
29 | #include <ctype.h> | |
30 | #include <assert.h> | |
31 | ||
32 | using namespace std; | |
33 | ||
34 | namespace Security { | |
35 | ||
36 | ||
37 | // | |
38 | // Given a constant text string, extract the leading substring up to 'end' (or \0), | |
39 | // canonicalize its case, and store the result for use. | |
40 | // | |
41 | HeaderMap::CanonicalKey::CanonicalKey(const char *key, char end) | |
42 | { | |
43 | assert(key && key[0]); // non-empty | |
44 | mValue[0] = toupper(key[0]); | |
45 | for (unsigned int n = 1; n < sizeof(mValue) - 1; n++) { | |
46 | if (key[n] == end) { | |
47 | mValue[n] = '\0'; | |
48 | return; | |
49 | } | |
50 | mValue[n] = tolower(key[n]); | |
51 | } | |
52 | // overflow -- truncate? throw? dynamic allocation? seppuko? :-) | |
53 | assert(false); | |
54 | } | |
55 | ||
56 | ||
57 | // | |
58 | // Add an entry | |
59 | // | |
60 | void HeaderMap::add(const char *key, const char *value) | |
61 | { | |
62 | add(CanonicalKey(key), value); | |
63 | } | |
64 | ||
65 | ||
66 | // | |
67 | // Given a standard form (Key: value), add its value to the headermap | |
68 | // | |
69 | void HeaderMap::add(const char *form) | |
70 | { | |
71 | while (*form && isspace(*form)) | |
72 | form++; | |
73 | if (const char *colon = strchr(form, ':')) { | |
74 | CanonicalKey key(form, ':'); | |
75 | const char *value = colon + 1; | |
76 | while (*value && isspace(*value)) | |
77 | value++; | |
78 | add(key, value); | |
79 | } else { | |
80 | // ignore this | |
81 | //@@@ signal an error? how? how bad? | |
82 | } | |
83 | } | |
84 | ||
85 | ||
86 | // | |
87 | // Internal add method, given a canonicalized key | |
88 | // | |
89 | void HeaderMap::add(const CanonicalKey &key, const char *value) | |
90 | { | |
91 | Map::iterator it = mMap.find(key); | |
92 | if (it == mMap.end()) | |
93 | mMap[key] = value; | |
94 | else | |
95 | merge(key, mMap[key], value); | |
96 | } | |
97 | ||
98 | ||
99 | // | |
100 | // Locate an entry in a headermap. | |
101 | // Find returns NULL if not found; [] creates a new entry if needed and returns | |
102 | // a reference to the value, in good STL tradition. | |
103 | // | |
104 | const char *HeaderMap::find(const char *key, const char *defaultValue) const | |
105 | { | |
106 | Map::const_iterator it = mMap.find(CanonicalKey(key)); | |
107 | return (it == mMap.end()) ? defaultValue : it->second.c_str(); | |
108 | } | |
109 | ||
110 | string &HeaderMap::operator[] (const char *key) | |
111 | { | |
112 | return mMap[CanonicalKey(key)]; | |
113 | } | |
114 | ||
115 | ||
116 | // | |
117 | // The default implementation of merge throws out the old contents and replaces | |
118 | // them with the new. | |
119 | // | |
120 | void HeaderMap::merge(string key, string &old, string newValue) | |
121 | { | |
122 | old = newValue; | |
123 | } | |
124 | ||
125 | ||
126 | // | |
127 | // Collect the entire contents into a single string | |
128 | // Note that this is NOT exactly what was passed in; certain canonicalizations have | |
129 | // been done; fields are reordered; and duplicate-header fields have been coalesced. | |
130 | //@@@ size could be pre-calculated (running counter). | |
131 | // | |
132 | string HeaderMap::collect(const char *lineEnding) const | |
133 | { | |
134 | string value; | |
135 | for (Map::const_iterator it = mMap.begin(); it != mMap.end(); it++) | |
136 | value += it->first + ": " + it->second + lineEnding; | |
137 | return value; | |
138 | } | |
139 | ||
140 | size_t HeaderMap::collectLength(const char *lineEnding) const | |
141 | { | |
142 | size_t size = 0; | |
143 | size_t sepLength = strlen(lineEnding); | |
144 | for (Map::const_iterator it = mMap.begin(); it != mMap.end(); it++) | |
145 | size += it->first.length() + 2 + it->second.length() + sepLength; | |
146 | return size; | |
147 | } | |
148 | ||
149 | ||
150 | } // end namespace Security |