Skip to content

Instantly share code, notes, and snippets.

@davidrecordon
Created May 11, 2010 08:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidrecordon/397042 to your computer and use it in GitHub Desktop.
Save davidrecordon/397042 to your computer and use it in GitHub Desktop.
<?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