00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "httpAuthorization.h"
00020 #include "httpChannel.h"
00021 #include "urlSpec.h"
00022
00023 #ifdef HAVE_SSL
00024
00025 static const char base64_table[64] = {
00026 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
00027 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
00028 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
00029 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
00030 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00031 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
00032 'w', 'x', 'y', 'z', '0', '1', '2', '3',
00033 '4', '5', '6', '7', '8', '9', '+', '/',
00034 };
00035
00036
00037
00038
00039
00040
00041 HTTPAuthorization::
00042 HTTPAuthorization(const HTTPAuthorization::Tokens &tokens,
00043 const URLSpec &url, bool is_proxy) {
00044 Tokens::const_iterator ti;
00045 ti = tokens.find("realm");
00046 if (ti != tokens.end()) {
00047 _realm = (*ti).second;
00048 }
00049
00050 URLSpec canon = get_canonical_url(url);
00051
00052 ti = tokens.find("domain");
00053 if (ti != tokens.end() && !is_proxy) {
00054
00055
00056 const string &domain = (*ti).second;
00057 size_t p = 0;
00058 while (p < domain.length()) {
00059 while (p < domain.length() && isspace(domain[p])) {
00060 ++p;
00061 }
00062 size_t q = p;
00063 while (q < domain.length() && !isspace(domain[q])) {
00064 ++q;
00065 }
00066 if (q > p) {
00067 string domain_str = domain.substr(p, q - p);
00068 URLSpec domain_url(domain_str);
00069 if (domain_url.has_server()) {
00070
00071 _domain.push_back(get_canonical_url(domain_url).get_url());
00072 } else {
00073
00074 domain_url = canon;
00075 domain_url.set_path(domain_str);
00076 _domain.push_back(domain_url.get_url());
00077 }
00078 }
00079 p = q;
00080 }
00081
00082 } else {
00083
00084
00085 string canon_str = canon.get_url();
00086 size_t slash = canon_str.rfind('/');
00087 nassertv(slash != string::npos);
00088 _domain.push_back(canon_str.substr(0, slash + 1));
00089 }
00090 }
00091
00092
00093
00094
00095
00096
00097 HTTPAuthorization::
00098 ~HTTPAuthorization() {
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 bool HTTPAuthorization::
00110 is_valid() {
00111 return true;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120 void HTTPAuthorization::
00121 parse_authentication_schemes(HTTPAuthorization::AuthenticationSchemes &schemes,
00122 const string &field_value) {
00123
00124
00125
00126
00127
00128
00129
00130
00131 size_t p = 0;
00132 while (p < field_value.length() && isspace(field_value[p])) {
00133 ++p;
00134 }
00135
00136 if (p < field_value.length()) {
00137 size_t q = p;
00138 while (q < field_value.length() && !isspace(field_value[q])) {
00139 ++q;
00140 }
00141
00142 string scheme = HTTPChannel::downcase(field_value.substr(p, q - p));
00143 Tokens *tokens = &(schemes[scheme]);
00144
00145
00146 p = q + 1;
00147 while (p < field_value.length()) {
00148 q = p;
00149 while (q < field_value.length() && field_value[q] != '=' &&
00150 field_value[q] != ',' && !isspace(field_value[q])) {
00151 ++q;
00152 }
00153 if (field_value[q] == '=') {
00154
00155 string token = HTTPChannel::downcase(field_value.substr(p, q - p));
00156 string value;
00157 p = scan_quoted_or_unquoted_string(value, field_value, q + 1);
00158 (*tokens)[token] = value;
00159
00160
00161 while (p < field_value.length() &&
00162 (field_value[p] == ',' || isspace(field_value[p]))) {
00163 ++p;
00164 }
00165
00166 } else {
00167
00168 scheme = HTTPChannel::downcase(field_value.substr(p, q - p));
00169 tokens = &(schemes[scheme]);
00170 p = q + 1;
00171 }
00172 }
00173 }
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 URLSpec HTTPAuthorization::
00185 get_canonical_url(const URLSpec &url) {
00186 URLSpec canon = url;
00187 canon.set_scheme(canon.get_scheme());
00188 canon.set_username(string());
00189 canon.set_port(canon.get_port());
00190 canon.set_path(canon.get_path());
00191
00192 return canon;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201 string HTTPAuthorization::
00202 base64_encode(const string &s) {
00203
00204
00205 size_t num_words = (s.size() + 2) / 3;
00206 string result;
00207 result.reserve(num_words * 4);
00208 size_t p;
00209 for (p = 0; p + 2 < s.size(); p += 3) {
00210 unsigned int word =
00211 ((unsigned)s[p] << 16) |
00212 ((unsigned)s[p + 1] << 8) |
00213 ((unsigned)s[p + 2]);
00214 result += base64_table[(word >> 18) & 0x3f];
00215 result += base64_table[(word >> 12) & 0x3f];
00216 result += base64_table[(word >> 6) & 0x3f];
00217 result += base64_table[(word) & 0x3f];
00218 }
00219
00220 if (p < s.size()) {
00221 unsigned int word = ((unsigned)s[p] << 16);
00222 p++;
00223 if (p < s.size()) {
00224 word |= ((unsigned)s[p] << 8);
00225 p++;
00226 nassertr(p == s.size(), result);
00227
00228 result += base64_table[(word >> 18) & 0x3f];
00229 result += base64_table[(word >> 12) & 0x3f];
00230 result += base64_table[(word >> 6) & 0x3f];
00231 result += '=';
00232 } else {
00233 result += base64_table[(word >> 18) & 0x3f];
00234 result += base64_table[(word >> 12) & 0x3f];
00235 result += '=';
00236 result += '=';
00237 }
00238 }
00239
00240 return result;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 size_t HTTPAuthorization::
00255 scan_quoted_or_unquoted_string(string &result, const string &source,
00256 size_t start) {
00257 result = string();
00258
00259 if (start < source.length()) {
00260 if (source[start] == '"') {
00261
00262 size_t p = start + 1;
00263 while (p < source.length() && source[p] != '"') {
00264 if (source[p] == '\\') {
00265
00266 ++p;
00267 if (p < source.length()) {
00268 result += source[p];
00269 ++p;
00270 }
00271 } else {
00272 result += source[p];
00273 ++p;
00274 }
00275 }
00276 if (p < source.length()) {
00277 ++p;
00278 }
00279 return p;
00280 }
00281
00282
00283 size_t p = start;
00284 while (p < source.length() && source[p] != ',' && !isspace(source[p])) {
00285 result += source[p];
00286 ++p;
00287 }
00288
00289 return p;
00290 }
00291
00292
00293 return start;
00294 }
00295
00296 #endif // HAVE_SSL