Created
May 11, 2010 08:01
-
-
Save davidrecordon/397042 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
error_reporting(E_ALL|E_STRICT); | |
$input = "david@davidrecordon.com"; | |
$input = "https://davidrecordon.com"; | |
$input = "www.davidrecordon.com"; | |
$parsed = parse_input($input); | |
$after = normalize_input($parsed); | |
echo $input . ' -> ' . $after . "\n"; | |
$curl = curl_init(); | |
if (!$curl) { | |
die("No curl!\n"); | |
} | |
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); | |
$user_endpoint = discover_endpoint($curl, $parsed['scheme'], $parsed['domain'], $after); | |
echo " endpoint: $user_endpoint\n"; | |
function parse_input($input) { | |
$url = @parse_url($input); | |
if (!$url) { | |
die("That isn't a valid identifier!\n"); | |
} | |
if (isset($url['user']) || isset($url['pass'])) { | |
die("We don't support username:password syntax.\n"); | |
} | |
if (isset($url['fragment'])) { | |
die("We don't support URL fragments.\n"); | |
} | |
if (isset($url['query'])) { | |
die("Query parameters in OpenIDs are a bad idea!\n"); | |
} | |
$identifier = array( | |
'scheme' => NULL, | |
'user' => NULL, | |
'domain' => NULL, | |
'port' => NULL, | |
'path' => NULL, | |
); | |
// email? | |
if (strstr($url['path'], '@')) { | |
list($user, $domain) = preg_split('/@/', $url['path']); | |
$identifier['scheme'] = 'acct'; | |
$identifier['user'] = $user; | |
$identifier['domain'] = $domain; | |
} else { // some form of URL | |
if (isset($url['host'])) { | |
$identifier['scheme'] = strtolower($url['scheme']); | |
$identifier['domain'] = $url['host']; | |
$identifier['port'] = isset($url['port']) ? $url['port'] : NULL; | |
$identifier['path'] = isset($url['path']) ? $url['path'] : NULL; | |
} elseif (isset($url['path'])) { // user didn't include a scheme | |
if (strstr($url['path'], '/')) { | |
list($domain, $path) = preg_split('/\//', $url['path']); | |
} else { | |
$domain = $url['path']; | |
$path = NULL; | |
} | |
$identifier['scheme'] = 'http'; | |
$identifier['domain'] = $domain; | |
$identifier['port'] = isset($url['port']) ? $url['port'] : NULL; | |
$identifier['path'] = $path ? '/' . $path : NULL; | |
} | |
} | |
// make sure we got something | |
if (!$identifier['domain']) { | |
die("Not sure what you gave us: $input\n"); | |
} | |
// make sure we ended up with a valid scheme | |
if (!in_array($identifier['scheme'], array('http', 'https', 'acct'))) { | |
die("Invalid URI scheme\n"); | |
} | |
return $identifier; | |
} | |
// turn what we figured out the user entered into a canonicalized string | |
function normalize_input($parsed) { | |
$identifier = ''; | |
if ($parsed['scheme'] == 'acct') { | |
$identifier = 'acct:' . $parsed['user'] . '@' . $parsed['domain']; | |
} else { | |
$identifier = $parsed['scheme'] . '://' . $parsed['domain']; | |
if ($parsed['port']) { | |
$identifier .= ':' . $parsed['port']; | |
} | |
$identifier .= $parsed['path']; | |
} | |
return $identifier; | |
} | |
function discover_endpoint($curl, $scheme, $domain, $identifier) { | |
// first try SSL | |
curl_setopt($curl, CURLOPT_URL, 'https://' . $domain . '/.well-known/host-meta.json'); | |
$host_meta = curl_exec($curl); | |
// don't fallback to HTTP if the user explicitly said HTTPS | |
if (!$host_meta && $scheme != 'https') { | |
curl_setopt($curl, CURLOPT_URL, 'http://' . $domain . '/.well-known/host-meta.json'); | |
$host_meta = curl_exec($curl); | |
} | |
if (!$host_meta || !isset($host_meta['lrdd'])) { | |
die("Couldn't find a valid host meta file for your domain: $domain\n"); | |
} | |
$host_meta = json_decode($host_meta, true); | |
// Host-priority is the default if it isn't set | |
if ($host_meta['lrdd']['priority'] == 'Resource-priority') { | |
if ($lrdd = _fetch_lrdd($curl, $host_meta, $identifier)) { | |
if (isset($lrdd['openid'])) { | |
return $lrdd['openid']['href']; | |
} | |
} | |
if ($endpoint = _fetch_identifier($curl, $identifier)) { | |
return $endpoint; | |
} | |
} else { | |
if ($endpoint = _fetch_identifier($curl, $identifier)) { | |
return $endpoint; | |
} | |
if ($lrdd = _fetch_lrdd($curl, $host_meta, $identifier)) { | |
if (isset($lrdd['openid'])) { | |
return $lrdd['openid']['href']; | |
} | |
} | |
} | |
return false; | |
} | |
function _fetch_lrdd($curl, $host_meta, $identifier) { | |
if (!isset($host_meta['lrdd']['template'])) { | |
die("No LRDD template.\n"); | |
} | |
$url = str_replace('{uri}', $identifier, $host_meta['lrdd']['template']); | |
curl_setopt($curl, CURLOPT_URL, $url); | |
$json = curl_exec($curl); | |
$lrdd = json_decode($json, true); | |
if ($lrdd['lrdd']['subject'] != $identifier) { | |
die("LRDD subject doesn't match...but it should!\n"); | |
} | |
return $lrdd; | |
} | |
function _fetch_identifier($curl, $identifier) { | |
// can't fetch emails | |
if (preg_match('/^acct:/', $identifier)) { | |
return false; | |
} | |
curl_setopt($curl, CURLOPT_URL, $identifier); | |
$html = curl_exec($curl); | |
if (!$html) { | |
die("Couldn't fetch the identifier: $identifier\n"); | |
} | |
// this now needs to parse the dom and look for a link tag in the head | |
// with a rel of openid. then return the href value or false | |
return false; | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment