PluginProbe
WebFinger / 1.2
WebFinger v1.2
4.1.0 trunk 0.5 0.7 0.9 0.9.1 1.0 1.0.1 1.1 1.2 1.3 1.3.1 2.0.0 2.0.1 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 All 36 releases
webfinger / plugin.php

plugin.php in WebFinger 1.2, at plugin.php

427 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Webfinger
4 Plugin URI: http://wordpress.org/extend/plugins/webfinger/
5 Description: Webfinger for WordPress
6 Version: 1.2
7 Author: Matthias Pfefferle
8 Author URI: http://notizblog.org/
9 */
10
11 /**
12 * returns a users default webfinger
13 *
14 * @param mixed $id_or_name_or_object
15 * @param boolean $protocol
16 * @return string
17 */
18 function get_webfinger($id_or_name_or_object = null, $protocol = false) {
19 $webfinger = new WebfingerPlugin();
20 $user = $webfinger->get_user_by_various($id_or_name_or_object);
21
22 if ($user) {
23 $webfinger = $user->user_login."@".parse_url(get_bloginfo('url'), PHP_URL_HOST);
24 if ($protocol) {
25 $webfinger = "acct:".$webfinger;
26 }
27 return $webfinger;
28 } else {
29 return null;
30 }
31 }
32
33 /**
34 * returns all webfingers
35 *
36 * @param mixed $id_or_name_or_object
37 * @param boolean $protocol
38 *
39 * @return array
40 */
41 function get_webfingers($id_or_name_or_object = null, $protocol = false) {
42 $webfinger = new WebfingerPlugin();
43 $user = $webfinger->get_user_by_various($id_or_name_or_object);
44 $webfingers = array();
45
46 if ($user) {
47 $webfingers[] = ($protocol ? "acct:" : "").get_webfinger($user);
48 $webfingers[] = get_author_posts_url($user->ID, $user->user_nicename);
49 $webfingers = apply_filters('webfingers', $webfingers);
50
51 return $webfingers;
52 } else {
53 return array();
54 }
55 }
56
57 /**
58 * webfinger
59 *
60 * @author Matthias Pfefferle
61 */
62 class WebfingerPlugin {
63
64 private $user;
65 private $webfinger_uri;
66
67
68 /**
69 * adds some query vars
70 *
71 * @param array $vars
72 * @return array
73 */
74 public function query_vars($vars) {
75 $vars[] = 'webfinger-uri';
76 $vars[] = 'webfinger';
77 $vars[] = 'format';
78 $vars[] = 'principal';
79 $vars[] = 'service';
80 return $vars;
81 }
82
83 /**
84 * parses the request
85 *
86 * @return mixed
87 */
88 public function parse_request() {
89 global $wp_query, $wp;
90
91 $query_vars = $wp->query_vars;
92
93 if( array_key_exists('webfinger-uri', $query_vars) ) {
94 if (!$this->user = $this->get_user_by_uri($query_vars['webfinger-uri'])) {
95 header("HTTP/1.0 404 Not Found");
96 echo "Not Found";
97 exit;
98 }
99
100 $this->webfinger_uri = $query_vars['webfinger-uri'];
101 $accept = explode(',', $_SERVER['HTTP_ACCEPT']);
102
103 if (in_array('application/json', $accept) || (array_key_exists('format', $query_vars) && $query_vars['format'] == "json")) {
104 $this->render_jrd();
105 } else {
106 $this->render_xrd();
107 }
108
109 exit;
110 }
111 }
112
113 public function render_simple_web_discovery($request) {
114 $this->user = $this->get_user_by_uri($request['principal']);
115 $this->webfinger_uri = $request['principal'];
116
117 if ($this->user) {
118 $content = $this->generate_content();
119
120 $swd = array();
121 foreach ($content['links'] as $link) {
122 if ($link['rel'] == $request['service']) {
123 $swd['locations'][] = $link['href'];
124 }
125 }
126
127 $swd = apply_filters('simple_web_discovery', $swd, $this->user, $request['service']);
128
129 if ($swd) {
130 header("Access-Control-Allow-Origin: *");
131 header('Content-Type: application/json; charset=' . get_option('blog_charset'), true);
132 echo json_encode($swd);
133 exit;
134 }
135 }
136
137 header("HTTP/1.0 404 Not Found");
138 echo "Not Found";
139 exit;
140 }
141
142 /**
143 * renders the webfinger file in xml
144 */
145 public function render_xrd() {
146 header("Access-Control-Allow-Origin: *");
147 header('Content-Type: application/xrd+xml; charset=' . get_option('blog_charset'), true);
148 $content_array = $this->generate_content();
149
150 echo "<?xml version='1.0' encoding='".get_option('blog_charset')."'?>\n";
151 echo "<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'\n";
152 // add xml-only namespaces
153 do_action('webfinger_ns');
154 echo ">\n";
155
156 echo $this->jrd_to_xrd($content_array);
157 // add xml-only content
158 do_action('webfinger_xrd', $this->user);
159
160 echo "\n</XRD>";
161 }
162
163 /**
164 * renders the webfinger file in json
165 */
166 public function render_jrd() {
167 header("Access-Control-Allow-Origin: *");
168 header('Content-Type: application/json; charset=' . get_option('blog_charset'), true);
169 $webfinger = $this->generate_content();
170
171 echo json_encode($webfinger);
172 }
173
174 /**
175 * generates the webfinger base array (and activate filter)
176 *
177 * @return array
178 */
179 public function generate_content() {
180 $url = get_author_posts_url($this->user->ID, $this->user->user_nicename);
181 $photo = get_user_meta($this->user->ID, 'photo', true);
182 if(!$photo) $photo = 'http://www.gravatar.com/avatar/'.md5($this->user->user_email);
183
184 $webfinger = array('subject' => $this->webfinger_uri,
185 'aliases' => array($url),
186 'links' => array(
187 array('rel' => 'http://webfinger.net/rel/profile-page', 'type' => 'text/html', 'href' => $url),
188 array('rel' => 'http://webfinger.net/rel/avatar', 'href' => $photo)
189 ));
190 if ($this->user->user_url) {
191 $webfinger['links'][] = array('rel' => 'http://webfinger.net/rel/profile-page', 'type' => 'text/html', 'href' => $this->user->user_url);
192 }
193 $webfinger = apply_filters('webfinger', $webfinger, $this->user);
194
195 return $webfinger;
196 }
197
198 /**
199 * recursive helper to generade the xrd-xml from the jrd array
200 *
201 * @param string $host_meta
202 * @return string
203 */
204 public function jrd_to_xrd($webfinger) {
205 $xrd = null;
206
207 foreach ($webfinger as $type => $content) {
208 // print subject
209 if ($type == "subject") {
210 $xrd .= "<Subject>$content</Subject>";
211 continue;
212 }
213
214 // print aliases
215 if ($type == "aliases") {
216 foreach ($content as $uri) {
217 $xrd .= "<Alias>".htmlentities($uri)."</Alias>";
218 }
219 continue;
220 }
221
222 // print properties
223 if ($type == "properties") {
224 foreach ($content as $type => $uri) {
225 $xrd .= "<Property type='".htmlentities($type)."'>".htmlentities($uri)."</Property>";
226 }
227 continue;
228 }
229
230 // print titles
231 if ($type == "titles") {
232 foreach ($content as $key => $value) {
233 if ($key == "default") {
234 $xrd .= "<Title>".htmlentities($value)."</Title>";
235 } else {
236 $xrd .= "<Title xml:lang='".htmlentities($key)."'>".htmlentities($value)."</Title>";
237 }
238 }
239 continue;
240 }
241
242 // print links
243 if ($type == "links") {
244 foreach ($content as $links) {
245 $temp = array();
246 $cascaded = false;
247 $xrd .= "<Link ";
248
249 foreach ($links as $key => $value) {
250 if (is_array($value)) {
251 $temp[$key] = $value;
252 $cascaded = true;
253 } else {
254 $xrd .= htmlentities($key)."='".htmlentities($value)."' ";
255 }
256 }
257 if ($cascaded) {
258 $xrd .= ">";
259 $xrd .= $this->jrd_to_xrd($temp);
260 $xrd .= "</Link>";
261 } else {
262 $xrd .= " />";
263 }
264 }
265
266 continue;
267 }
268 }
269
270 return $xrd;
271 }
272
273 /**
274 * returns a Userobject
275 *
276 * @param string $uri
277 * @return stdClass
278 */
279 private function get_user_by_uri($uri) {
280 global $wpdb;
281
282 $uri = urldecode($uri);
283
284 if (preg_match("~^https?://~i", $uri)) {
285 // check if url matches with a
286 // users profile url
287 foreach (get_users_of_blog() as $user) {
288 if (rtrim(str_replace("www.", "", get_author_posts_url($user->ID, $user->user_nicename)), "/") ==
289 rtrim(str_replace("www.", "", $uri), "/")) {
290 return $user;
291 }
292 }
293 } elseif (preg_match('/^([a-zA-Z]+:)?([^@]+)@([a-zA-Z0-9._-]+)$/i', $uri, $array)) {
294 $username = $array[2];
295 $host = $array[3];
296 $email = $username."@".$host;
297
298 if ($host == parse_url(get_bloginfo('url'), PHP_URL_HOST)) {
299 $sql = "SELECT * FROM $wpdb->users u INNER JOIN $wpdb->usermeta um ON u.id=um.user_id WHERE u.user_email = '$email' OR
300 (um.meta_key = 'jabber' AND um.meta_value = '$email') OR
301 u.user_login = '$username' LIMIT 1;";
302 $user = $wpdb->get_results($wpdb->prepare($sql));
303 if (!empty($user)) {
304 return $user[0];
305 }
306 }
307 }
308
309 return false;
310 }
311
312 /**
313 * add the host meta information
314 */
315 public function add_host_meta_link() {
316 echo "<Link rel='lrdd' template='".get_option('siteurl')."/?webfinger-uri={uri}' type='application/xrd+xml' />";
317 }
318
319 /**
320 * add the host meta information
321 */
322 public function add_host_meta_info($array) {
323 $array["links"][] = array("rel" => "lrdd", "template" => get_option('siteurl')."/?webfinger-uri={uri}", "type" => "application/xrd+xml");
324 $array["links"][] = array("rel" => "lrdd", "template" => get_option('siteurl')."/?webfinger-uri={uri}?format=json", "type" => "application/json");
325
326 return $array;
327 }
328
329 /**
330 * adds lrdd-header-link to author profile pages
331 */
332 public function add_html_link() {
333 global $wp_query;
334
335 if (is_author() && !is_feed()) {
336 $author = $wp_query->get_queried_object();
337 $url = get_author_posts_url($author->ID, $author->user_nicename);
338
339 echo "\n";
340 echo "<link rel='lrdd' href='".get_option('siteurl')."/?webfinger-uri=".urlencode($url)."' type='application/xrd+xml' />";
341 echo "\n";
342 }
343 }
344
345 /**
346 * prints webfinger part on the user-site
347 *
348 * @param stdClass $user
349 */
350 public function user_profile_infos($user) {
351 $webfingers = get_webfingers($user, true);
352 ?>
353 <h3 id="webfinger">Webfinger</h3>
354
355 <table class="form-table">
356 <tr>
357 <th scope="row"><?php _e('Your Identifier')?></th>
358 <td>
359 <ul>
360 <?php foreach ($webfingers as $webfinger) { ?>
361 <li><?php echo $webfinger ?></li>
362 <?php } ?>
363 </ul>
364
365 <a href="http://webfinger.org/lookup/<?php echo get_webfinger($user); ?>" target="_blank">Check your webfinger!</a>
366 </td>
367 </tr>
368 </table>
369 <?php
370 }
371
372 /**
373 * add a settings link next to deactive / edit
374 *
375 * @param array $links
376 * @param string $file
377 * @return array
378 */
379 public function settings_link( $links, $file ) {
380 if( preg_match("/webfinger/i", $file) && function_exists( "admin_url" ) ) {
381 $settings_link = '<a href="' . admin_url( 'profile.php#webfinger' ) . '">' . __('Identifiers') . '</a>';
382 array_unshift( $links, $settings_link );
383 }
384 return $links;
385 }
386
387 /**
388 * Convenience method to get user data by ID, username, object or from current user.
389 *
390 * @param mixed $id_or_name_or_object the username, ID or object. If not provided, the current user will be used.
391 * @return bool|object False on failure, User DB row object
392 *
393 * @author Will Norris
394 * @see get_userdata_by_various() # DiSo OpenID-Plugin
395 */
396 public function get_user_by_various($id_or_name_or_object = null) {
397 if ( $id_or_name_or_object === null ) {
398 $user = wp_get_current_user();
399 if ($user == null) return false;
400 return $user->data;
401 } else if ( is_object($id_or_name_or_object) ) {
402 return $id_or_name_or_object;
403 } else if ( is_numeric($id_or_name_or_object) ) {
404 return get_userdata($id_or_name_or_object);
405 } else {
406 return get_userdatabylogin($id_or_name_or_object);
407 }
408 }
409 }
410
411 function webfinger_init() {
412 $webfinger = new WebfingerPlugin();
413
414 add_action('well_known_simple-web-discovery', array(&$webfinger, 'render_simple_web_discovery'), 2);
415 add_filter('query_vars', array(&$webfinger, 'query_vars'));
416 add_action('parse_request', array(&$webfinger, 'parse_request'));
417 add_action('wp_head', array(&$webfinger, 'add_html_link'));
418 add_filter('host_meta', array(&$webfinger, 'add_host_meta_info'));
419 add_filter('plugin_action_links', array(&$webfinger, 'settings_link'), 10, 2);
420
421 // add profile parts
422 add_action('show_user_profile', array(&$webfinger, 'user_profile_infos'));
423 add_action('edit_user_profile', array(&$webfinger, 'user_profile_infos'));
424 }
425
426 webfinger_init();
427 ?>