]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/headermap.cpp
Security-177.tar.gz
[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 #include <ctype.h>
24 #include <assert.h>
25
26 using namespace std;
27
28 namespace Security {
29
30
31 //
32 // Given a constant text string, extract the leading substring up to 'end' (or \0),
33 // canonicalize its case, and store the result for use.
34 //
35 HeaderMap::CanonicalKey::CanonicalKey(const char *key, char end)
36 {
37 assert(key && key[0]); // non-empty
38 mValue[0] = toupper(key[0]);
39 for (unsigned int n = 1; n < sizeof(mValue) - 1; n++) {
40 if (key[n] == end) {
41 mValue[n] = '\0';
42 return;
43 }
44 mValue[n] = tolower(key[n]);
45 }
46 // overflow -- truncate? throw? dynamic allocation? seppuko? :-)
47 assert(false);
48 }
49
50
51 //
52 // Add an entry
53 //
54 void HeaderMap::add(const char *key, const char *value)
55 {
56 add(CanonicalKey(key), value);
57 }
58
59
60 //
61 // Given a standard form (Key: value), add its value to the headermap
62 //
63 void HeaderMap::add(const char *form)
64 {
65 while (*form && isspace(*form))
66 form++;
67 if (const char *colon = strchr(form, ':')) {
68 CanonicalKey key(form, ':');
69 const char *value = colon + 1;
70 while (*value && isspace(*value))
71 value++;
72 add(key, value);
73 } else {
74 // ignore this
75 //@@@ signal an error? how? how bad?
76 }
77 }
78
79
80 //
81 // Internal add method, given a canonicalized key
82 //
83 void HeaderMap::add(const CanonicalKey &key, const char *value)
84 {
85 Map::iterator it = mMap.find(key);
86 if (it == mMap.end())
87 mMap[key] = value;
88 else
89 merge(key, mMap[key], value);
90 }
91
92
93 //
94 // Locate an entry in a headermap.
95 // Find returns NULL if not found; [] creates a new entry if needed and returns
96 // a reference to the value, in good STL tradition.
97 //
98 const char *HeaderMap::find(const char *key, const char *defaultValue) const
99 {
100 Map::const_iterator it = mMap.find(CanonicalKey(key));
101 return (it == mMap.end()) ? defaultValue : it->second.c_str();
102 }
103
104 string &HeaderMap::operator[] (const char *key)
105 {
106 return mMap[CanonicalKey(key)];
107 }
108
109
110 //
111 // The default implementation of merge throws out the old contents and replaces
112 // them with the new.
113 //
114 void HeaderMap::merge(string key, string &old, string newValue)
115 {
116 old = newValue;
117 }
118
119
120 //
121 // Collect the entire contents into a single string
122 // Note that this is NOT exactly what was passed in; certain canonicalizations have
123 // been done; fields are reordered; and duplicate-header fields have been coalesced.
124 //@@@ size could be pre-calculated (running counter).
125 //
126 string HeaderMap::collect(const char *lineEnding) const
127 {
128 string value;
129 for (Map::const_iterator it = mMap.begin(); it != mMap.end(); it++)
130 value += it->first + ": " + it->second + lineEnding;
131 return value;
132 }
133
134 size_t HeaderMap::collectLength(const char *lineEnding) const
135 {
136 size_t size = 0;
137 size_t sepLength = strlen(lineEnding);
138 for (Map::const_iterator it = mMap.begin(); it != mMap.end(); it++)
139 size += it->first.length() + 2 + it->second.length() + sepLength;
140 return size;
141 }
142
143
144 } // end namespace Security