From b3a0ff033060ac5716e43eb582c16be07928ac31 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Sun, 15 Apr 2012 02:29:24 +0200 Subject: [PATCH 1/3] Libravatar Addon Avatar addon to look up avatars at Libravatar. Libravatar is a free and open replacement for Gravatar and you can also host it on you own server. This addon only provides the lookup of avatars at Libravatar. It requires PHP >= 5.3 and you need to disable the gravatar addon. --- libravatar/README.md | 36 +++ libravatar/Services/Libravatar.php | 372 +++++++++++++++++++++++++++++ libravatar/admin.tpl | 2 + libravatar/libravatar.php | 115 +++++++++ 4 files changed, 525 insertions(+) create mode 100644 libravatar/README.md create mode 100644 libravatar/Services/Libravatar.php create mode 100644 libravatar/admin.tpl create mode 100644 libravatar/libravatar.php diff --git a/libravatar/README.md b/libravatar/README.md new file mode 100644 index 00000000..16fbd85a --- /dev/null +++ b/libravatar/README.md @@ -0,0 +1,36 @@ +# Libravatar Plugin +by [Klaus Weidenbach](http://friendica.dszdw.net/profile/klaus) + +This addon allows you to look up an avatar image for new users and contacts at [Libravatar](http://www.libravatar.com). It will be used if there have not been found any other avatar images yet for example through OpenID. + +Libravatar is a free and open replacement for Gravatar. It is a service where people can store an avatar image for their email-addresses. These avatar images can get looked up for example in comment functions, profile pages, etc. on other sites. There exists a central installation at [www.libravatar.com](http://www.libravatar.com), but you can also host it on your own server. If no avatar was found Libravatar will look up at Gravatar as a fallback. +There is no rating available, as it is on Gravatar, so all avatar lookups are g-rated. (Suitable for all audiences.) + +PHP >= 5.3 is required for this plugin! + +You can not use the Libravatar and Gravatar addon at the same time. You need to choose one. If you need other ratings than g you better stay with Gravatar, otherwise it is safe to use Libravatar, because it will fall back to Gravatar if nothing was found at Libravatar. + +* * * + +# Configuration +## Default Avatar Image +If no avatar was found for an email Libravatar can create some pseudo-random generated avatars based on an email hash. You can choose between these presets: + +* __MM__: (mystery-man) a static image +* __Identicon__: a generated geometric pattern based on email hash +* __Monsterid__: a generated 'monster' with different colors, faces, etc. based on email hash +* __Wavatar__: faces with different features and backgrounds based on email hash +* __Retro__: 8-bit arcade-styled pixelated faces based on email hash + +See examples at [Libravatar][1]. + +## Alternative Configuration +Open the .htconfig.php file and add "libravatar" to the list of activated addons: + + $a->config['system']['addon'] = "..., libravatar"; + +You can add one configuration variable for the addon: + + $a->config['libravatar']['default_avatar'] = "identicon"; + +[1]: http://wiki.libravatar.org/api/ "See API documentation at Libravatar for more information" diff --git a/libravatar/Services/Libravatar.php b/libravatar/Services/Libravatar.php new file mode 100644 index 00000000..d3024408 --- /dev/null +++ b/libravatar/Services/Libravatar.php @@ -0,0 +1,372 @@ + + * @copyright 2011 Services_Libravatar committers. + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version SVN: + * @link http://pear.php.net/package/Services_Libravatar + * @since File available since Release 0.1.0 + */ + +/** + * PHP support for the Libravatar.org service. + * + * Using this class is easy. After including or requiring + * PEAR/libravatar.php simply do: + * + * $libravatar = new Services_Libravatar(); + * $url = $libravatar->url('melissa@meldraweb.com'); + * + * + * This would populate $url with the string: + * http://cdn.libravatar.org/avatar/4db84629c121f2d443d33bdb9fd149bc + * + * A complicated lookup using all the options is: + * + * $libravatar = new Services_Libravatar(); + * $options = array(); + * $options['s'] = '40'; + * $options['algorithm'] = 'sha256'; + * $options['https'] = true; + * $options['d'] = 'http://upload.wikimedia.org/wikipedia/commons/a/af/Tux.png'; + * $url = $libravatar->url('melissa@meldraweb.com', $options); + * + * + * @category Services + * @package Services_Libravatar + * @author Melissa Draper + * @copyright 2011 Services_Libravatar committers. + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version Release: + * @link http://pear.php.net/package/Services_Libravatar + * @since Class available since Release 0.1.0 + */ +class Services_Libravatar +{ + + /** + * Composes a URL for the identifier and options passed in + * + * Compose a full URL as specified by the Libravatar API, based on the + * email address or openid URL passed in, and the options specified. + * + * @param string $identifier a string of either an email address + * or an openid url + * @param array $options an array of (bool) https, (string) algorithm + * (string) s or size, (string) d or default + * + * @return string A string of a full URL for an avatar image + * + * @since Method available since Release 0.1.0 + */ + public function url($identifier, $options = array()) + { + + // If no identifier has been passed, set it to a null. + // This way, there'll always be something returned. + if (!$identifier) { + $identifier = null; + } + + $https = null; + if (isset($options['https']) && $options['https'] === true) { + $https = true; + } + + // If the algorithm has been passed in $options, send it on. + // This will only affect email functionality. + if (isset($options['algorithm']) && is_string($options['algorithm'])) { + $identiferHash = $this->identiferHash( + $identifier, + $https, + $options['algorithm'] + ); + } else { + $identiferHash = $this->identiferHash($identifier, $https); + } + + // Get the domain so we can determine the SRV stuff for federation + $domain = $this->domainGet($identifier, $https); + + // If https has been specified in $options, make sure we make the + // correct SRV lookup + if (isset($options['https']) && $options['https'] === true) { + $service = $this->srvGet($domain, true); + $protocol = 'https'; + } else { + $service = $this->srvGet($domain); + $protocol = 'http'; + } + + // We no longer need these, and they will pollute our query string + unset($options['algorithm']); + unset($options['https']); + + // If there are any $options left, we want to make those into a query + $params = null; + if (count($options) > 0) { + $params = '?' . http_build_query($options); + } + + // Compose the URL from the pieces we generated + $url = $protocol . '://' . $service . '/avatar/' . $identiferHash . $params; + + // Return the URL string + return $url; + + } + + /** + * Create a hash of the identifier. + * + * Create a hash of the email address or openid passed in. Algorithm + * used for email address ONLY can be varied. Either md5 or sha256 + * are supported by the Libravatar API. Will be ignored for openid. + * + * @param string $identifier A string of the email address or openid URL + * @param boolean $https If this is https, true. + * @param string $hash A string of the hash algorithm type to make + * + * @return string A string hash of the identifier. + * + * @since Method available since Release 0.1.0 + */ + protected function identiferHash($identifier, $https = false, $hash = 'md5') + { + + if (filter_var($identifier, FILTER_VALIDATE_EMAIL)) { + // If email, we can select our algorithm. Default to md5 for + // gravatar fallback. + return hash($hash, $identifier); + } else { + + // The protocol is important. If we're lacking it this will not be + // filtered. Add it per our preference in the options. + if (stripos($identifier, 'http') !== 0) { + if ($https === true) { + $protocol = 'https://'; + } else { + $protocol = 'http://'; + } + $identifier = $protocol . $identifier; + } + + // Is this an email address or an OpenID account + $filter = filter_var( + $identifier, + FILTER_VALIDATE_URL, + FILTER_FLAG_PATH_REQUIRED + ); + + if ($filter) { + // If this is an OpenID, split the string and make sure the + // formatting is correct. See the Libravatar API for more info. + // http://wiki.libravatar.org/api/ + $url = parse_url($identifier); + $hashurl = strtolower($url['scheme']) . '://' . + strtolower($url['host']); + if (isset($url['port']) && $url['scheme'] === 'http' + && $url['port'] != 80 + || isset($url['port']) && $url['scheme'] === 'https' + && $url['port'] != 443 + ) { + $hashurl .= ':' . $url['port']; + } + $hashurl .= $url['path']; + return hash('sha256', $hashurl); + } + } + } + + /** + * Grab the domain from the identifier. + * + * Extract the domain from the Email or OpenID. + * + * @param string $identifier A string of the email address or openid URL + * @param boolean $https If this is https, true. + * + * @return string A string of the domain to use + * + * @since Method available since Release 0.1.0 + */ + protected function domainGet($identifier, $https = false) + { + + // What are we, email or openid? Split ourself up and get the + // important bit out. + if (filter_var($identifier, FILTER_VALIDATE_EMAIL)) { + $email = explode('@', $identifier); + return $email[1]; + } else { + + // The protocol is important. If we're lacking it this will not be + // filtered. Add it per our preference in the options. + if ( ! strpos($identifier, 'http')) { + if ($https === true) { + $protocol = 'https://'; + } else { + $protocol = 'http://'; + } + $identifier = $protocol . $identifier; + } + + $filter = filter_var( + $identifier, + FILTER_VALIDATE_URL, + FILTER_FLAG_PATH_REQUIRED + ); + + if ($filter) { + $url = parse_url($identifier); + $domain = $url['host']; + if (isset($url['port']) && $url['scheme'] === 'http' + && $url['port'] != 80 + || isset($url['port']) && $url['scheme'] === 'https' + && $url['port'] != 443 + ) { + $domain .= ':' . $url['port']; + } + + return $domain; + } + } + } + + /** + * Get the target to use. + * + * Get the SRV record, filtered by priority and weight. If our domain + * has no SRV records, fall back to Libravatar.org + * + * @param string $domain A string of the domain we extracted from the + * provided identifer with domainGet() + * @param boolean $https Whether or not to look for https records + * + * @return string The target URL. + * + * @since Method available since Release 0.1.0 + */ + protected function srvGet($domain, $https = false) + { + + // Are we going secure? Set up a fallback too. + if (isset($https) && $https === true) { + $subdomain = '_avatars-sec._tcp.'; + $fallback = 'seccdn.'; + } else { + $subdomain = '_avatars._tcp.'; + $fallback = 'cdn.'; + } + + // Lets try get us some records based on the choice of subdomain + // and the domain we had passed in. + $srv = dns_get_record($subdomain . $domain, DNS_SRV); + + // Did we get anything? No? + if (count($srv) == 0) { + // Then let's try Libravatar.org. + return $fallback . 'libravatar.org'; + } + + // Sort by the priority. We must get the lowest. + usort($srv, array($this, 'comparePriority')); + + $top = $srv[0]; + $sum = 0; + + // Try to adhere to RFC2782's weighting algorithm, page 3 + // "arrange all SRV RRs (that have not been ordered yet) in any order, + // except that all those with weight 0 are placed at the beginning of + // the list." + shuffle($srv); + $srvs = array(); + foreach ($srv as $s) { + if ($s['weight'] == 0) { + array_unshift($srvs, $s); + } else { + array_push($srvs, $s); + } + } + + foreach ($srvs as $s) { + if ($s['pri'] == $top['pri']) { + // "Compute the sum of the weights of those RRs" + $sum += (int) $s['weight']; + // "and with each RR associate the running sum in the selected + // order." + $pri[$sum] = $s; + } + } + + // "Then choose a uniform random number between 0 and the sum computed + // (inclusive)" + $random = rand(0, $sum); + + // "and select the RR whose running sum value is the first in the selected + // order which is greater than or equal to the random number selected" + foreach ($pri as $k => $v) { + if ($k >= $random) { + return $v['target']; + } + } + } + + /** + * Sorting function for record priorities. + * + * @param mixed $a A mixed value passed by usort() + * @param mixed $b A mixed value passed by usort() + * + * @return mixed The result of the comparison + * + * @since Method available since Release 0.1.0 + */ + protected function comparePriority($a, $b) + { + return $a['pri'] - $b['pri']; + } + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> + diff --git a/libravatar/admin.tpl b/libravatar/admin.tpl new file mode 100644 index 00000000..814f4a44 --- /dev/null +++ b/libravatar/admin.tpl @@ -0,0 +1,2 @@ +{{ inc field_select.tpl with $field=$default_avatar}}{{ endinc }} +
diff --git a/libravatar/libravatar.php b/libravatar/libravatar.php new file mode 100644 index 00000000..1705a9c1 --- /dev/null +++ b/libravatar/libravatar.php @@ -0,0 +1,115 @@ += 5.3) + * Version: 1.0 + * Author: Klaus Weidenbach + */ + +/** + * Installs the plugin hook + */ +function libravatar_install() { + if (! version_compare(PHP_VERSION, '5.3.0', '>=')) { + info(t('Could NOT install Libravatar successfully.
It requires PHP >= 5.3') .EOL); + // avoid registering the hook + return false; + } + register_hook('avatar_lookup', 'addon/libravatar/libravatar.php', 'libravatar_lookup'); + + logger("registered libravatar in avatar_lookup hook"); +} + +/** + * Removes the plugin hook + */ +function libravatar_uninstall() { + unregister_hook('avatar_lookup', 'addon/libravatar/libravatar.php', 'libravatar_lookup'); + + logger("uninstalled libravatar"); +} + +/** + * Looks up the avatar at Libravatar and returns the URL. + * + * @param $a array + * @param &$b array + */ +function libravatar_lookup($a, &$b) { + $default_avatar = get_config('libravatar', 'default_img'); + + if (! $default_avatar) { + // if not set, look up if there was one from the gravatar addon + $default_avatar = get_config('gravatar', 'default_img'); + // setting default avatar if nothing configured + if (! $default_avatar) + $default_avatar = 'identicon'; // default image will be a random pattern + } + + require_once 'Services/Libravatar.php'; + $libravatar = new Services_Libravatar(); + $options = array(); + $options['s'] = $b['size']; + $options['d'] = $default_avatar; + $avatar_url = $libravatar->url($b['email'], $options); + + $b['url'] = $avatar_url; + $b['success'] = true; +} + +/** + * Display admin settings for this addon + */ +function libravatar_plugin_admin (&$a, &$o) { + $t = file_get_contents( dirname(__file__)."/admin.tpl"); + + $default_avatar = get_config('libravatar', 'default_img'); + + // set default values for first configuration + if(! $default_avatar) + $default_avatar = 'identicon'; // pseudo-random geometric pattern based on email hash + + // Available options for the select boxes + $default_avatars = array( + 'mm' => t('generic profile image'), + 'identicon' => t('random geometric pattern'), + 'monsterid' => t('monster face'), + 'wavatar' => t('computer generated face'), + 'retro' => t('retro arcade style face'), + ); + + // Show warning if PHP version is too old + if (! version_compare(PHP_VERSION, '5.3.0', '>=')) { + $o = '
' .t('Warning') .'

'; + $o .= sprintf(t('Your PHP version %s is lower than the required PHP 5.3.'), PHP_VERSION); + $o .= '
' .t('This addon is not functional on you server.') .'


'; + return; + } + + // Libravatar falls back to gravatar, so show warning about gravatar addon if enabled + $r = q("SELECT * FROM `addon` WHERE `name` = '%s' and `installed` = 1", + dbesc('gravatar') + ); + if (count($r)) { + $o = '

' .t('Information') .'

' .t('Gravatar addon is installed. Please disable the gravatar addon.
The Libravatar addon will fall back to gravatar if nothing was found at libravatar.') .'



'; + } + + // output Libravatar settings + $o .= ''; + $o .= replace_macros( $t, array( + '$submit' => t('Submit'), + '$default_avatar' => array('avatar', t('Default avatar image'), $default_avatar, t('Select default avatar image if none was found. See README'), $default_avatars), + )); +} + +/** + * Save admin settings + */ +function libravatar_plugin_admin_post (&$a) { + check_form_security_token('libravatarrsave'); + + $default_avatar = ((x($_POST, 'avatar')) ? notags(trim($_POST['avatar'])) : 'identicon'); + set_config('libravatar', 'default_img', $default_avatar); + info(t('Libravatar settings updated.') .EOL); +} +?> From 5c110b68994b90a75362de00828aef5cef9bc867 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Sat, 14 Jul 2012 20:30:12 +0200 Subject: [PATCH 2/3] Updated Services_Libravatar 0.2.1 Updated external class Services_Libravatar to version 0.2.1 and replaced deprecated functions. This class is under MIT License. Included libravatar.tgz --- libravatar.tgz | Bin 0 -> 7970 bytes libravatar/Services/Libravatar.php | 631 +++++++++++++++++++++-------- libravatar/libravatar.php | 17 +- 3 files changed, 472 insertions(+), 176 deletions(-) create mode 100644 libravatar.tgz diff --git a/libravatar.tgz b/libravatar.tgz new file mode 100644 index 0000000000000000000000000000000000000000..0405af9bd532c8ec17112fcbbd3b92d65f07ead8 GIT binary patch literal 7970 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 Y6e&`qNRc8%iu4rpFSfFU?f{?w01Q=L!vFvP literal 0 HcmV?d00001 diff --git a/libravatar/Services/Libravatar.php b/libravatar/Services/Libravatar.php index d3024408..1b6d022e 100644 --- a/libravatar/Services/Libravatar.php +++ b/libravatar/Services/Libravatar.php @@ -1,7 +1,5 @@ * @copyright 2011 Services_Libravatar committers. * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version SVN: * @link http://pear.php.net/package/Services_Libravatar * @since File available since Release 0.1.0 */ @@ -43,240 +40,364 @@ * PHP support for the Libravatar.org service. * * Using this class is easy. After including or requiring - * PEAR/libravatar.php simply do: - * - * $libravatar = new Services_Libravatar(); - * $url = $libravatar->url('melissa@meldraweb.com'); - * + * Services/Libravatar.php simply do: + * + * $libravatar = new Services_Libravatar(); + * $url = $libravatar->getUrl('melissa@meldraweb.com'); + * * - * This would populate $url with the string: - * http://cdn.libravatar.org/avatar/4db84629c121f2d443d33bdb9fd149bc + * This would populate $url with the string: + * + * http://cdn.libravatar.org/avatar/4db84629c121f2d443d33bdb9fd149bc + * * * A complicated lookup using all the options is: - * - * $libravatar = new Services_Libravatar(); - * $options = array(); - * $options['s'] = '40'; - * $options['algorithm'] = 'sha256'; - * $options['https'] = true; - * $options['d'] = 'http://upload.wikimedia.org/wikipedia/commons/a/af/Tux.png'; - * $url = $libravatar->url('melissa@meldraweb.com', $options); - * + * + * $libravatar = new Services_Libravatar(); + * $libravatar->setSize(40); + * $libravatar->setAlgorithm('sha256'); + * $libravatar->setHttps(true); + * $libravatar->setDefault( + * 'http://upload.wikimedia.org/wikipedia/commons/a/af/Tux.png' + * ); + * $url = $libravatar->getUrl('melissa@meldraweb.com'); + * * * @category Services * @package Services_Libravatar * @author Melissa Draper * @copyright 2011 Services_Libravatar committers. * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version Release: + * @version Release: 0.2.1 * @link http://pear.php.net/package/Services_Libravatar * @since Class available since Release 0.1.0 */ class Services_Libravatar { + /** + * Hashing algorithm to use + * + * @var string + * @see processAlgorithm() + * @see setAlgorithm() + */ + protected $algorithm = 'md5'; /** - * Composes a URL for the identifier and options passed in + * Default image URL to use * - * Compose a full URL as specified by the Libravatar API, based on the - * email address or openid URL passed in, and the options specified. + * @var string + * @see processDefault() + * @see setDefault() + */ + protected $default; + + /** + * If HTTPS URLs should be used * - * @param string $identifier a string of either an email address - * or an openid url - * @param array $options an array of (bool) https, (string) algorithm - * (string) s or size, (string) d or default + * @var boolean + * @see detectHttps() + * @see setHttps() + */ + protected $https; + + /** + * Image size in pixels * - * @return string A string of a full URL for an avatar image + * @var integer + * @see processSize() + * @see setSize() + */ + protected $size; + + + /** + * Composes a URL for the identifier and options passed in * - * @since Method available since Release 0.1.0 + * Compose a full URL as specified by the Libravatar API, based on the + * email address or openid URL passed in, and the options specified. + * + * @param string $identifier a string of either an email address + * or an openid url + * @param array $options an array of (bool) https, (string) algorithm + * (string) size, (string) default. + * See the set* methods. + * + * @return string A string of a full URL for an avatar image + * + * @since Method available since Release 0.2.0 + * @deprecated Use getUrl() instead */ public function url($identifier, $options = array()) { + return $this->getUrl($identifier, $options); + } + /** + * Composes a URL for the identifier and options passed in + * + * Compose a full URL as specified by the Libravatar API, based on the + * email address or openid URL passed in, and the options specified. + * + * @param string $identifier a string of either an email address + * or an openid url + * @param array $options an array of (bool) https, (string) algorithm + * (string) size, (string) default. + * See the set* methods. + * + * @return string A string of a full URL for an avatar image + * + * @since Method available since Release 0.2.0 + * @throws InvalidArgumentException When an invalid option is passed + */ + public function getUrl($identifier, $options = array()) + { // If no identifier has been passed, set it to a null. // This way, there'll always be something returned. if (!$identifier) { $identifier = null; - } - - $https = null; - if (isset($options['https']) && $options['https'] === true) { - $https = true; - } - - // If the algorithm has been passed in $options, send it on. - // This will only affect email functionality. - if (isset($options['algorithm']) && is_string($options['algorithm'])) { - $identiferHash = $this->identiferHash( - $identifier, - $https, - $options['algorithm'] - ); } else { - $identiferHash = $this->identiferHash($identifier, $https); + $identifier = $this->normalizeIdentifier($identifier); } + // Load all options + $options = $this->checkOptionsArray($options); + $https = $this->https; + if (isset($options['https'])) { + $https = (bool)$options['https']; + } + + $algorithm = $this->algorithm; + if (isset($options['algorithm'])) { + $algorithm = $this->processAlgorithm($options['algorithm']); + } + + $default = $this->default; + if (isset($options['default'])) { + $default = $this->processDefault($options['default']); + } + $size = $this->size; + if (isset($options['size'])) { + $size = $this->processSize($options['size']); + } + + + $identifierHash = $this->identifierHash($identifier, $algorithm); + // Get the domain so we can determine the SRV stuff for federation - $domain = $this->domainGet($identifier, $https); + $domain = $this->domainGet($identifier); // If https has been specified in $options, make sure we make the // correct SRV lookup - if (isset($options['https']) && $options['https'] === true) { - $service = $this->srvGet($domain, true); - $protocol = 'https'; - } else { - $service = $this->srvGet($domain); - $protocol = 'http'; + $service = $this->srvGet($domain, $https); + $protocol = $https ? 'https' : 'http'; + + $params = array(); + if ($size !== null) { + $params['size'] = $size; } - - // We no longer need these, and they will pollute our query string - unset($options['algorithm']); - unset($options['https']); - - // If there are any $options left, we want to make those into a query - $params = null; - if (count($options) > 0) { - $params = '?' . http_build_query($options); + if ($default !== null) { + $params['default'] = $default; + } + $paramString = ''; + if (count($params) > 0) { + $paramString = '?' . http_build_query($params); } // Compose the URL from the pieces we generated - $url = $protocol . '://' . $service . '/avatar/' . $identiferHash . $params; + $url = $protocol . '://' . $service . '/avatar/' . $identifierHash + . $paramString; // Return the URL string return $url; - } /** - * Create a hash of the identifier. + * Checks the options array and verify that only allowed options are in it. * - * Create a hash of the email address or openid passed in. Algorithm - * used for email address ONLY can be varied. Either md5 or sha256 - * are supported by the Libravatar API. Will be ignored for openid. + * @param array $options Array of options for getUrl() * - * @param string $identifier A string of the email address or openid URL - * @param boolean $https If this is https, true. - * @param string $hash A string of the hash algorithm type to make - * - * @return string A string hash of the identifier. - * - * @since Method available since Release 0.1.0 + * @return void + * @throws Exception When an invalid option is used */ - protected function identiferHash($identifier, $https = false, $hash = 'md5') + protected function checkOptionsArray($options) { + //this short options are deprecated! + if (isset($options['s'])) { + $options['size'] = $options['s']; + unset($options['s']); + } + if (isset($options['d'])) { + $options['default'] = $options['d']; + unset($options['d']); + } + $allowedOptions = array( + 'algorithm' => true, + 'default' => true, + 'https' => true, + 'size' => true, + ); + foreach ($options as $key => $value) { + if (!isset($allowedOptions[$key])) { + throw new InvalidArgumentException( + 'Invalid option in array: ' . $key + ); + } + } + + return $options; + } + + /** + * Normalizes the identifier (E-mail address or OpenID) + * + * @param string $identifier E-Mail address or OpenID + * + * @return string Normalized identifier + */ + protected function normalizeIdentifier($identifier) + { if (filter_var($identifier, FILTER_VALIDATE_EMAIL)) { - // If email, we can select our algorithm. Default to md5 for - // gravatar fallback. - return hash($hash, $identifier); + return strtolower($identifier); } else { - - // The protocol is important. If we're lacking it this will not be - // filtered. Add it per our preference in the options. - if (stripos($identifier, 'http') !== 0) { - if ($https === true) { - $protocol = 'https://'; - } else { - $protocol = 'http://'; - } - $identifier = $protocol . $identifier; - } - - // Is this an email address or an OpenID account - $filter = filter_var( - $identifier, - FILTER_VALIDATE_URL, - FILTER_FLAG_PATH_REQUIRED - ); - - if ($filter) { - // If this is an OpenID, split the string and make sure the - // formatting is correct. See the Libravatar API for more info. - // http://wiki.libravatar.org/api/ - $url = parse_url($identifier); - $hashurl = strtolower($url['scheme']) . '://' . - strtolower($url['host']); - if (isset($url['port']) && $url['scheme'] === 'http' - && $url['port'] != 80 - || isset($url['port']) && $url['scheme'] === 'https' - && $url['port'] != 443 - ) { - $hashurl .= ':' . $url['port']; - } - $hashurl .= $url['path']; - return hash('sha256', $hashurl); - } + return self::normalizeOpenId($identifier); } } /** - * Grab the domain from the identifier. + * Create a hash of the identifier. * - * Extract the domain from the Email or OpenID. + * Create a hash of the email address or openid passed in. Algorithm + * used for email address ONLY can be varied. Either md5 or sha256 + * are supported by the Libravatar API. Will be ignored for openid. * - * @param string $identifier A string of the email address or openid URL - * @param boolean $https If this is https, true. + * @param string $identifier A string of the email address or openid URL + * @param string $hash A string of the hash algorithm type to make + * Uses the php implementation of hash() + * MD5 preferred for Gravatar fallback * - * @return string A string of the domain to use + * @return string A string hash of the identifier. * - * @since Method available since Release 0.1.0 + * @since Method available since Release 0.1.0 */ - protected function domainGet($identifier, $https = false) + protected function identifierHash($identifier, $hash = 'md5') { + if (filter_var($identifier, FILTER_VALIDATE_EMAIL) || $identifier === null) { + // If email, we can select our algorithm. Default to md5 for + // gravatar fallback. + return hash($hash, $identifier); + } + + //no email, so the identifier has to be an OpenID + return hash('sha256', $identifier); + } + + /** + * Normalizes an identifier (URI or XRI) + * + * @param mixed $identifier URI or XRI to be normalized + * + * @return string Normalized Identifier. + * Empty string when the OpenID is invalid. + * + * @internal Adapted from OpenID::normalizeIdentifier() + */ + public static function normalizeOpenId($identifier) + { + // XRI + if (preg_match('@^xri://@i', $identifier)) { + return preg_replace('@^xri://@i', '', $identifier); + } + + if (in_array($identifier[0], array('=', '@', '+', '$', '!'))) { + return $identifier; + } + + // URL + if (!preg_match('@^http[s]?://@i', $identifier)) { + $identifier = 'http://' . $identifier; + } + if (strpos($identifier, '/', 8) === false) { + $identifier .= '/'; + } + if (!filter_var($identifier, FILTER_VALIDATE_URL)) { + return ''; + } + + $parts = parse_url($identifier); + $parts['scheme'] = strtolower($parts['scheme']); + $parts['host'] = strtolower($parts['host']); + + //http://openid.net/specs/openid-authentication-2_0.html#normalization + return $parts['scheme'] . '://' + . (isset($parts['user']) ? $parts['user'] : '') + . (isset($parts['pass']) ? ':' . $parts['pass'] : '') + . (isset($parts['user']) || isset($parts['pass']) ? '@' : '') + . $parts['host'] + . ( + (isset($parts['port']) + && $parts['scheme'] === 'http' && $parts['port'] != 80) + || (isset($parts['port']) + && $parts['scheme'] === 'https' && $parts['port'] != 443) + ? ':' . $parts['port'] : '' + ) + . $parts['path'] + . (isset($parts['query']) ? '?' . $parts['query'] : ''); + //leave out fragment as requested by the spec + } + + /** + * Grab the domain from the identifier. + * + * Extract the domain from the Email or OpenID. + * + * @param string $identifier A string of the email address or openid URL + * + * @return string A string of the domain to use + * + * @since Method available since Release 0.1.0 + */ + protected function domainGet($identifier) + { + if ($identifier === null) { + return null; + } // What are we, email or openid? Split ourself up and get the // important bit out. if (filter_var($identifier, FILTER_VALIDATE_EMAIL)) { $email = explode('@', $identifier); return $email[1]; - } else { - - // The protocol is important. If we're lacking it this will not be - // filtered. Add it per our preference in the options. - if ( ! strpos($identifier, 'http')) { - if ($https === true) { - $protocol = 'https://'; - } else { - $protocol = 'http://'; - } - $identifier = $protocol . $identifier; - } - - $filter = filter_var( - $identifier, - FILTER_VALIDATE_URL, - FILTER_FLAG_PATH_REQUIRED - ); - - if ($filter) { - $url = parse_url($identifier); - $domain = $url['host']; - if (isset($url['port']) && $url['scheme'] === 'http' - && $url['port'] != 80 - || isset($url['port']) && $url['scheme'] === 'https' - && $url['port'] != 443 - ) { - $domain .= ':' . $url['port']; - } - - return $domain; - } } + + //OpenID + $url = parse_url($identifier); + $domain = $url['host']; + if (isset($url['port']) && $url['scheme'] === 'http' + && $url['port'] != 80 + || isset($url['port']) && $url['scheme'] === 'https' + && $url['port'] != 443 + ) { + $domain .= ':' . $url['port']; + } + + return $domain; } /** - * Get the target to use. + * Get the target to use. * - * Get the SRV record, filtered by priority and weight. If our domain - * has no SRV records, fall back to Libravatar.org + * Get the SRV record, filtered by priority and weight. If our domain + * has no SRV records, fall back to Libravatar.org * - * @param string $domain A string of the domain we extracted from the - * provided identifer with domainGet() - * @param boolean $https Whether or not to look for https records + * @param string $domain A string of the domain we extracted from the + * provided identifier with domainGet() + * @param boolean $https Whether or not to look for https records * - * @return string The target URL. + * @return string The target URL. * - * @since Method available since Release 0.1.0 + * @since Method available since Release 0.1.0 */ protected function srvGet($domain, $https = false) { @@ -344,20 +465,197 @@ class Services_Libravatar } /** - * Sorting function for record priorities. + * Sorting function for record priorities. * - * @param mixed $a A mixed value passed by usort() - * @param mixed $b A mixed value passed by usort() + * @param mixed $a A mixed value passed by usort() + * @param mixed $b A mixed value passed by usort() * - * @return mixed The result of the comparison + * @return mixed The result of the comparison * - * @since Method available since Release 0.1.0 + * @since Method available since Release 0.1.0 */ protected function comparePriority($a, $b) { return $a['pri'] - $b['pri']; } + /** + * Automatically set the https option depending on the current connection + * value. + * + * If the current connection is HTTPS, the https options is activated. + * If it is not HTTPS, the https option is deactivated. + * + * @return self + */ + public function detectHttps() + { + $this->setHttps( + isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] + ); + + return $this; + } + + /** + * Verify and cast the email address hashing algorithm to use. + * + * @param string $algorithm Algorithm to use, "sha256" or "md5". + * + * @return string Algorithm + * + * @throws InvalidArgumentException When an unsupported algorithm is given + */ + protected function processAlgorithm($algorithm) + { + $algorithm = (string)$algorithm; + if ($algorithm !== 'md5' && $algorithm !== 'sha256') { + throw new InvalidArgumentException( + 'Only md5 and sha256 hashing supported' + ); + } + + return $algorithm; + } + + /** + * Verify and cast the default URL to use when no avatar image can be found. + * If none is set, the libravatar logo is returned. + * + * @param string $url Full URL to use OR one of the following: + * - "404" - give a "404 File not found" instead of an image + * - "mm" + * - "identicon" + * - "monsterid" + * - "wavatar" + * - "retro" + * + * @return string Default URL + * + * @throws InvalidArgumentException When an invalid URL is given + */ + protected function processDefault($url) + { + if ($url === null) { + return $url; + } + + $url = (string)$url; + + switch ($url) { + case '404': + case 'mm': + case 'identicon': + case 'monsterid': + case 'wavatar': + case 'retro': + break; + default: + $valid = filter_var($url, FILTER_VALIDATE_URL); + if (!$valid) { + throw new InvalidArgumentException('Invalid default avatar URL'); + } + break; + } + + return $url; + } + + /** + * Verify and cast the required size of the images. + * + * @param integer $size Size (width and height in pixels) of the image. + * NULL for the default width. + * + * @return integer Size + * + * @throws InvalidArgumentException When a size <= 0 is given + */ + protected function processSize($size) + { + if ($size === null) { + return $size; + } + + $size = (int)$size; + if ($size <= 0) { + throw new InvalidArgumentException('Size has to be larger than 0'); + } + + return (int)$size; + } + + + /** + * Set the email address hashing algorithm to use. + * To keep gravatar compatibility, use "md5". + * + * @param string $algorithm Algorithm to use, "sha256" or "md5". + * + * @return self + * @throws InvalidArgumentException When an unsupported algorithm is given + */ + public function setAlgorithm($algorithm) + { + $this->algorithm = $this->processAlgorithm($algorithm); + + return $this; + } + + /** + * Set the default URL to use when no avatar image can be found. + * If none is set, the gravatar logo is returned. + * + * @param string $url Full URL to use OR one of the following: + * - "404" - give a "404 File not found" instead of an image + * - "mm" + * - "identicon" + * - "monsterid" + * - "wavatar" + * - "retro" + * + * @return self + * @throws InvalidArgumentException When an invalid URL is given + */ + public function setDefault($url) + { + $this->default = $this->processDefault($url); + + return $this; + } + + /** + * Set if HTTPS URLs shall be returned. + * + * @param boolean $useHttps If HTTPS url shall be returned + * + * @return self + * + * @see detectHttps() + */ + public function setHttps($useHttps) + { + $this->https = (bool)$useHttps; + + return $this; + } + + /** + * Set the required size of the images. + * Every avatar image is square sized, which means you need to set only number. + * + * @param integer $size Size (width and height) of the image + * + * @return self + * @throws InvalidArgumentException When a size <= 0 is given + */ + public function setSize($size) + { + $this->size = $this->processSize($size); + + return $this; + } + } /* @@ -369,4 +667,3 @@ class Services_Libravatar */ ?> - diff --git a/libravatar/libravatar.php b/libravatar/libravatar.php index 1705a9c1..08ed6d00 100644 --- a/libravatar/libravatar.php +++ b/libravatar/libravatar.php @@ -2,7 +2,7 @@ /** * Name: Libravatar Support * Description: If there is no avatar image for a new user or contact this plugin will look for one at Libravatar. Please disable Gravatar addon if you use this one. (requires PHP >= 5.3) - * Version: 1.0 + * Version: 1.1 * Author: Klaus Weidenbach */ @@ -26,7 +26,7 @@ function libravatar_install() { function libravatar_uninstall() { unregister_hook('avatar_lookup', 'addon/libravatar/libravatar.php', 'libravatar_lookup'); - logger("uninstalled libravatar"); + logger("unregistered libravatar in avatar_lookup hook"); } /** @@ -48,10 +48,9 @@ function libravatar_lookup($a, &$b) { require_once 'Services/Libravatar.php'; $libravatar = new Services_Libravatar(); - $options = array(); - $options['s'] = $b['size']; - $options['d'] = $default_avatar; - $avatar_url = $libravatar->url($b['email'], $options); + $libravatar->setSize($b['size']); + $libravatar->setDefault($default_avatar); + $avatar_url = $libravatar->getUrl($b['email']); $b['url'] = $avatar_url; $b['success'] = true; @@ -81,8 +80,8 @@ function libravatar_plugin_admin (&$a, &$o) { // Show warning if PHP version is too old if (! version_compare(PHP_VERSION, '5.3.0', '>=')) { $o = '
' .t('Warning') .'

'; - $o .= sprintf(t('Your PHP version %s is lower than the required PHP 5.3.'), PHP_VERSION); - $o .= '
' .t('This addon is not functional on you server.') .'


'; + $o .= sprintf(t('Your PHP version %s is lower than the required PHP >= 5.3.'), PHP_VERSION); + $o .= '
' .t('This addon is not functional on your server.') .'


'; return; } @@ -91,7 +90,7 @@ function libravatar_plugin_admin (&$a, &$o) { dbesc('gravatar') ); if (count($r)) { - $o = '

' .t('Information') .'

' .t('Gravatar addon is installed. Please disable the gravatar addon.
The Libravatar addon will fall back to gravatar if nothing was found at libravatar.') .'



'; + $o = '
' .t('Information') .'

' .t('Gravatar addon is installed. Please disable the Gravatar addon.
The Libravatar addon will fall back to Gravatar if nothing was found at Libravatar.') .'



'; } // output Libravatar settings From 1aaecea8dbb5a58262c82215e94c2794976496da Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Sat, 14 Jul 2012 21:11:43 +0200 Subject: [PATCH 3/3] Add check if libravatar addon is enabled, too. Added a check to gravatar if the libravatar addon is also enabled. Only one of these two addons should be anabled and libravatar will fall back to gravatar if it found nothing at libravatar. --- gravatar.tgz | Bin 2349 -> 2552 bytes gravatar/gravatar.php | 17 +++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/gravatar.tgz b/gravatar.tgz index 38e942f897d238f7ff9d23874002b019aba309e9..25106f2658a5c407d184214ee68f1aa089ad7ae5 100644 GIT binary patch literal 2552 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 */ @@ -12,7 +12,7 @@ function gravatar_install() { register_hook('avatar_lookup', 'addon/gravatar/gravatar.php', 'gravatar_lookup'); - logger("installed gravatar"); + logger("registered gravatar in avatar_lookup hook"); } /** @@ -21,7 +21,7 @@ function gravatar_install() { function gravatar_uninstall() { unregister_hook('avatar_lookup', 'addon/gravatar/gravatar.php', 'gravatar_lookup'); - logger("uninstalled gravatar"); + logger("unregistered gravatar in avatar_lookup hook"); } /** @@ -81,7 +81,16 @@ function gravatar_plugin_admin (&$a, &$o) { 'x' => 'x' ); - $o = ''; + // Check if Libravatar is enabled and show warning + $r = q("SELECT * FROM `addon` WHERE `name` = '%s' and `installed` = 1", + dbesc('libravatar') + ); + if (count($r)) { + $o = '
' .t('Information') .'

' .t('Libravatar addon is installed, too. Please disable Libravatar addon or this Gravatar addon.
The Libravatar addon will fall back to Gravatar if nothing was found at Libravatar.') .'



'; + } + + // output Gravatar settings + $o .= ''; $o .= replace_macros( $t, array( '$submit' => t('Submit'), '$default_avatar' => array('avatar', t('Default avatar image'), $default_avatar, t('Select default avatar image if none was found at Gravatar. See README'), $default_avatars),