private void postPlugin(final boolean isPing) throws IOException {
		// The plugin's description file containg all of the plugin data such as
		// name, version, author, etc
		final PluginDescriptionFile description = plugin.getDescription();

		// Construct the post data
		final StringBuilder data = new StringBuilder();
		data.append(encode("guid")).append('=').append(encode(guid));
		encodeDataPair(data, "version", description.getVersion());
		encodeDataPair(data, "server", Bukkit.getVersion());
		encodeDataPair(data, "players", Integer.toString(Bukkit.getServer().getOnlinePlayers().length));
		encodeDataPair(data, "revision", String.valueOf(REVISION));

		// If we're pinging, append it
		if (isPing) {
			encodeDataPair(data, "ping", "true");
		}

		// Acquire a lock on the graphs, which lets us make the assumption we
		// also lock everything
		// inside of the graph (e.g plotters)
		synchronized (graphs) {
			final Iterator<Graph> iter = graphs.iterator();

			while (iter.hasNext()) {
				final Graph graph = iter.next();

				for (Plotter plotter : graph.getPlotters()) {
					// The key name to send to the metrics server
					// The format is C-GRAPHNAME-PLOTTERNAME where separator -
					// is defined at the top
					// Legacy (R4) submitters use the format Custom%s, or
					// CustomPLOTTERNAME
					final String key = String.format("C%s%s%s%s", CUSTOM_DATA_SEPARATOR, graph.getName(), CUSTOM_DATA_SEPARATOR, plotter.getColumnName());

					// The value to send, which for the foreseeable future is
					// just the string
					// value of plotter.getValue()
					final String value = Integer.toString(plotter.getValue());

					// Add it to the http post data :)
					encodeDataPair(data, key, value);
				}
			}
		}

		// Create the url
		URL url = new URL(BASE_URL + String.format(REPORT_URL, encode(plugin.getDescription().getName())));

		// Connect to the website
		URLConnection connection;

		// Mineshafter creates a socks proxy, so we can safely bypass it
		// It does not reroute POST requests so we need to go around it
		if (isMineshafterPresent()) {
			connection = url.openConnection(Proxy.NO_PROXY);
		} else {
			connection = url.openConnection();
		}

		connection.setDoOutput(true);

		// Write the data
		final OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
		writer.write(data.toString());
		writer.flush();

		// Now read the response
		final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		final String response = reader.readLine();

		// close resources
		writer.close();
		reader.close();

		if (response == null || response.startsWith("ERR")) {
			throw new IOException(response); // Throw the exception
		} else {
			// Is this the first update this hour?
			if (response.contains("OK This is your first update this hour")) {
				synchronized (graphs) {
					final Iterator<Graph> iter = graphs.iterator();

					while (iter.hasNext()) {
						final Graph graph = iter.next();

						for (Plotter plotter : graph.getPlotters()) {
							plotter.reset();
						}
					}
				}
			}
		}
	}