summaryrefslogtreecommitdiffabout
path: root/lib/ax.cc
blob: ccdb706ac288e99e01cfbcc4f922a69bc15d14fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <opkele/exception.h>
#include <opkele/ax.h>
#include <opkele/uris.h>
#include <opkele/util.h>

#include <map>
#include <string>
#include <vector>

using namespace std;

namespace opkele {

    void ax_t::add_attribute(const char *uri, bool required, const char *alias /* = NULL */, int count /* = 1 */) {
	assert(uri && *uri);
	assert(count != 0);

	ax_attr_t attr;
	attr.uri = uri;
	attr.required = required;
	attr.count = count;
	// if no alias is specified, generate one using an internal auto-incremented counter
	attr.alias = alias ? alias : string("attr") + opkele::util::long_to_string(++alias_count);
	
	attrs.push_back(attr);
    }

    void ax_t::rp_checkid_hook(basic_openid_message& om) {
	if (attrs.size() == 0) return; // not asking for any attributes

	string pfx = om.allocate_ns(OIURI_AX10,"ax");
	om.set_field(pfx+".mode", "fetch_request"); // only supports fetch_request for now

	string required_fields, optional_fields;
	for (size_t i = 0; i < attrs.size(); i++) {
            // build up list of required/optional aliases
	    if (attrs[i].required) required_fields += (required_fields.empty() ? "" : ",") + attrs[i].alias;
	    else optional_fields += (optional_fields.empty() ? "" : ",") + attrs[i].alias;

	    om.set_field(pfx+".type."+attrs[i].alias, attrs[i].uri);

            // only specify count if it's >1 or unlimited
	    if (attrs[i].count == UNLIMITED_COUNT) {
		om.set_field(pfx+".count."+attrs[i].alias, "unlimited");
	    } else if (attrs[i].count > 1) {
		om.set_field(pfx+".count."+attrs[i].alias, opkele::util::long_to_string(attrs[i].count));
	    }
	}

	if (!required_fields.empty()) om.set_field(pfx+".required", required_fields);
	if (!optional_fields.empty()) om.set_field(pfx+".if_available", optional_fields);

	if (!update_url.empty()) om.set_field(pfx+".update_url", update_url);
    }

    void ax_t::checkid_hook(basic_openid_message& om) {
	rp_checkid_hook(om); }

    void ax_t::rp_id_res_hook(const basic_openid_message& om,
	    const basic_openid_message& sp) {
	string pfx;
	try {
	    pfx = om.find_ns(OIURI_AX10,"ax");
	}catch(failed_lookup&) {
		return;
	}
	pfx += '.';

	// first look at all aliases and generate an internal uri->alias map
	string fn;
	map<string, string> aliases;
	for (basic_openid_message::fields_iterator it = sp.fields_begin(); it != sp.fields_end(); ++it) {
	    fn = *it;
	    string type_pfx = pfx; type_pfx += "type.";
	    size_t pos = fn.find(type_pfx);
	    if (pos == string::npos) continue;
            string alias = fn.substr(pos + type_pfx.size());
            aliases[sp.get_field(fn)] = alias;
	}

	// now for each alias, pull out the count and value(s) and store uri->[value1, ...]
	for (map<string, string>::iterator it = aliases.begin(); it != aliases.end(); ++it) {
	    vector<string> values;
	    fn = pfx; fn += "count." + it->second;
	    if (sp.has_field(fn)) {
	        int count = opkele::util::string_to_long(sp.get_field(fn));
		for (int i = 1; i <= count; i++) {
		    fn = pfx; fn += "value." + it->second + "." + opkele::util::long_to_string(i);
		    values.push_back(sp.get_field(fn));
		}
	    } else {
		fn = pfx; fn += "value." + it->second;
		values.push_back(sp.get_field(fn));
	    }
	    response_attrs[it->first] = values;
	}

	fn = pfx; fn += "update_url";
	if (sp.has_field(fn)) update_url = sp.get_field(fn);
    }

    string ax_t::get_attribute(const char *uri, int index /* = 0 */) {
	if (response_attrs.find(uri) == response_attrs.end()) return "";
	return response_attrs[uri][index];
    }

    size_t ax_t::get_attribute_count(const char *uri) {
	if (response_attrs.find(uri) == response_attrs.end()) return 0;
	return response_attrs[uri].size();
    }

    void ax_t::id_res_hook(const basic_openid_message& om,
	    const basic_openid_message& sp) {
	rp_id_res_hook(om,sp); }

    void ax_t::op_checkid_hook(const basic_openid_message& inm) {
    }

    void ax_t::op_id_res_hook(basic_openid_message& oum) {
    }

    void ax_t::checkid_hook(const basic_openid_message& inm,
	    basic_openid_message& oum) {
	op_checkid_hook(inm);
        setup_response(inm,oum);
	op_id_res_hook(oum);
    }

    void ax_t::setup_response(const basic_openid_message& /* inm */,basic_openid_message& /* oum */) {
	setup_response();
    }
    void ax_t::setup_response() {
    }
}