From 7b286d62c33062a891882ff9c0f983033087e635 Mon Sep 17 00:00:00 2001
From: lechuck <l3chuck@autistici.org>
Date: Thu, 24 Jan 2013 16:02:45 +0000
Subject: [PATCH] Added plugin for Sentry integration
 https://github.com/ryanbagwell/wordpress-sentry

---
 wp-content/wordpress-sentry/README.md         |   4 +
 .../class.wp-raven-client.php                 |  56 +++
 .../wordpress-sentry/optionspage.html.php     |  44 ++
 wp-content/wordpress-sentry/raven/.gitignore  |   3 +
 wp-content/wordpress-sentry/raven/.travis.yml |  10 +
 wp-content/wordpress-sentry/raven/AUTHORS     |   4 +
 wp-content/wordpress-sentry/raven/LICENSE     |  12 +
 wp-content/wordpress-sentry/raven/README.rst  |  93 ++++
 .../wordpress-sentry/raven/composer.json      |  27 ++
 .../raven/lib/Raven/Autoloader.php            |  45 ++
 .../raven/lib/Raven/Client.php                | 399 ++++++++++++++++++
 .../raven/lib/Raven/Compat.php                | 133 ++++++
 .../raven/lib/Raven/ErrorHandler.php          |  74 ++++
 .../raven/lib/Raven/Stacktrace.php            | 115 +++++
 .../wordpress-sentry/raven/phpunit.xml.dist   |  25 ++
 .../raven/test/Raven/Tests/ClientTest.php     | 142 +++++++
 .../raven/test/Raven/Tests/CompatTest.php     |  38 ++
 .../test/Raven/Tests/ErrorHandlerTest.php     |  37 ++
 .../wordpress-sentry/raven/test/bootstrap.php |  15 +
 .../wordpress-sentry/wordpress-sentry.php     |  49 +++
 20 files changed, 1325 insertions(+)
 create mode 100644 wp-content/wordpress-sentry/README.md
 create mode 100644 wp-content/wordpress-sentry/class.wp-raven-client.php
 create mode 100644 wp-content/wordpress-sentry/optionspage.html.php
 create mode 100644 wp-content/wordpress-sentry/raven/.gitignore
 create mode 100644 wp-content/wordpress-sentry/raven/.travis.yml
 create mode 100644 wp-content/wordpress-sentry/raven/AUTHORS
 create mode 100644 wp-content/wordpress-sentry/raven/LICENSE
 create mode 100644 wp-content/wordpress-sentry/raven/README.rst
 create mode 100644 wp-content/wordpress-sentry/raven/composer.json
 create mode 100644 wp-content/wordpress-sentry/raven/lib/Raven/Autoloader.php
 create mode 100644 wp-content/wordpress-sentry/raven/lib/Raven/Client.php
 create mode 100644 wp-content/wordpress-sentry/raven/lib/Raven/Compat.php
 create mode 100644 wp-content/wordpress-sentry/raven/lib/Raven/ErrorHandler.php
 create mode 100644 wp-content/wordpress-sentry/raven/lib/Raven/Stacktrace.php
 create mode 100644 wp-content/wordpress-sentry/raven/phpunit.xml.dist
 create mode 100644 wp-content/wordpress-sentry/raven/test/Raven/Tests/ClientTest.php
 create mode 100644 wp-content/wordpress-sentry/raven/test/Raven/Tests/CompatTest.php
 create mode 100644 wp-content/wordpress-sentry/raven/test/Raven/Tests/ErrorHandlerTest.php
 create mode 100644 wp-content/wordpress-sentry/raven/test/bootstrap.php
 create mode 100644 wp-content/wordpress-sentry/wordpress-sentry.php

diff --git a/wp-content/wordpress-sentry/README.md b/wp-content/wordpress-sentry/README.md
new file mode 100644
index 000000000..2bb58f2b7
--- /dev/null
+++ b/wp-content/wordpress-sentry/README.md
@@ -0,0 +1,4 @@
+wordpress-sentry
+================
+
+A WordpRess plugin to handle reporting php error to Django's Sentry
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/class.wp-raven-client.php b/wp-content/wordpress-sentry/class.wp-raven-client.php
new file mode 100644
index 000000000..ab42e6662
--- /dev/null
+++ b/wp-content/wordpress-sentry/class.wp-raven-client.php
@@ -0,0 +1,56 @@
+<?php
+
+
+require_once( dirname(__FILE__).'/raven/lib/Raven/Client.php' );
+require_once( dirname(__FILE__).'/raven/lib/Raven/Compat.php' );
+require_once( dirname(__FILE__).'/raven/lib/Raven/ErrorHandler.php' );
+require_once( dirname(__FILE__).'/raven/lib/Raven/Stacktrace.php' );
+
+class WP_Raven_Client extends Raven_Client {
+	
+	function __construct() {
+		
+		$this->settings = get_option( 'sentry-settings' );
+		
+		if ( !isset( $this->settings['dsn'] )) return;
+		
+		if ( $this->settings['dsn'] == '' ) return;
+		
+		parent::__construct( $this->settings['dsn'] );
+		
+		$this->setErrorReportingLevel( $this->settings['reporting_level'] );
+		
+		$this->setHandlers();
+		
+	}
+	
+	function setHandlers() {
+		$error_handler = new Raven_ErrorHandler( $this );
+		set_error_handler( array( $error_handler, 'handleError' ));
+		set_exception_handler( array( $error_handler, 'handleException' ));
+	}
+	
+	function setErrorReportingLevel( $level = 'E_WARNING' ) {
+		
+		
+		
+		$errorLevelMap = array(
+			'E_NONE' => 0,
+			'E_WARNING' => 2,
+			'E_NOTICE' => 8,
+			'E_USER_ERROR' => 256,
+			'E_USER_WARNING' => 512,
+			'E_USER_NOTICE' => 1024,
+			'E_RECOVERABLE_ERROR' => 4096,
+			'E_ALL' => 8191
+			);
+		
+		if ( array_key_exists( $level, $errorLevelMap ) )
+			$this->_max_error_reporting_level = $errorLevelMap[ $level ];
+	}	
+	
+	
+}
+
+
+?>
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/optionspage.html.php b/wp-content/wordpress-sentry/optionspage.html.php
new file mode 100644
index 000000000..2dd4e14ad
--- /dev/null
+++ b/wp-content/wordpress-sentry/optionspage.html.php
@@ -0,0 +1,44 @@
+<div class="wrap">
+	<h2>Sentry Error Reporting Settings</h2>
+	
+	<form action="" method="post">
+		
+		<table class="form-table">
+			<tbody>
+				<tr valign="top">
+					<th scope="row">
+						<label for="sentry_dsn">Sentry DSN</label>
+					</th>
+					<td>
+						<input name="sentry_dsn" type="text" id="sentry-dsn" value="<?php echo $dsn; ?>" class="regular-text">
+					</td>
+				</tr>
+				
+				<tr valign="top">
+					<th scope="row">
+						<label for="sentry_dsn">Error Reporting Level</label>
+					</th>
+					<td>
+						<select name="sentry_reporting_level">
+							<option value="E_NONE" <?php echo ($reporting_level == 'E_NONE') ? 'selected="selected"' : '';?>>None</option>
+							<option value="E_WARNING" <?php echo ($reporting_level == 'E_WARNING') ? 'selected="selected"' : '';?>>Warnings</option>
+							<option value="E_NOTICE" <?php echo ($reporting_level == 'E_NOTICE') ? 'selected="selected"' : '';?>>Notices</option>
+							<option value="E_USER_ERROR" <?php echo ($reporting_level == 'E_USER_ERROR') ? 'selected="selected"' : '';?>>User Errors</option>
+							<option value="E_USER_WARNING" <?php echo ($reporting_level == 'E_USER_WARNING') ? 'selected="selected"' : '';?>>User Warnings</option>
+							<option value="E_USER_NOTICE" <?php echo ($reporting_level == 'E_USER_NOTICE') ? 'selected="selected"' : '';?>>User Notices</option>
+							<option value="E_RECOVERABLE_ERROR" <?php echo ($reporting_level == 'E_RECOVERABLE_ERROR') ? 'selected="selected"' : '';?>>Recoverable Errors</option>
+							<option value="E_ALL" <?php echo ($reporting_level == 'E_ALL') ? 'selected="selected"' : '';?>>All Errors</option>
+						</select>
+						 ("User Notices" is recommended)
+					</td>
+				</tr>				
+			</tbody>
+		</table>
+		
+		<p class="submit">
+			<input type="submit" name="submit" id="submit" class="button-primary" value="Save Changes">
+		</p>
+
+	</form>
+	
+</div>
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/raven/.gitignore b/wp-content/wordpress-sentry/raven/.gitignore
new file mode 100644
index 000000000..d6544d92a
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/.gitignore
@@ -0,0 +1,3 @@
+*.lock
+package.xml
+/vendor
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/raven/.travis.yml b/wp-content/wordpress-sentry/raven/.travis.yml
new file mode 100644
index 000000000..6f2007918
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/.travis.yml
@@ -0,0 +1,10 @@
+language: php
+php:
+  - 5.2
+  - 5.3
+  - 5.4
+notifications:
+  irc:
+    channels: "irc.freenode.org#sentry"
+    on_success: change
+    on_failure: change
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/raven/AUTHORS b/wp-content/wordpress-sentry/raven/AUTHORS
new file mode 100644
index 000000000..b9769880b
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/AUTHORS
@@ -0,0 +1,4 @@
+The Raven PHP client was originally written by Michael van Tellingen
+and is maintained by the Sentry Team.
+
+http://github.com/getsentry/raven-php/contributors
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/raven/LICENSE b/wp-content/wordpress-sentry/raven/LICENSE
new file mode 100644
index 000000000..c53c66caf
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/LICENSE
@@ -0,0 +1,12 @@
+Copyright (c) 2012 Sentry Team and individual contributors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+    3. Neither the name of the Raven nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/raven/README.rst b/wp-content/wordpress-sentry/raven/README.rst
new file mode 100644
index 000000000..750de4680
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/README.rst
@@ -0,0 +1,93 @@
+raven-php
+=========
+
+.. image:: https://secure.travis-ci.org/getsentry/raven-php.png?branch=master
+   :target: http://travis-ci.org/getsentry/raven-php
+
+
+raven-php is an experimental PHP client for `Sentry <http://aboutsentry.com/>`_.
+
+::
+
+    // Instantiate a new client with a compatible DSN
+    $client = new Raven_Client('http://public:secret@example.com/1');
+
+    // Capture a message
+    $event_id = $client->getIdent($client->captureMessage('my log message'));
+
+    // Capture an exception
+    $event_id = $client->getIdent($client->captureException($ex));
+
+    // Give the user feedback
+    echo "Sorry, there was an error!";
+    echo "Your reference ID is " . $event_id;
+
+    // Install error handlers
+    $error_handler = new Raven_ErrorHandler($client);
+    $error_handler->registerExceptionHandler();
+    $error_handler->registerErrorHandler();
+
+Installation
+------------
+
+Install with Composer
+~~~~~~~~~~~~~~~~~~~~~
+
+If you're using `Composer <https://github.com/composer/composer>`_ to manage
+dependencies, you can add Raven with it.
+
+::
+
+    {
+        "require": {
+            "raven/raven": ">=0.2.0"
+        }
+    }
+
+or to get the latest version off the master branch:
+
+::
+
+    {
+        "require": {
+            "raven/raven": "dev-master"
+        }
+    }
+
+
+Install source from GitHub
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To install the source code:
+
+::
+
+    $ git clone git://github.com/getsentry/raven-php.git
+
+And include it in your scripts:
+
+::
+
+    require_once '/path/to/Raven/library/Raven.php';
+
+Or, alternatively use the autoloader:
+
+::
+
+    require_once '/path/to/Raven/library/Raven/Autoloader.php';
+    Raven_Autoloader::register();
+
+Or, if you're using `Composer <https://github.com/composer/composer>`_:
+
+::
+
+    require_once 'vendor/autoload.php';
+    
+
+Resources
+---------
+
+* `Bug Tracker <http://github.com/getsentry/raven-php/issues>`_
+* `Code <http://github.com/getsentry/raven-php>`_
+* `Mailing List <https://groups.google.com/group/getsentry>`_
+* `IRC <irc://irc.freenode.net/sentry>`_  (irc.freenode.net, #sentry)
diff --git a/wp-content/wordpress-sentry/raven/composer.json b/wp-content/wordpress-sentry/raven/composer.json
new file mode 100644
index 000000000..7e49081c3
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/composer.json
@@ -0,0 +1,27 @@
+{
+    "name": "raven/raven",
+    "type": "library",
+    "description": "A PHP client for Sentry (http://getsentry.com)",
+    "keywords": ["log", "logging"],
+    "homepage": "http://getsentry.com",
+    "version": "0.2.0",
+    "license": "Apache License 2",
+    "authors": [
+        {
+            "name": "Michael van Tellingen",
+            "email": ""
+        },
+        {
+            "name": "David Cramer",
+            "email": "dcramer@gmail.com"
+        }
+    ],
+    "require": {
+        "php": ">=5.2.4"
+    },
+    "autoload": {
+        "psr-0" : {
+            "Raven_" : "lib/"
+        }
+    }
+}
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/raven/lib/Raven/Autoloader.php b/wp-content/wordpress-sentry/raven/lib/Raven/Autoloader.php
new file mode 100644
index 000000000..dc1bc8a02
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/lib/Raven/Autoloader.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of Raven.
+ *
+ * (c) Sentry Team
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Autoloads Raven classes.
+ *
+ * @package raven
+ */
+class Raven_Autoloader
+{
+    /**
+     * Registers Raven_Autoloader as an SPL autoloader.
+     */
+    static public function register()
+    {
+        ini_set('unserialize_callback_func', 'spl_autoload_call');
+        spl_autoload_register(array(new self, 'autoload'));
+    }
+
+    /**
+     * Handles autoloading of classes.
+     *
+     * @param  string  $class  A class name.
+     *
+     * @return boolean Returns true if the class has been loaded
+     */
+    static public function autoload($class)
+    {
+        if (0 !== strpos($class, 'Raven')) {
+            return;
+        }
+
+        if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
+            require $file;
+        }
+    }
+}
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/raven/lib/Raven/Client.php b/wp-content/wordpress-sentry/raven/lib/Raven/Client.php
new file mode 100644
index 000000000..265c19475
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/lib/Raven/Client.php
@@ -0,0 +1,399 @@
+<?php
+
+/*
+ * This file is part of Raven.
+ *
+ * (c) Sentry Team
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Raven PHP Client
+ *
+ * @package raven
+ */
+
+class Raven_Client
+{
+    const DEBUG = 10;
+    const INFO = 20;
+    const WARN = 30;
+    const WARNING = 30;
+    const ERROR = 40;
+
+    function __construct($options_or_dsn=null, $options=array())
+    {
+        if (is_null($options_or_dsn)) {
+            // Read from environment
+            $options_or_dsn = $_SERVER['SENTRY_DSN'];
+        }
+        if (!is_array($options_or_dsn)) {
+            // Must be a valid DSN
+            $options_or_dsn = self::parseDSN($options_or_dsn);
+        }
+        $options = array_merge($options_or_dsn, $options);
+
+        $this->servers = (!empty($options['servers']) ? $options['servers'] : null);
+        $this->secret_key = (!empty($options['secret_key']) ? $options['secret_key'] : null);
+        $this->public_key = (!empty($options['public_key']) ? $options['public_key'] : null);
+        $this->project = (isset($options['project']) ? $options['project'] : 1);
+        $this->auto_log_stacks = (isset($options['auto_log_stacks']) ? $options['auto_log_stacks'] : false);
+        $this->name = (!empty($options['name']) ? $options['name'] : Raven_Compat::gethostname());
+        $this->site = (!empty($options['site']) ? $options['site'] : $this->_server_variable('SERVER_NAME'));
+        $this->_lasterror = null;
+    }
+
+    /**
+     * Parses a Raven-compatible DSN and returns an array of its values.
+     */
+    public static function parseDSN($dsn)
+    {
+        $url = parse_url($dsn);
+        $scheme = (isset($url['scheme']) ? $url['scheme'] : '');
+        if (!in_array($scheme, array('http', 'https', 'udp'))) {
+            throw new InvalidArgumentException('Unsupported Sentry DSN scheme: ' . $scheme);
+        }
+        $netloc = (isset($url['host']) ? $url['host'] : null);
+        $netloc.= (isset($url['port']) ? ':'.$url['port'] : null);
+        $rawpath = (isset($url['path']) ? $url['path'] : null);
+        if ($rawpath) {
+            $pos = strrpos($rawpath, '/', 1);
+            if ($pos !== false) {
+                $path = substr($rawpath, 0, $pos);
+                $project = substr($rawpath, $pos + 1);
+            }
+            else {
+                $path = '';
+                $project = substr($rawpath, 1);
+            }
+        }
+        else {
+            $project = null;
+            $path = '';
+        }
+        $username = (isset($url['user']) ? $url['user'] : null);
+        $password = (isset($url['pass']) ? $url['pass'] : null);
+        if (empty($netloc) || empty($project) || empty($username) || empty($password)) {
+            throw new InvalidArgumentException('Invalid Sentry DSN: ' . $dsn);
+        }
+        return array(
+            'servers'    => array(sprintf('%s://%s%s/api/store/', $scheme, $netloc, $path)),
+            'project'    => $project,
+            'public_key' => $username,
+            'secret_key' => $password,
+        );
+    }
+
+    /**
+     * Given an identifier, returns a Sentry searchable string.
+     */
+    public function getIdent($ident)
+    {
+        // XXX: We dont calculate checksums yet, so we only have the ident.
+        return $ident;
+    }
+
+    /**
+     * Deprecated
+     */
+    public function message($message, $params=array(), $level=self::INFO,
+                            $stack=false)
+    {
+        return $this->captureMessage($message, $params, $level, $stack);
+    }
+
+    /**
+     * Deprecated
+     */
+    public function exception($exception)
+    {
+        return $this->captureException($exception);
+    }
+
+    /**
+     * Log a message to sentry
+     */
+    public function captureMessage($message, $params=array(), $level=self::INFO,
+                            $stack=false)
+    {
+        $data = array(
+            'message' => vsprintf($message, $params),
+            'level' => $level,
+            'sentry.interfaces.Message' => array(
+                'message' => $message,
+                'params' => $params,
+            )
+        );
+        return $this->capture($data, $stack);
+    }
+
+    /**
+     * Log an exception to sentry
+     */
+    public function captureException($exception, $culprit=null, $logger=null)
+    {
+	
+        $exc_message = $exception->getMessage();
+        if (empty($exc_message)) {
+            $exc_message = '<unknown exception>';
+        }
+
+        $data = array(
+            'message' => $exc_message
+        );
+
+        $data['sentry.interfaces.Exception'] = array(
+                'value' => $exc_message,
+                'type' => $exception->getCode(),
+                'module' => $exception->getFile() .':'. $exception->getLine(),
+        );
+
+        if ($culprit){
+            $data["culprit"] = $culprit;
+        }
+
+        if ($logger){
+            $data["logger"] = $logger;
+        }
+
+        /**'sentry.interfaces.Exception'
+         * Exception::getTrace doesn't store the point at where the exception
+         * was thrown, so we have to stuff it in ourselves. Ugh.
+         */
+        $trace = $exception->getTrace();
+        $frame_where_exception_thrown = array(
+            'file' => $exception->getFile(),
+            'line' => $exception->getLine(),
+        );
+        array_unshift($trace, $frame_where_exception_thrown);
+        return $this->capture($data, $trace);
+    }
+
+    public function capture($data, $stack)
+    {
+        $event_id = $this->uuid4();
+
+        if (!isset($data['timestamp'])) $data['timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
+        if (!isset($data['level'])) $data['level'] = self::ERROR;
+
+        // The function getallheaders() is only available when running in a
+        // web-request. The function is missing when run from the commandline..
+        $headers = array();
+        if (function_exists('getallheaders')) {
+            $headers = getallheaders();
+        }
+
+        $data = array_merge($data, array(
+            'server_name' => $this->name,
+            'event_id' => $event_id,
+            'project' => $this->project,
+            'site' => $this->site,
+            'sentry.interfaces.Http' => array(
+                'method' => $this->_server_variable('REQUEST_METHOD'),
+                'url' => $this->get_current_url(),
+                'query_string' => $this->_server_variable('QUERY_STRNG'),
+                'data' => $_POST,
+                'cookies' => $_COOKIE,
+                'headers' => $headers,
+                'env' => $_SERVER,
+            )
+        ));
+
+        if ((!$stack && $this->auto_log_stacks) || $stack === True) {
+            $stack = debug_backtrace();
+
+            // Drop last stack
+            array_shift($stack);
+        }
+
+        /**
+         * PHP's way of storing backstacks seems bass-ackwards to me
+         * 'function' is not the function you're in; it's any function being
+         * called, so we have to shift 'function' down by 1. Ugh.
+         */
+        for ($i = 0; $i < count($stack) - 1; $i++) {
+            $stack[$i]['function'] = $stack[$i + 1]['function'];
+        }
+        $stack[count($stack) - 1]['function'] = null;
+
+        if ($stack && !isset($data['sentry.interfaces.Stacktrace'])) {
+            $data['sentry.interfaces.Stacktrace'] = array(
+                'frames' => Raven_Stacktrace::get_stack_info($stack)
+            );
+        }
+
+        if (function_exists('mb_convert_encoding')) {
+            $data = $this->remove_invalid_utf8($data);
+        }
+
+        $this->send($data);
+
+        return $event_id;
+    }
+
+    public function send($data)
+    {
+        $message = base64_encode(gzcompress(Raven_Compat::json_encode($data)));
+
+        foreach($this->servers as $url) {
+            $timestamp = microtime(true);
+            $signature = $this->get_signature(
+                $message, $timestamp, $this->secret_key);
+
+            $headers = array(
+                'X-Sentry-Auth' => $this->get_auth_header(
+                    $signature, $timestamp, 'raven-php/0.1', $this->public_key),
+                'Content-Type' => 'application/octet-stream'
+            );
+
+            $this->send_remote($url, $message, $headers);
+        }
+    }
+
+    private function send_remote($url, $data, $headers=array())
+    {
+        $parts = parse_url($url);
+        $parts['netloc'] = $parts['host'].(isset($parts['port']) ? ':'.$parts['port'] : null);
+
+        if ($parts['scheme'] === 'udp')
+            return $this->send_udp($parts['netloc'], $data, $headers['X-Sentry-Auth']);
+
+        return $this->send_http($url, $data, $headers);
+    }
+
+    private function send_udp($netloc, $data, $headers)
+    {
+        list($host, $port) = explode(':', $netloc);
+        $raw_data = $headers."\n\n".$data;
+
+        $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
+        socket_sendto($sock, $raw_data, strlen($raw_data), 0, $host, $port);
+        socket_close($sock);
+
+        return true;
+    }
+
+    /**
+     * Send the message over http to the sentry url given
+     */
+    private function send_http($url, $data, $headers=array())
+    {
+        $new_headers = array();
+        foreach($headers as $key => $value) {
+            array_push($new_headers, $key .': '. $value);
+        }
+        $parts = parse_url($url);
+        $curl = curl_init($url);
+        curl_setopt($curl, CURLOPT_POST, 1);
+        curl_setopt($curl, CURLOPT_HTTPHEADER, $new_headers);
+        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
+        curl_setopt($curl, CURLOPT_VERBOSE, false);
+        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+        $ret = curl_exec($curl);
+        $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+        $success = ($code == 200);
+        curl_close($curl);
+        if (!$success) {
+            // It'd be nice just to raise an exception here, but it's not very PHP-like
+            $this->_lasterror = $ret;
+        }
+        return $success;
+    }
+
+    /**
+     * Create a signature
+     */
+    private function get_signature($message, $timestamp, $key)
+    {
+        return Raven_Compat::hash_hmac('sha1', sprintf('%F', $timestamp) .' '. $message, $key);
+    }
+
+    private function get_auth_header($signature, $timestamp, $client,
+                                     $api_key=null)
+    {
+        $header = array(
+            sprintf("sentry_timestamp=%F", $timestamp),
+            "sentry_signature={$signature}",
+            "sentry_client={$client}",
+            "sentry_version=2.0",
+        );
+
+        if ($api_key) {
+            array_push($header, "sentry_key={$api_key}");
+        }
+
+        return sprintf('Sentry %s', implode(', ', $header));
+    }
+
+    /**
+     * Generate an uuid4 value
+     */
+    private function uuid4()
+    {
+        $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
+            // 32 bits for "time_low"
+            mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
+
+            // 16 bits for "time_mid"
+            mt_rand( 0, 0xffff ),
+
+            // 16 bits for "time_hi_and_version",
+            // four most significant bits holds version number 4
+            mt_rand( 0, 0x0fff ) | 0x4000,
+
+            // 16 bits, 8 bits for "clk_seq_hi_res",
+            // 8 bits for "clk_seq_low",
+            // two most significant bits holds zero and one for variant DCE1.1
+            mt_rand( 0, 0x3fff ) | 0x8000,
+
+            // 48 bits for "node"
+            mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
+        );
+        return str_replace('-', '', $uuid);
+    }
+
+    /**
+     * Return the URL for the current request
+     */
+    private function get_current_url()
+    {
+        // When running from commandline the REQUEST_URI is missing.
+        if ($this->_server_variable('REQUEST_URI') === '') {
+            return '';
+        }
+
+        $schema = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'
+            || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
+        return $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+    }
+
+    private function _server_variable($key)
+    {
+        if (isset($_SERVER[$key])) {
+            return $_SERVER[$key];
+        }
+        return '';
+    }
+
+    private function remove_invalid_utf8($data)
+    {
+        foreach ($data as $key => $value) {
+            if (is_string($key)) {
+                $key = mb_convert_encoding($key, 'UTF-8', 'UTF-8');
+            }
+            if (is_string($value)) {
+                $value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
+            }
+            if (is_array($value)) {
+                $value = $this->remove_invalid_utf8($value);
+            }
+            $data[$key] = $value;
+        }
+
+        return $data;
+    }
+
+}
diff --git a/wp-content/wordpress-sentry/raven/lib/Raven/Compat.php b/wp-content/wordpress-sentry/raven/lib/Raven/Compat.php
new file mode 100644
index 000000000..39623c4fa
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/lib/Raven/Compat.php
@@ -0,0 +1,133 @@
+<?php
+
+/*
+ * This file is part of Raven.
+ *
+ * (c) Sentry Team
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+ 
+class Raven_Compat
+{
+
+    public static function gethostname()
+    {
+        if (function_exists('gethostname')) {
+            return gethostname();
+        }
+        return self::_gethostname();
+    }
+
+    public static function _gethostname()
+    {
+        return php_uname('n');
+    }
+
+    public static function hash_hmac($algo, $data, $key, $raw_output=false)
+    {
+        if (function_exists('hash_hmac')) {
+            return hash_hmac($algo, $data, $key, $raw_output);
+        }
+        return self::_hash_hmac($algo, $data, $key, $raw_output);
+    }
+
+    /**
+     * Implementation from 'KC Cloyd'.
+     * See http://nl2.php.net/manual/en/function.hash-hmac.php
+     */
+    public static function _hash_hmac($algo, $data, $key, $raw_output=false)
+    {
+        $algo = strtolower($algo);
+        $pack = 'H'.strlen($algo('test'));
+        $size = 64;
+        $opad = str_repeat(chr(0x5C), $size);
+        $ipad = str_repeat(chr(0x36), $size);
+
+        if (strlen($key) > $size) {
+            $key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
+        } else {
+            $key = str_pad($key, $size, chr(0x00));
+        }
+
+        for ($i = 0; $i < strlen($key) - 1; $i++) {
+            $opad[$i] = $opad[$i] ^ $key[$i];
+            $ipad[$i] = $ipad[$i] ^ $key[$i];
+        }
+
+        $output = $algo($opad.pack($pack, $algo($ipad.$data)));
+
+        return ($raw_output) ? pack($pack, $output) : $output;
+    }
+
+    /**
+     * Note that we discard the options given to be compatible
+     * with PHP < 5.3
+     */
+    public static function json_encode($value, $options=0)
+    {
+        if (function_exists('json_encode')) {
+            return json_encode($value);
+        }
+        return self::_json_encode($value);
+    }
+
+    /** 
+     * Implementation taken from
+     * http://www.mike-griffiths.co.uk/php-json_encode-alternative/
+     */
+    public static function _json_encode($value)
+    {
+        static $jsonReplaces = array(
+            array('\\', '/', "\n", "\t", "\r", "\b", "\f", '"'), 
+            array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
+
+        if (is_null($value)) {
+            return 'null';
+        }
+        if ($value === false) {
+            return 'false';
+        }
+        if ($value === true) {
+            return 'true';
+        }
+
+        if (is_scalar($value)) {
+            
+            // Always use '.' for floats.
+            if (is_float($value)) {
+                return floatval(str_replace(',', '.', strval($value)));
+            }
+            if (is_string($value)) {
+                return sprintf('"%s"', 
+                    str_replace($jsonReplaces[0], $jsonReplaces[1], $value));
+            }
+            else {
+                return $value;
+            }
+        }
+
+        $isList = true;
+        for ($i = 0, reset($value); true; $i++) { 
+            if (key($value) !== $i) {
+                $isList = false;
+                break;
+            }
+        }
+        $result = array();
+        if ($isList) {
+            foreach ($value as $v) {
+                $result[] = self::_json_encode($v);
+            }
+            return '[' . join(',', $result) . ']';
+        } 
+        else {
+            foreach ($value as $k => $v) {
+                $result[] = self::_json_encode($k) . ':' . self::_json_encode($v);
+            }
+            return '{' . join(',', $result) . '}';
+        }
+    }
+}
+
diff --git a/wp-content/wordpress-sentry/raven/lib/Raven/ErrorHandler.php b/wp-content/wordpress-sentry/raven/lib/Raven/ErrorHandler.php
new file mode 100644
index 000000000..0ba6f836e
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/lib/Raven/ErrorHandler.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of Raven.
+ *
+ * (c) Sentry Team
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Event handlers for exceptions and errors
+ *
+ * $client = new Raven_Client('http://public:secret/example.com/1');
+ * $error_handler = new Raven_ErrorHandler($client);
+ * $error_handler->registerExceptionHandler();
+ * $error_handler->registerErrorHandler();
+ *
+ * @package raven
+ */
+
+class Raven_ErrorHandler
+{
+    private $max_error_reporting_level = 2;
+
+	function __construct($client) {
+        $this->client = $client;
+
+		if ( $client->_max_error_reporting_level )
+			$this->max_error_reporting_level = $client->_max_error_reporting_level;
+			
+    }
+
+    function handleException($e, $isError = false) {
+        $e->event_id = $this->client->getIdent($this->client->captureException($e));
+
+        if (!$isError && $this->call_existing_exception_handler && $this->old_exception_handler) {
+            call_user_func($this->old_exception_handler, $e);
+        }
+    }
+
+    function handleError($code, $message, $file='', $line=0, $context=array()) {
+        
+		if ( $code >= $this->max_error_reporting_level )
+			return;
+
+        $e = new ErrorException($message, 0, $code, $file, $line);
+        $this->handleException($e, $isError = true);
+
+
+        if ($this->call_existing_error_handler && $this->old_error_handler) {
+            call_user_func($this->old_error_handler, $code, $message, $file, $line, $context);
+        }
+    }
+
+    function registerExceptionHandler($call_existing_exception_handler = true)
+    {
+        $this->old_exception_handler = set_exception_handler(array($this, 'handleException'));
+        $this->call_existing_exception_handler = $call_existing_exception_handler;
+    }
+
+    function registerErrorHandler($call_existing_error_handler = true, $error_types = E_ALL)
+    {
+        $this->old_error_handler = set_error_handler(array($this, 'handleError'), $error_types);
+        $this->call_existing_error_handler = $call_existing_error_handler;
+    }
+    
+    private $old_exception_handler = null;
+    private $call_existing_exception_handler = false;
+    private $old_error_handler = null;
+    private $call_existing_error_handler = false;
+}
+?>
diff --git a/wp-content/wordpress-sentry/raven/lib/Raven/Stacktrace.php b/wp-content/wordpress-sentry/raven/lib/Raven/Stacktrace.php
new file mode 100644
index 000000000..e3f830323
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/lib/Raven/Stacktrace.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Small helper class to inspect the stacktrace
+ *
+ * @package raven
+ */
+class Raven_Stacktrace
+{
+    public static function get_stack_info($stack)
+    {
+        $result = array();
+        foreach($stack as $frame) {
+            if (!isset($frame['file'])) {
+                $args = (is_array($frame['args']) ? implode(',', $frame['args']) : $frame['args']);
+                if (isset($frame['class'])) {
+                    $context['line'] = sprintf('%s%s%s(%s)',
+                        $frame['class'], $frame['type'], $frame['function'],
+                        $args);
+                }
+                else {
+                    $context['line'] = sprintf('%s(%s)', $frame['function'], $args);
+                }
+                $abs_path = '';
+                $context['prefix'] = '';
+                $context['suffix'] = '';
+                $context['filename'] = $filename = '[Anonymous function]';
+                $context['lineno'] = 0;
+            }
+            else {
+                $context = self::read_source_file($frame['file'], $frame['line']);
+                $abs_path = $frame['file'];
+                $filename = basename($frame['file']);
+            }
+
+            $module = $filename;
+            if (isset($frame['class'])) {
+                $module .= ':' . $frame['class'];
+            }
+
+            array_push($result, array(
+                'abs_path' => $abs_path,
+                'filename' => $context['filename'],
+                'lineno' => $context['lineno'],
+                'module' => $module,
+                'function' => $frame['function'],
+                'vars' => array(),
+                'pre_context' => $context['prefix'],
+                'context_line' => $context['line'],
+                'post_context' => $context['suffix'],
+
+            ));
+        }
+        return array_reverse($result);
+    }
+
+    private static function read_source_file($filename, $lineno)
+    {
+        $frame = array(
+            'prefix' => array(),
+            'line' => '',
+            'suffix' => array(),
+            'filename' => $filename,
+            'lineno' => $lineno,
+        );
+
+        if ($filename === null || $lineno === null) {
+            return $frame;
+        }
+
+        // Code which is eval'ed have a modified filename.. Extract the
+        // correct filename + linenumber from the string.
+        $matches = array();
+        $matched = preg_match("/^(.*?)\((\d+)\) : eval\(\)'d code$/",
+            $filename, $matches);
+        if ($matched) {
+            $frame['filename'] = $filename = $matches[1];
+            $frame['lineno'] = $lineno = $matches[2];
+        }
+
+
+        // Try to open the file. We wrap this in a try/catch block in case
+        // someone has modified the error_trigger to throw exceptions.
+        try {
+            $fh = fopen($filename, 'r');
+            if ($fh === false) {
+                return $frame;
+            }
+        }
+        catch (ErrorException $exc) {
+            return $frame;
+        }
+
+        $line = false;
+        $cur_lineno = 0;
+
+        while(!feof($fh)) {
+            $cur_lineno++;
+            $line = fgets($fh);
+
+            if ($cur_lineno == $lineno) {
+                $frame['line'] = $line;
+            }
+            elseif ($lineno - $cur_lineno > 0 && $lineno - $cur_lineno < 3)
+            {
+                $frame['prefix'][] = $line;
+            }
+            elseif ($lineno - $cur_lineno > -3 && $lineno - $cur_lineno < 0)
+            {
+                $frame['suffix'][] = $line;
+            }
+        }
+        fclose($fh);
+        return $frame;
+    }
+}
diff --git a/wp-content/wordpress-sentry/raven/phpunit.xml.dist b/wp-content/wordpress-sentry/raven/phpunit.xml.dist
new file mode 100644
index 000000000..532f1613c
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/phpunit.xml.dist
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit backupGlobals="false"
+         backupStaticAttributes="false"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         stopOnFailure="false"
+         syntaxCheck="false"
+         bootstrap="test/bootstrap.php"
+>
+  <testsuites>
+    <testsuite name="Raven Test Suite">
+      <directory>./test/Raven/</directory>
+    </testsuite>
+  </testsuites>
+
+  <filter>
+    <whitelist>
+      <directory suffix=".php">./lib/Raven/</directory>
+    </whitelist>
+  </filter>
+</phpunit>
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/raven/test/Raven/Tests/ClientTest.php b/wp-content/wordpress-sentry/raven/test/Raven/Tests/ClientTest.php
new file mode 100644
index 000000000..4f27125ed
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/test/Raven/Tests/ClientTest.php
@@ -0,0 +1,142 @@
+<?php
+
+/*
+ * This file is part of Raven.
+ *
+ * (c) Sentry Team
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+class Raven_Tests_ClientTest extends PHPUnit_Framework_TestCase
+{
+    public function testParseDsnHttp()
+    {
+        $result = Raven_Client::parseDsn('http://public:secret@example.com/1');
+
+        $this->assertEquals($result['project'], 1);
+        $this->assertEquals($result['servers'], array('http://example.com/api/store/'));
+        $this->assertEquals($result['public_key'], 'public');
+        $this->assertEquals($result['secret_key'], 'secret');
+    }
+
+    public function testParseDsnHttps()
+    {
+        $result = Raven_Client::parseDsn('https://public:secret@example.com/1');
+
+        $this->assertEquals($result['project'], 1);
+        $this->assertEquals($result['servers'], array('https://example.com/api/store/'));
+        $this->assertEquals($result['public_key'], 'public');
+        $this->assertEquals($result['secret_key'], 'secret');
+    }
+
+    public function testParseDsnPath()
+    {
+        $result = Raven_Client::parseDsn('http://public:secret@example.com/app/1');
+
+        $this->assertEquals($result['project'], 1);
+        $this->assertEquals($result['servers'], array('http://example.com/app/api/store/'));
+        $this->assertEquals($result['public_key'], 'public');
+        $this->assertEquals($result['secret_key'], 'secret');
+    }
+
+    public function testParseDsnPort()
+    {
+        $result = Raven_Client::parseDsn('http://public:secret@example.com:9000/app/1');
+
+        $this->assertEquals($result['project'], 1);
+        $this->assertEquals($result['servers'], array('http://example.com:9000/app/api/store/'));
+        $this->assertEquals($result['public_key'], 'public');
+        $this->assertEquals($result['secret_key'], 'secret');
+    }
+
+    public function testParseDsnInvalidScheme()
+    {
+        try {
+            $result = Raven_Client::parseDsn('gopher://public:secret@/1');
+            $this->fail();
+        } catch (Exception $e) {
+            return;
+        }
+    }
+
+    public function testParseDsnMissingNetloc()
+    {
+        try {
+            $result = Raven_Client::parseDsn('http://public:secret@/1');
+            $this->fail();
+        } catch (Exception $e) {
+            return;
+        }
+    }
+
+    public function testParseDsnMissingProject()
+    {
+        try {
+            $result = Raven_Client::parseDsn('http://public:secret@example.com');
+            $this->fail();
+        } catch (Exception $e) {
+            return;
+        }
+    }
+
+    /**
+     * @expectedException InvalidArgumentException
+     */
+    public function testParseDsnMissingPublicKey()
+    {
+        $result = Raven_Client::parseDsn('http://:secret@example.com/1');
+    }
+    /**
+     * @expectedException InvalidArgumentException
+     */
+    public function testParseDsnMissingSecretKey()
+    {
+        $result = Raven_Client::parseDsn('http://public@example.com/1');
+    }
+
+    public function testDsnFirstArgument()
+    {
+        $client = new Raven_Client('http://public:secret@example.com/1');
+
+        $this->assertEquals($client->project, 1);
+        $this->assertEquals($client->servers, array('http://example.com/api/store/'));
+        $this->assertEquals($client->public_key, 'public');
+        $this->assertEquals($client->secret_key, 'secret');
+    }
+
+    public function testDsnFirstArgumentWithOptions()
+    {
+        $client = new Raven_Client('http://public:secret@example.com/1', array(
+            'site' => 'foo',
+        ));
+
+        $this->assertEquals($client->project, 1);
+        $this->assertEquals($client->servers, array('http://example.com/api/store/'));
+        $this->assertEquals($client->public_key, 'public');
+        $this->assertEquals($client->secret_key, 'secret');
+        $this->assertEquals($client->site, 'foo');
+    }
+
+    public function testOptionsFirstArgument()
+    {
+        $client = new Raven_Client(array(
+            'servers' => array('http://example.com/api/store/'),
+        ));
+
+        $this->assertEquals($client->servers, array('http://example.com/api/store/'));
+    }
+
+    public function testOptionsFirstArgumentWithOptions()
+    {
+        $client = new Raven_Client(array(
+            'servers' => array('http://example.com/api/store/'),
+        ), array(
+            'site' => 'foo',
+        ));
+
+        $this->assertEquals($client->servers, array('http://example.com/api/store/'));
+        $this->assertEquals($client->site, 'foo');
+    }
+}
diff --git a/wp-content/wordpress-sentry/raven/test/Raven/Tests/CompatTest.php b/wp-content/wordpress-sentry/raven/test/Raven/Tests/CompatTest.php
new file mode 100644
index 000000000..39397d902
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/test/Raven/Tests/CompatTest.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of Raven.
+ *
+ * (c) Sentry Team
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+class Raven_Tests_CompatTest extends PHPUnit_Framework_TestCase
+{
+    public function test_gethostname()
+    {
+        $this->assertEquals(Raven_Compat::gethostname(), Raven_Compat::_gethostname());
+        $this->assertTrue(strlen(Raven_Compat::_gethostname()) > 0);
+    }
+
+    public function test_hash_hmac()
+    {
+        $result = Raven_Compat::hash_hmac('sha1', 'foo', 'bar');
+        $this->assertEquals($result, '85d155c55ed286a300bd1cf124de08d87e914f3a');
+
+        $result = Raven_Compat::_hash_hmac('sha1', 'foo', 'bar');
+        $this->assertEquals($result, '85d155c55ed286a300bd1cf124de08d87e914f3a');
+    }
+
+    public function test_json_encode()
+    {
+        $result = Raven_Compat::json_encode(array('foo' => array('bar' => 1)));
+        $this->assertEquals($result, '{"foo":{"bar":1}}');
+
+        $result = Raven_Compat::_json_encode(array('foo' => array('bar' => 1)));
+        $this->assertEquals($result, '{"foo":{"bar":1}}');
+    }
+}
+
diff --git a/wp-content/wordpress-sentry/raven/test/Raven/Tests/ErrorHandlerTest.php b/wp-content/wordpress-sentry/raven/test/Raven/Tests/ErrorHandlerTest.php
new file mode 100644
index 000000000..05384c5e1
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/test/Raven/Tests/ErrorHandlerTest.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of Raven.
+ *
+ * (c) Sentry Team
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+class Raven_Tests_ErrorHandlerTest extends PHPUnit_Framework_TestCase
+{
+    public function testErrorsAreLoggedAsExceptions()
+    {
+        $client = $this->getMock('Client', array('captureException', 'getIdent'));
+        $client->expects($this->once())
+               ->method('captureException')
+               ->with($this->isInstanceOf('ErrorException'));
+
+        $handler = new Raven_ErrorHandler($client);
+        $handler->handleError(E_WARNING, 'message');
+    }
+
+    public function testExceptionsAreLogged()
+    {
+        $client = $this->getMock('Client', array('captureException', 'getIdent'));
+        $client->expects($this->once())
+               ->method('captureException')
+               ->with($this->isInstanceOf('ErrorException'));
+
+        $e = new ErrorException('message', 0, E_WARNING, '', 0);
+
+        $handler = new Raven_ErrorHandler($client);
+        $handler->handleException($e);
+    }
+}
diff --git a/wp-content/wordpress-sentry/raven/test/bootstrap.php b/wp-content/wordpress-sentry/raven/test/bootstrap.php
new file mode 100644
index 000000000..0f18068c7
--- /dev/null
+++ b/wp-content/wordpress-sentry/raven/test/bootstrap.php
@@ -0,0 +1,15 @@
+<?php
+
+/*
+ * This file is part of Raven.
+ *
+ * (c) Sentry Team
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+error_reporting(E_ALL | E_STRICT);
+
+require_once dirname(__FILE__).'/../lib/Raven/Autoloader.php';
+Raven_Autoloader::register();
\ No newline at end of file
diff --git a/wp-content/wordpress-sentry/wordpress-sentry.php b/wp-content/wordpress-sentry/wordpress-sentry.php
new file mode 100644
index 000000000..e72cdcb6a
--- /dev/null
+++ b/wp-content/wordpress-sentry/wordpress-sentry.php
@@ -0,0 +1,49 @@
+<?php
+/*
+Plugin Name: WordPress Sentry Client
+Plugin URI: http://www.hzdg.com
+Description: Sends PHP errors to Django Sentry
+Author: Ryan Bagwell
+Version: 1
+Author URI: http://www.ryanbagwell.com
+*/
+
+require_once( dirname(__FILE__).'/class.wp-raven-client.php' );
+
+class WPSentry extends WP_Raven_Client {
+	
+	function WPSentry() {
+
+		add_action( 'admin_menu', array( $this, 'addOptionsPage' ));
+				
+		if ( is_admin() && $_POST )
+			$this->saveOptions();
+		
+		parent::__construct();
+		
+	}
+	
+	function addOptionsPage() {
+		add_options_page('Sentry Error Reporting Settings', 'Sentry', 8, 'sentrysettings', array( $this, 'printOptionsHTML' ));
+	}
+	
+	function printOptionsHTML() {		
+		extract( $this->settings );
+		require_once( dirname(__FILE__).'/optionspage.html.php' );	
+	}
+	
+	function saveOptions() {
+		
+		if ( !isset( $_POST[ 'sentry_dsn' ] ) || !isset( $_POST[ 'sentry_reporting_level' ]))
+			return;
+		
+		update_option('sentry-settings', array(
+			'dsn' => $_POST[ 'sentry_dsn' ],
+			'reporting_level' => $_POST[ 'sentry_reporting_level' ]
+		));
+
+	}
+
+}
+
+add_action('plugins_loaded', create_function(null, '$wps = new WPSentry(); ') );
\ No newline at end of file
-- 
GitLab