Giter Site home page Giter Site logo

diso / wordpress-openid Goto Github PK

View Code? Open in Web Editor NEW
33.0 7.0 28.0 2.47 MB

Allows WordPress to provide and consumer OpenIDs for authentication of users and comments.

Home Page: https://wordpress.org/plugins/openid/

License: Apache License 2.0

PHP 99.29% CSS 0.09% JavaScript 0.62%
wordpress openid openid-provider openid-consumer plugin wordpress-plugin diso

wordpress-openid's Introduction

OpenID

Contributors: willnorris, factoryjoe, pfefferle
Tags: openid, authentication, login, comments
Requires at least: 2.8
Tested up to: 6.0
Stable tag: 3.6.1
Requires PHP: 5.6
License: Apache-2.0
License URI: https://www.apache.org/licenses/LICENSE-2.0

Allows WordPress to provide and consumer OpenIDs for authentication of users and comments.

Description

OpenID is an open standard that allows users to authenticate to websites without having to create a new password. This plugin allows users to login to their local WordPress account using an OpenID, as well as enabling commenters to leave authenticated comments with OpenID. The plugin also includes an OpenID provider, enabling users to login to OpenID-enabled sites using their own personal WordPress account. XRDS-Simple is required for the OpenID Provider and some features of the OpenID Consumer.

Developer documentation, which includes all of the public methods and hooks for integrating with and extending the plugin, can be found here.

Installation

This plugin follows the standard WordPress installation method:

  1. Upload the openid folder to the /wp-content/plugins/ directory
  2. Activate the plugin through the 'Plugins' menu in WordPress
  3. Configure the plugin through the 'OpenID' section of the 'Options' menu

Frequently Asked Questions

Why do I get blank screens when I activate the plugin?

In some cases the plugin may have problems if not enough memory has been allocated to PHP. Try ensuring that the PHP memory_limit is at least 8MB (limits of 64MB are not uncommon).

Why don't https OpenIDs work?

SSL certificate problems creep up when working with some OpenID providers (namely MyOpenID). This is typically due to an outdated CA cert bundle being used by libcurl. An explanation of the problem and a couple of solutions can be found here.

Why do I get the error "Invalid openid.mode ''"?

There are actually a couple of reasons that can cause this, but it seems one of the more common causes is a conflict with certain mod_security rules. See this blog post for instructions on how to resolve this issue.

How do I use SSL for OpenID transactions?

First, be aware that this only works in WordPress 2.6 and up. Make sure you've turned on SSL in WordPress by defining either of the following globals as "true" in your wp-config.php file:

  • FORCE_SSL_LOGIN
  • FORCE_SSL_ADMIN

Then, also define the following global as "true" in your wp-config.php file:

  • OPENID_SSL

Be aware that you will almost certainly have trouble with this if you are not using a certificate purchased from a well-known certificate authority.

How do I get help if I have a problem?

Please direct support questions to the "Plugins and Hacks" section of the WordPress.org Support Forum. Just make sure and include the tag 'openid' so that I'll see your post. Additionally, you can file a bug report at http://code.google.com/p/diso/issues/list.

Screenshots

  1. Commentors can use their OpenID when leaving a comment
  2. Users can login with their OpenID in place of a traditional username and password
  3. Users authorized to use the OpenID Provider can delegate to a different provider
  4. Users can add additional OpenIDs which they can use to login to WordPress
  5. Users authorized to use the OpenID Provider can monitor which sites they've logged in to

Changelog

Project maintined on github at diso/wordpress-openid.

version 3.6.1 (June 2022)

  • fixed PHP 8 issue (props to mscherer)
  • updated code to match the WordPress Coding Standard

version 3.6.0 (Mai 2022)

  • fixed issue with ActivityPub plugin
  • updated to latest OpenID library
  • added CI/CD toolings

version 3.5.0 (Feb 12, 2019)

  • fixed PHP warnings and deprecation messages

version 3.4.4 (Jan 12, 2018)

  • fixed bug with latest OpenID library

version 3.4.3 (Jan 12, 2018)

  • update to latest OpenID library

version 3.4.2 (Nov 20, 2016)

  • update to latest OpenID library
  • fixed error response if nonce doesn't match #46

version 3.4.1 (Jan 31, 2016)

version 3.4.0 (Jul 22, 2015)

  • update to latest OpenID library (includes lots of bug fixes, particularly with PHP 5.3). Full changelog on github.
  • fixed various PHP warnings/errors.
  • various improvements and bugfixes (props @rodrigoprimo).
  • attempt to use email as username before url for open id new user (props @yincrash).
  • chinese and german (props Stephan Richter) translations.
  • added WebFinger support

Full changelog on github.

version 3.3.4 (Nov 16, 2012)

  • update to latest OpenID library (includes lots of bug fixes, particularly with PHP 5.3). Full changelog on github.
  • various bug fixes. Full changelog on github.

version 3.3.3 (Aug 24, 2010)

  • add/update danish, japanese, and spanish translations
  • update to latest version of php-openid library
  • fix a few PHP and WordPress warnings and notices

version 3.3.2 (Nov 06, 2009)

  • add localizations for czech, danish, french, spanish, and vietnamese. Some are more up to date than others. More are welcome, see http://code.google.com/p/diso/issues/detail?id=26
  • remove stylesheet for recent comments widget, since it breaks the style for OpenID comments
  • various fixes with administration panels

version 3.3.1 (Sep 28, 2009)

  • tiny bug in get_user_openids causing it to always return empty array

version 3.3 (Sep 28, 2009)

  • minimum required version has been bumped to WordPress 2.8
  • fix support for WordPress MU
  • new, less obtrusive UI for comment form. Should also work with all themes in some form (with or without js).
  • many administrative options have been moved to their respective locations on core WordPress Settings pages
  • drop support for experimental EAUT and IDIB protocols
  • drop support for installing the plugin in mu-plugins folder
  • always include 'index.php' on OpenID endpoint URLs. Without that, some deployments were having problems.
  • fix bug relating to trackbacks and pingbacks
  • fix bug (#121) relating to unregistered options (props tom.tdw for the patch)
  • lots of minor bug fixes

version 3.2.3 (Jul 20, 2009)

  • fix XSS vulnerability. (props Stuart Metcalfe)

version 3.2.2 (Mar 19, 2009)

  • fix problems when using non-index.php permalinks with non-apache web servers
  • ensure that show_on_front option is not empty
  • function name typo (props gunemalli)
  • fix deprecated pass-by-reference call in php-openid library (props jschuur)
  • fix UI bug on registration form with IE browsers (props oledole)
  • UI tweaks to better match WP 2.7
  • update a few strings for localization and POT file

version 3.2.1 (Feb 13, 2009)

  • patch php-openid library to fix XRDS handling (thanks Mike Jones for helping find this)
  • add default values for some openid vars -- necessary for OP-initiated login
  • fix bug with OpenID server where OpenID request was sometimes lost
  • add filter for openid_trust_root

version 3.2 (Jan 20, 2009)

  • add uninstall hook for WordPress 2.7 -- this will remove all traces of the plugin from the database
  • UI fixes for WordPress 2.7
  • add settings link to plugins page
  • silence XML parsing errors with PHP4
  • ensure wp_scripts is set
  • ensure openid comment processing occurs after akismet
  • add ellipses to truncated OpenIDs (fixes #94)
  • fix bug where Yahoo! OpenIDs weren't matching profile URL (fixes #98)
  • don't return empty SREG values
  • Add support for consuming Attribute Exchange
  • use a single return_to URL for all OpenID actions
  • cleaner OpenID service URLs when permalinks configured to do so (all path, no query string)
  • fixed issue where OpenID Server would sometimes break depending on a users permalink structure (fixed #101)
  • fixed issue where OpenID consumer would sometimes break if mod_encoding was enabled in Apache (used for WebDAV) (fixed #96)
  • don't redirect when performing discovery on OpenID trust root

version 3.1.4 (Nov 04, 2008)

  • allow OP extensions to include XRDS Types in login service
  • run OpenID comment processor after Akismet, and skip if Akismet marks comment as spam

version 3.1.3 (Oct 27, 2008)

  • fix error message if /dev/urandom is not readable

version 3.1.2 (Oct 26, 2008)

  • ensure source of randomness is set properly
  • prevent duplicate cleanup_openid cron jobs
  • prevent SQL errors on activation
  • suppress verbose error logging with XML parsing

version 3.1.1 (Oct 20, 2008)

  • fix bug with OpenID Provider XRDS code that prevents ability to login to some sites (like plaxo.com)

version 3.1 (Oct 19, 2008)

  • added hidden constant to set custom comments post page (OPENID_COMMENTS_POST_PAGE)
  • additional option to skip name and email check for OpenID comments
  • use preferred username (from SREG) if possible when creating new account
  • truncate long URLs when used as display_name for comments
  • numerous bug fixes, including bug with registration form

version 3.0 (Oct 02, 2008)

  • includes OpenID Provider
  • supports OpenID delegation
  • add experimental support for Email Address to URL Transformation
  • many new hooks for extension and integration
  • major code refactoring

version 2.2.2 (Aug 06, 2008)

  • fix bug with "unauthorized return_to URL" (only known problem with openid.pl)
  • fix bug with comments containing non-latin characters
  • respect CUSTOM_USER_META_TABLE constant if present (also added CUSTOM_OPENID_IDENTITY_TABLE constant)
  • add experimental support for Identity in the Browser

version 2.2.1 (Jul 25, 2008)

  • fixed EAUT handling code
  • fixed bug that broke comments containing double quotes (")

version 2.2.0 (Jul 23, 2008)

  • use POST replay for comments (fixes compatibility with other comment plugins)
  • only build openid object when needed (much better memory usage)
  • support for Email Address to URL Transformation (see eaut.org)
  • fixed bug when using suhosin (hardened php)
  • use hooks for gathering user data (more extensible)
  • fixed openid spoofing vulnerability (http://plugins.trac.wordpress.org/ticket/702)
  • lots code refactoring and UI cleanup

version 2.1.9 (May 20, 2008)

  • fix javascript loading issues
  • fix various bugs when creating new account with OpenID
  • fix error message, and add new warning prompt when removing last OpenID for account

version 2.1.8 (Apr 02, 2008)

version 2.1.7 (Mar 21, 2008)

  • remove php5 dependency bug... AGAIN!
  • also remove some other custom changes to php-openid I forgot were in there. This may actually re-introduce some edge-case bugs, but I'd rather expose them so that we can get the appropriate patches pushed upstream if they really are necessary.

version 2.1.6 (Mar 20, 2008)

  • update php-openid library to latest. Now properly supports Yahoo's OpenID provider.

version 2.1.5 (Mar 20, 2008)

  • add support for wordpress v2.5

version 2.1.4 (Feb 13, 2008)

  • fix php5 dependency bug
  • improve jQuery code to reduce problems with other js libraries

version 2.1.3 (Feb 06, 2008)

  • address security bug mentioned here. Props Sam Alexander

version 2.1.2

  • minor typo in profile data code

version 2.1.1

  • minor bug where profile data is being overwritten

version 2.1

  • added FAQ items for plugin updater and adding an OpenID field to a comment form
  • better tracking of which users have OpenIDs linked to their local WP account
  • better automatic username generation
  • fixed bug where non-OpenID websites had problems (bug 729)
  • upgrade to version 2.0 of JanRain OpenID library
  • admin option to rebuild tables

version 2.0

  • simplified admin interface by using reasonable defaults. Default behaviors include:
  • "unobtrusive mode"
  • always add openid to wp-login.php
  • always use WP option 'home' for the trust root
  • new features
  • hook for trust engine, with very simple implementation included
  • supports OpenID 2.0 (draft 12) as well as OpenID 1.1 and SReg 1.0
  • normal collection of bug fixes

version 1.0.1

  • added wordpress.org style readme.txt

version 1.0 (also known as r13)

Full SVN logs are available at http://dev.wp-plugins.org/log/openid/.

The original OpenID plugin for WordPress was a collaborative effort between Alan Castonguay and Hans Granqvist.

Will Norris forked the plugin and has since become the maintainer.

wordpress-openid's People

Contributors

chrismessina avatar fuzzie avatar grnq avatar mmcev106 avatar mscherer avatar pfefferle avatar rodrigoprimo avatar simonwgill avatar singpolyma avatar willnorris avatar yincrash avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

wordpress-openid's Issues

backtrace on php 8.0

We upgraded our wordpress instance to php 8.0, and the openid login fail with the following backtrace:

An error of type E_ERROR was caused in line 198 of the file /nas/content/live/fedorapod/wp-content/plugins/openid/common.php. 
Error message: 
  Uncaught ArgumentCountError: 
    Too few arguments to function openid_customer_error_handler(), 4 passed in /nas/content/live/fedorapod/wp-content/plugins/openid/lib/Auth/Yadis/XML.php on line 248 and exactly 5 expected in /nas/content/live/fedorapod/wp-content/plugins/openid/common.php:198
Stack trace: 
#0 /nas/content/live/fedorapod/wp-content/plugins/openid/lib/Auth/Yadis/XML.php(248): openid_customer_error_handler(8192, 'Function libxml...', '/nas/content/li...', 248) 
#1 /nas/content/live/fedorapod/wp-content/plugins/openid/lib/Auth/Yadis/XML.php(35): Auth_Yadis_dom->setXML('init('getNextService('Auth_OpenID_dis...', Object(Auth_Yadis_ParanoidHTTPFetcher)) 
#9 /nas/content/live/fedorapod/wp-content/plugins/openid/consumer.php(127): Auth_OpenID_Consumer->begin('https://id.fedo...') 
#10 /nas/content/live/fedorapod/wp-content/plugins/openid/consumer.php(149): openid_begin_consumer('https://id.fedo...') 
#11 /nas/content/live/fedorapod/wp-content/plugins/openid/login.php(27): openid_start_login('https://id.fedo...', 'login', 'https://podcast...') 
#12 /nas/content/live/fedorapod/wp-includes/class-wp-hook.php(309): openid_authenticate(NULL) 
#13 /nas/content/live/fedorapod/wp-includes/plugin.php(191): WP_Hook->apply_filters(NULL, Array) 
#14 /nas/content/live/fedorapod/wp-includes/pluggable.php(620): apply_filters('authenticate', NULL, '', '') 
#15 /nas/content/live/fedorapod/wp-includes/user.php(95): wp_authenticate('', '') 
#16 /nas/content/live/fedorapod/wp-login.php(1221): wp_signon(Array, true) #17 {main} thrown

It seems that the error handler signature have changed for php 8:
https://www.php.net/manual/en/function.set-error-handler.php

errcontext was deprecated and is now removed.

Assertion not able to be verified

As of recent, I've been trying to login into a Gitea instance with my OpenID from the WordPress OpenID server. However, it's not working and gives me the following error:

Could not verify assertion with provider

A particular query string caught my eye and I didn't know if this is a problem and how it should be solved:

openid.assoc_handle: {HMAC-SHA1}{5e1e4df1}{h+mJgQ==}

Any chance of addressing "This is an OpenID server"?

Steps to reproduce: Attempt OpenID authentication with any OpenID consuming website.

Expected result: OpenID authentication.

Actual result: Browser redirected to example.com/wordpress/?openid=server, which returns a blank page. Refreshing the page returns a message: This is an OpenID Server.

This is not useful.

This has been the case for some years now and I read that it is something to do with PHP versions > 5.3. It would be really useful if someone could bring OpenID for WP back to life by updating the version in the WordPress plugin registry!

when commenting, don't perform discovery on empty website

Currently, the plugin attempts to perform OpenID discovery (a displays a small spinner icon) when focus leaves the website field on the comment form. If the field is left empty, the spinner is displayed and never goes away. This OpenID discovery should be skipped if the field is empty.

Encoding mismatch for identity URL during login

Just had to debug and fix this on my installation:

On login.php:34 you need a urldecode() around $_REQUEST['identity_url'], otherwise your code tries to validate the nonce and find the user based on the urlencoded identity_url. That fails because the nonce was generated with, and the user is associated with, the non-encoded identity url.

This is using version 3.3.3 of the plugin with WP 2.9.2 and PHP 5.3.2.

This repo vs WordPress plugin repository?

So the code here works and is quite recent, whereas the 'officially' published version in the WordPress plugin repository doesn't work (for me) and appears to be abandoned. Is there a situation preventing updates getting made to the WordPress repository?

Google connect - Catchable fatal error: Object of class WP_Error could not be converted to string

I see this error.

Catchable fatal error: Object of class WP_Error could not be converted to string in /wp-includes/capabilities.php on line 497

This error happening when the mail id already exists in the site. (Non openid account)

Why not we show message like "The email id you trying to use, already associated with another account. If you already registered with us please login to your account and connect your openids in Users -> Your openids"

Make sense?

Can't get auth working, 403 Forbidden Error

I'm getting a "Forbidden - You don't have permission to access /wp-login.php on this server" error upon returning to wp-login.php?finish_openid=1.... This is Wordpress 4.9.1 with plugin version 4.3.2

I can access /wp-login.php just fine so it is not an Apache configuration issue.
The passed parameters, triggering that error, are:

?finish_openid=1&identity_url=<urlencoded_identity>
&redirect_to=<nonurlencoded_url>
&_wpnonce=<thenonce>

The nonurlencoded_url contains slashes, but I dubt it matters

Issue with openid connect

I keep getting this error after authentication

Warning: require_once(/home/xxxxxxxpublic_html/xxxxxxx/wp-content/plugins/openid/Auth/OpenID/SReg.php) [function.require-once]: failed to open stream: No such file or directory in /home/xxxxxxx/public_html/xxxxxxx/wp-content/plugins/openid/common.php on line 464

Fatal error: require_once() [function.require]: Failed opening required '/home/xxxxxxx/public_html/xxxxxxx/wp-content/plugins/openid/Auth/OpenID/SReg.php' (include_path='/home/xxxxxxx/public_html/xxxxxxx/wp-content/plugins/openid/lib:.:/usr/lib/php:/usr/local/lib/php') in /home/xxxxxxx/public_html/xxxxxxx/wp-content/plugins/openid/common.php on line 464

Doubled error message

Error messages given in the login screen are doubled. Maybe this is specific to my weird install (debian chroot on a tmpfs)... Anyway, I found a quickfix: just don't globalize the $error var in login.php#L30.

Edit: pushed the quickfix to a fork (twice, actually, the first time I forgot to open a new branch).

/index.php/openid/server returns 404 errors

I could not complete a full log-in process on http://colorhat.com while using Wordpress 3.3. After logging in, I would be redirected to /index.php/openid/server which would return the 404 error. I am using permalinks perfectly well elsewhere on the site.

I've changed the openid_service_url function to always return the querystring variation. On line 616, I replaced the block

  if ($wp_rewrite->using_permalinks()) {
          $url .= 'index.php/openid/' . $service;
  } else {
          $url .= '?openid=' . $service;
  }

with

  $url .= '?openid=' . $service;

These urls aren't for general consumption, so I'm not desperate to having the Cool URL. I'm happy that I can now use the openid provider for its intended purpose now.

Conflict with wordpress-activitypub handling of replies

I see there's some overlap in the developers of these two plugins, so hopefully this is easily resolved.

I'm on Wordpress 5.9.3, running version 3.5.0 of Openid and 0.13.3 of wordpress-activitypub on PHP 7.4.14. When I reply to a post via Mastodon, the following shows up in my debug logs:

 PHP Notice:  Undefined index: login_with_openid in /wordpresspath/wp-content/plugins/openid/comments.php on line 68

and the reply does not make it into Wordpress as a comment. That line assumes there's going to be a login_with_openid parameter on the request, which presumably Mastodon/ActivityPub is not supplying.

If I modify that line to check array_key_exists first, the notice disappears from the logs, but the comment still doesn't make it into WP.

I haven't continued tracing through the missing reply problem enough to know if there are further issues with the openid plugin, but I at least wanted to log this one, since openid probably shouldn't assume that value exists.

Add SVN access keys

@willnorris can you add the same SVN secrets to the OpenID Repo, as you did in the XRDS-Simple? Then it is easier for me to update the plugin.

Allow leaving visible OpenID logo in the comments form

I'd like to suggest visitors of my blog the use of OpenID for comments.

The current interface only adds the OpenID logo when an URL is entered in the "Website" input field of the comment form, but until then, the visitor has no hint about OpenID being supported.

Also, the "Name" and "Mail" fields are reported (by label) as being "required", which isn't the case when authenticating via OpenID.

Would it be possible to make the labelling and visibility of OpenID logo customizable via an OpenID plugin settings form ?

\cc @pfefferle

Associating with my profile fails with "OpenID login failed : Invalid openid.mode No mode set"

First: this is not the same issue as mentioned in the FAQ. I don't run Apache but nginx, hence no mod_security involved at all.

The actual error message is "OpenIDloginfailed:Invalidopenid.modeNomodeset" -- yes, it does not include a single space (as can be seen in the URL).

Setup: nginx 1.0.5, proxying with the FastCGI protocol to php-fpm 5.3.6 on a Ubuntu 11.10 64bit machine. Wordpress 3.3.1, OpenID plugin 3.3.3

This happens with several different OpenID providers, e.g. myopenid.com, pip.verisign-labs.com. In fact I cannot get one of the five I use to work.

Happens both with http and https based OpenIDs.

wordpress-openid does not publish openid provider via XRDS

I've been using a single-author wordpress install as my OpenID for a while. After I upgraded to 3.3, things went wrong.

I've isolated this code block from lines 53-55 which is ending the function before adding the provider services. For my example openid of "http://www.patternwebsolutions.com/" $path is always going to be "/" where $script is "/index.php/openid/server".

if ($path != $script && !is_admin()) {
  return $xrds;
}

Two questions. What is this block checking for? And why are you checking that a logged-in admin user is requesting the xrds document?

I've commented it out for now, and it's pushing out the correct xrds elements. Now, I just have to figure out why wordpress is giving me an intermittent 404 error. I suspect my rewrite rules are doing something screwy.

Call to a member function needsSIgn() to a non-object

I've tried logging here but when I click «Continue» in the «Verify Your Identity» page, my site says:

Fatal error: Call to a member function needsSigning() on a non-object in /blabla/blabla/blabla/wp-content/plugins/openid/lib/Auth/OpenID/Server.php on line 1500

Here infos:

[INFO] PHP version: 5.4.21
[INFO] PHP memory limit: 256M
[INFO] Include Path:

    /blabla/blabla/blabla/wp-content/plugins/openid/lib
    /blabla/blabla/blabla/wp-admin
    /usr/share/php

[INFO] WordPress version: 4.0
[INFO] PHP OpenID Library Version: 2.2.2
[INFO] MySQL version: mysqlnd 5.0.10 - 20111026 - $Id: blablabla $
[INFO] WordPress' table prefix: blablabla_
[OK] Curl Support: Version 7.21.0. SSL: GnuTLS/2.8.6. Supports: dict, file, ftp, ftps, http, https, imap, imaps, ldap, ldaps, pop3, pop3s, rtsp, smtp, smtps, telnet, tftp.
[OK] Big Integer support: GMP is installed.
[INFO] Plugin Revision: 519
[INFO] Plugin Database Revision: 24426
[INFO] XRDS-Simple: XRDS-Simple plugin is installed.
[OK] Overall Plugin Status

(It's a Wordpress Multisite)

How can I help you to fix this problem?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.