-rw-r--r-- | lib/ax.cc | 135 | ||||
-rw-r--r-- | lib/oauth_ext.cc | 75 |
2 files changed, 210 insertions, 0 deletions
diff --git a/lib/ax.cc b/lib/ax.cc new file mode 100644 index 0000000..ccdb706 --- a/dev/null +++ b/lib/ax.cc | |||
@@ -0,0 +1,135 @@ | |||
1 | #include <opkele/exception.h> | ||
2 | #include <opkele/ax.h> | ||
3 | #include <opkele/uris.h> | ||
4 | #include <opkele/util.h> | ||
5 | |||
6 | #include <map> | ||
7 | #include <string> | ||
8 | #include <vector> | ||
9 | |||
10 | using namespace std; | ||
11 | |||
12 | namespace opkele { | ||
13 | |||
14 | void ax_t::add_attribute(const char *uri, bool required, const char *alias /* = NULL */, int count /* = 1 */) { | ||
15 | assert(uri && *uri); | ||
16 | assert(count != 0); | ||
17 | |||
18 | ax_attr_t attr; | ||
19 | attr.uri = uri; | ||
20 | attr.required = required; | ||
21 | attr.count = count; | ||
22 | // if no alias is specified, generate one using an internal auto-incremented counter | ||
23 | attr.alias = alias ? alias : string("attr") + opkele::util::long_to_string(++alias_count); | ||
24 | |||
25 | attrs.push_back(attr); | ||
26 | } | ||
27 | |||
28 | void ax_t::rp_checkid_hook(basic_openid_message& om) { | ||
29 | if (attrs.size() == 0) return; // not asking for any attributes | ||
30 | |||
31 | string pfx = om.allocate_ns(OIURI_AX10,"ax"); | ||
32 | om.set_field(pfx+".mode", "fetch_request"); // only supports fetch_request for now | ||
33 | |||
34 | string required_fields, optional_fields; | ||
35 | for (size_t i = 0; i < attrs.size(); i++) { | ||
36 | // build up list of required/optional aliases | ||
37 | if (attrs[i].required) required_fields += (required_fields.empty() ? "" : ",") + attrs[i].alias; | ||
38 | else optional_fields += (optional_fields.empty() ? "" : ",") + attrs[i].alias; | ||
39 | |||
40 | om.set_field(pfx+".type."+attrs[i].alias, attrs[i].uri); | ||
41 | |||
42 | // only specify count if it's >1 or unlimited | ||
43 | if (attrs[i].count == UNLIMITED_COUNT) { | ||
44 | om.set_field(pfx+".count."+attrs[i].alias, "unlimited"); | ||
45 | } else if (attrs[i].count > 1) { | ||
46 | om.set_field(pfx+".count."+attrs[i].alias, opkele::util::long_to_string(attrs[i].count)); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | if (!required_fields.empty()) om.set_field(pfx+".required", required_fields); | ||
51 | if (!optional_fields.empty()) om.set_field(pfx+".if_available", optional_fields); | ||
52 | |||
53 | if (!update_url.empty()) om.set_field(pfx+".update_url", update_url); | ||
54 | } | ||
55 | |||
56 | void ax_t::checkid_hook(basic_openid_message& om) { | ||
57 | rp_checkid_hook(om); } | ||
58 | |||
59 | void ax_t::rp_id_res_hook(const basic_openid_message& om, | ||
60 | const basic_openid_message& sp) { | ||
61 | string pfx; | ||
62 | try { | ||
63 | pfx = om.find_ns(OIURI_AX10,"ax"); | ||
64 | }catch(failed_lookup&) { | ||
65 | return; | ||
66 | } | ||
67 | pfx += '.'; | ||
68 | |||
69 | // first look at all aliases and generate an internal uri->alias map | ||
70 | string fn; | ||
71 | map<string, string> aliases; | ||
72 | for (basic_openid_message::fields_iterator it = sp.fields_begin(); it != sp.fields_end(); ++it) { | ||
73 | fn = *it; | ||
74 | string type_pfx = pfx; type_pfx += "type."; | ||
75 | size_t pos = fn.find(type_pfx); | ||
76 | if (pos == string::npos) continue; | ||
77 | string alias = fn.substr(pos + type_pfx.size()); | ||
78 | aliases[sp.get_field(fn)] = alias; | ||
79 | } | ||
80 | |||
81 | // now for each alias, pull out the count and value(s) and store uri->[value1, ...] | ||
82 | for (map<string, string>::iterator it = aliases.begin(); it != aliases.end(); ++it) { | ||
83 | vector<string> values; | ||
84 | fn = pfx; fn += "count." + it->second; | ||
85 | if (sp.has_field(fn)) { | ||
86 | int count = opkele::util::string_to_long(sp.get_field(fn)); | ||
87 | for (int i = 1; i <= count; i++) { | ||
88 | fn = pfx; fn += "value." + it->second + "." + opkele::util::long_to_string(i); | ||
89 | values.push_back(sp.get_field(fn)); | ||
90 | } | ||
91 | } else { | ||
92 | fn = pfx; fn += "value." + it->second; | ||
93 | values.push_back(sp.get_field(fn)); | ||
94 | } | ||
95 | response_attrs[it->first] = values; | ||
96 | } | ||
97 | |||
98 | fn = pfx; fn += "update_url"; | ||
99 | if (sp.has_field(fn)) update_url = sp.get_field(fn); | ||
100 | } | ||
101 | |||
102 | string ax_t::get_attribute(const char *uri, int index /* = 0 */) { | ||
103 | if (response_attrs.find(uri) == response_attrs.end()) return ""; | ||
104 | return response_attrs[uri][index]; | ||
105 | } | ||
106 | |||
107 | size_t ax_t::get_attribute_count(const char *uri) { | ||
108 | if (response_attrs.find(uri) == response_attrs.end()) return 0; | ||
109 | return response_attrs[uri].size(); | ||
110 | } | ||
111 | |||
112 | void ax_t::id_res_hook(const basic_openid_message& om, | ||
113 | const basic_openid_message& sp) { | ||
114 | rp_id_res_hook(om,sp); } | ||
115 | |||
116 | void ax_t::op_checkid_hook(const basic_openid_message& inm) { | ||
117 | } | ||
118 | |||
119 | void ax_t::op_id_res_hook(basic_openid_message& oum) { | ||
120 | } | ||
121 | |||
122 | void ax_t::checkid_hook(const basic_openid_message& inm, | ||
123 | basic_openid_message& oum) { | ||
124 | op_checkid_hook(inm); | ||
125 | setup_response(inm,oum); | ||
126 | op_id_res_hook(oum); | ||
127 | } | ||
128 | |||
129 | void ax_t::setup_response(const basic_openid_message& /* inm */,basic_openid_message& /* oum */) { | ||
130 | setup_response(); | ||
131 | } | ||
132 | void ax_t::setup_response() { | ||
133 | } | ||
134 | } | ||
135 | |||
diff --git a/lib/oauth_ext.cc b/lib/oauth_ext.cc new file mode 100644 index 0000000..b728854 --- a/dev/null +++ b/lib/oauth_ext.cc | |||
@@ -0,0 +1,75 @@ | |||
1 | #include <opkele/exception.h> | ||
2 | #include <opkele/oauth_ext.h> | ||
3 | #include <opkele/uris.h> | ||
4 | #include <algorithm> | ||
5 | |||
6 | namespace opkele { | ||
7 | using std::find; | ||
8 | |||
9 | void oauth_ext_t::rp_checkid_hook(basic_openid_message& om) { | ||
10 | |||
11 | string pfx = om.allocate_ns(OIURI_OAUTH10,"oauth"); | ||
12 | //required: openid.oauth.consumer=www.plaxo.com | ||
13 | //optional: openid.oauth.scope=http://www.google.com/m8/feeds/ | ||
14 | if (m_consumer.empty()) throw bad_input(OPKELE_CP_ "Required consumer key is missing from OAuth extension"); | ||
15 | om.set_field(pfx+".consumer", m_consumer); | ||
16 | if (!m_scope.empty()) om.set_field(pfx+".scope", m_scope); | ||
17 | } | ||
18 | |||
19 | void oauth_ext_t::checkid_hook(basic_openid_message& om) { | ||
20 | rp_checkid_hook(om); } | ||
21 | |||
22 | void oauth_ext_t::rp_id_res_hook(const basic_openid_message& om, | ||
23 | const basic_openid_message& sp) { | ||
24 | string pfx; | ||
25 | try { | ||
26 | pfx = om.get_ns(OIURI_OAUTH10); | ||
27 | }catch(failed_lookup&) { | ||
28 | return; | ||
29 | } | ||
30 | pfx += '.'; | ||
31 | //required: openid.oauth.request_token=abcdefg | ||
32 | //optional: openid.oauth.consumer=www.plaxo.com | ||
33 | //optional: openid.oauth.scope=http://www.google.com/m8/feeds/ | ||
34 | string fn; | ||
35 | |||
36 | fn = pfx + "request_token"; | ||
37 | if (sp.has_field(fn)) { | ||
38 | m_request_token = sp.get_field(fn); | ||
39 | } else throw bad_input(OPKELE_CP_ "Missing required response field: "+fn); | ||
40 | |||
41 | fn = pfx + "consumer"; | ||
42 | if (sp.has_field(fn)) { | ||
43 | m_consumer = sp.get_field(fn); | ||
44 | } | ||
45 | |||
46 | fn = pfx + "scope"; | ||
47 | if (sp.has_field(fn)) { | ||
48 | m_scope = sp.get_field(fn); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | void oauth_ext_t::id_res_hook(const basic_openid_message& om, | ||
53 | const basic_openid_message& sp) { | ||
54 | rp_id_res_hook(om,sp); } | ||
55 | |||
56 | void oauth_ext_t::op_checkid_hook(const basic_openid_message& inm) { | ||
57 | } | ||
58 | |||
59 | void oauth_ext_t::op_id_res_hook(basic_openid_message& oum) { | ||
60 | } | ||
61 | |||
62 | void oauth_ext_t::checkid_hook(const basic_openid_message& inm, | ||
63 | basic_openid_message& oum) { | ||
64 | op_checkid_hook(inm); | ||
65 | setup_response(inm,oum); | ||
66 | op_id_res_hook(oum); | ||
67 | } | ||
68 | |||
69 | void oauth_ext_t::setup_response(const basic_openid_message& /* inm */,basic_openid_message& /* oum */) { | ||
70 | setup_response(); | ||
71 | } | ||
72 | void oauth_ext_t::setup_response() { | ||
73 | } | ||
74 | } | ||
75 | |||