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