15 #include "httpAuthorization.h" 16 #include "httpChannel.h" 21 static const char base64_table[64] = {
22 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
23 'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
24 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
25 'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
26 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
27 'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
28 'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
29 '4',
'5',
'6',
'7',
'8',
'9',
'+',
'/',
32 static unsigned char base64_invert[128];
33 static bool got_base64_invert =
false;
41 HTTPAuthorization(
const HTTPAuthorization::Tokens &tokens,
42 const URLSpec &url,
bool is_proxy) {
43 Tokens::const_iterator ti;
44 ti = tokens.find(
"realm");
45 if (ti != tokens.end()) {
46 _realm = (*ti).second;
49 URLSpec canon = get_canonical_url(url);
51 ti = tokens.find(
"domain");
52 if (ti != tokens.end() && !is_proxy) {
55 const string &domain = (*ti).second;
57 while (p < domain.length()) {
58 while (p < domain.length() && isspace(domain[p])) {
62 while (q < domain.length() && !isspace(domain[q])) {
66 string domain_str = domain.substr(p, q - p);
68 if (domain_url.has_server()) {
70 _domain.push_back(get_canonical_url(domain_url).get_url());
75 _domain.push_back(domain_url.get_url());
84 string canon_str = canon.
get_url();
85 size_t slash = canon_str.rfind(
'/');
86 nassertv(slash != string::npos);
87 _domain.push_back(canon_str.substr(0, slash + 1));
97 ~HTTPAuthorization() {
108 bool HTTPAuthorization::
119 void HTTPAuthorization::
120 parse_authentication_schemes(HTTPAuthorization::AuthenticationSchemes &schemes,
121 const string &field_value) {
131 while (p < field_value.length() && isspace(field_value[p])) {
135 if (p < field_value.length()) {
137 while (q < field_value.length() && !isspace(field_value[q])) {
141 string scheme = HTTPChannel::downcase(field_value.substr(p, q - p));
142 Tokens *tokens = &(schemes[scheme]);
146 while (p < field_value.length()) {
148 while (q < field_value.length() && field_value[q] !=
'=' &&
149 field_value[q] !=
',' && !isspace(field_value[q])) {
152 if (field_value[q] ==
'=') {
154 string token = HTTPChannel::downcase(field_value.substr(p, q - p));
156 p = scan_quoted_or_unquoted_string(value, field_value, q + 1);
157 (*tokens)[token] = value;
160 while (p < field_value.length() &&
161 (field_value[p] ==
',' || isspace(field_value[p]))) {
167 scheme = HTTPChannel::downcase(field_value.substr(p, q - p));
168 tokens = &(schemes[scheme]);
184 get_canonical_url(
const URLSpec &url) {
200 string HTTPAuthorization::
201 base64_encode(
const string &s) {
204 size_t num_words = (s.size() + 2) / 3;
206 result.reserve(num_words * 4);
208 for (p = 0; p + 2 < s.size(); p += 3) {
210 ((unsigned)s[p] << 16) |
211 ((unsigned)s[p + 1] << 8) |
212 ((unsigned)s[p + 2]);
213 result += base64_table[(word >> 18) & 0x3f];
214 result += base64_table[(word >> 12) & 0x3f];
215 result += base64_table[(word >> 6) & 0x3f];
216 result += base64_table[(word) & 0x3f];
220 unsigned int word = ((unsigned)s[p] << 16);
223 word |= ((unsigned)s[p] << 8);
225 nassertr(p == s.size(), result);
227 result += base64_table[(word >> 18) & 0x3f];
228 result += base64_table[(word >> 12) & 0x3f];
229 result += base64_table[(word >> 6) & 0x3f];
232 result += base64_table[(word >> 18) & 0x3f];
233 result += base64_table[(word >> 12) & 0x3f];
247 string HTTPAuthorization::
248 base64_decode(
const string &s) {
250 if (!got_base64_invert) {
252 for (i = 0; i < 128; i++) {
253 base64_invert[i] = 0xff;
256 for (
int i = 0; i < 64; i++) {
257 base64_invert[(int)base64_table[i]] = i;
260 base64_invert[(int)
'='] = 0;
262 got_base64_invert =
true;
267 size_t num_words = s.size() / 4;
269 result.reserve(num_words * 3);
271 for (p = 0; p < s.size(); p += 4) {
272 unsigned int c0 = base64_invert[s[p] & 0x7f];
273 unsigned int c1 = base64_invert[s[p + 1] & 0x7f];
274 unsigned int c2 = base64_invert[s[p + 2] & 0x7f];
275 unsigned int c3 = base64_invert[s[p + 3] & 0x7f];
278 (c0 << 18) | (c1 << 12) | (c2 << 6) | c3;
280 result += (char)((word >> 16) & 0xff);
281 if (s[p + 2] !=
'=') {
282 result += (char)((word >> 8) & 0xff);
283 if (s[p + 3] !=
'=') {
284 result += (char)(word & 0xff);
303 size_t HTTPAuthorization::
304 scan_quoted_or_unquoted_string(
string &result,
const string &source,
308 if (start < source.length()) {
309 if (source[start] ==
'"') {
311 size_t p = start + 1;
312 while (p < source.length() && source[p] !=
'"') {
313 if (source[p] ==
'\\') {
316 if (p < source.length()) {
325 if (p < source.length()) {
333 while (p < source.length() && source[p] !=
',' && !isspace(source[p])) {
345 #endif // HAVE_OPENSSL A container for a URL, e.g.
int get_port() const
Returns the port number specified by the URL, or the default port if not specified.
string get_path() const
Returns the path specified by the URL, or "/" if no path is specified.
void set_scheme(const string &scheme)
Replaces the scheme part of the URL specification.
const string & get_url() const
Returns the complete URL specification.
string get_scheme() const
Returns the scheme specified by the URL, or empty string if no scheme is specified.
void set_path(const string &path)
Replaces the path part of the URL specification.
void set_port(const string &port)
Replaces the port part of the URL specification.
void set_username(const string &username)
Replaces the username part of the URL specification.