diff --git a/composer.json b/composer.json
index 97ef123..81ed919 100644
--- a/composer.json
+++ b/composer.json
@@ -20,7 +20,8 @@
     "symfony-cmf/routing": "1.1.*@alpha",
     "easyrdf/easyrdf": "0.8.*@beta",
     "phpunit/phpunit": "3.7.*",
-    "zendframework/zend-feed": "2.2.*"
+    "zendframework/zend-feed": "2.2.*",
+    "bitworking/mimeparse": "2.0.*"
   },
   "autoload": {
     "psr-0": {
diff --git a/composer.lock b/composer.lock
index 75394ba..cdf183e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -6,6 +6,55 @@
     "hash": "9cad5a32fc0b4c0fac16fbda1b8ead16",
     "packages": [
         {
+            "name": "bitworking/mimeparse",
+            "version": "2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ramsey/mimeparse",
+                "reference": "2.0.0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://github.com/ramsey/mimeparse/zipball/2.0.0",
+                "reference": "2.0.0",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Bitworking": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Joe Gregorio",
+                    "homepage": "http://bitworking.org"
+                },
+                {
+                    "name": "Andrew \"Venom\" K."
+                },
+                {
+                    "name": "Ben Ramsey",
+                    "homepage": "http://benramsey.com"
+                }
+            ],
+            "description": "Basic functions for handling mime-types, forked from Joe Gregorio's mimeparse library <http://code.google.com/p/mimeparse/>.",
+            "homepage": "http://code.google.com/p/mimeparse/",
+            "keywords": [
+                "accept",
+                "http",
+                "mime"
+            ],
+            "time": "2012-09-18 09:55:34"
+        },
+        {
             "name": "doctrine/common",
             "version": "2.3.0",
             "source": {
diff --git a/core/lib/Drupal/Core/ContentNegotiation.php b/core/lib/Drupal/Core/ContentNegotiation.php
index 500200c..5064646 100644
--- a/core/lib/Drupal/Core/ContentNegotiation.php
+++ b/core/lib/Drupal/Core/ContentNegotiation.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core;
 
 use Symfony\Component\HttpFoundation\Request;
+use Drupal\Core\Mimeparse;
 
 /**
  * This class is a central library for content type negotiation.
@@ -39,7 +40,7 @@ public function getContentType(Request $request) {
     // Check all formats, if priority format is found return it.
     $first_found_format = FALSE;
     $priority = array('html', 'drupal_ajax', 'drupal_modal', 'drupal_dialog');
-    foreach ($request->getAcceptableContentTypes() as $mime_type) {
+    foreach (Mimeparse::getWeightedAcceptableContentTypes($request) as $mime_type => $q) {
       $format = $request->getFormat($mime_type);
       if (in_array($format, $priority, TRUE)) {
         return $format;
diff --git a/core/lib/Drupal/Core/Mimeparse.php b/core/lib/Drupal/Core/Mimeparse.php
new file mode 100644
index 0000000..4d68a2c
--- /dev/null
+++ b/core/lib/Drupal/Core/Mimeparse.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Mimeparse.
+ */
+
+namespace Drupal\Core;
+
+use Symfony\Component\HttpFoundation\Request;
+use Bitworking\Mimeparse as BaseMimeparse;
+
+/**
+ * Parses and extracts MIME types from an HTTP request.
+ *
+ * This Mimeparse class is used to get a list of acceptable MIME type with their
+ * associated quality factor (weight).
+ */
+class Mimeparse extends BaseMimeparse {
+
+  /**
+   * Extracts acceptable MIME types with quality factors from a request.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   A Request object from which to extract the MIME types.
+   *
+   * @return array
+   *   An array of MIME types and their associated quality factor.
+   */
+  static public function getWeightedAcceptableContentTypes(Request $request) {
+    $parsedHeader = explode(',', $request->headers->get('Accept'));
+
+    // Builds an array of acceptable MIME types and their quality factor.
+    foreach ($parsedHeader as $i => $r) {
+      $normalized = static::parseAndNormalizeMediaRange($r);
+      $mimetype = $normalized[0] . '/' . $normalized[1];
+      $weighted_mimetypes[$mimetype] = $normalized[2]['q'];
+    }
+    arsort($weighted_mimetypes);
+
+    return $weighted_mimetypes;
+  }
+}
diff --git a/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php b/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php
index f77e254..1b478b7 100644
--- a/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php
+++ b/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php
@@ -11,6 +11,7 @@
 use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
 use Symfony\Component\Routing\RouteCollection;
 use Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface;
+use Drupal\Core\Mimeparse;
 
 /**
  * This class filters routes based on the media type in HTTP Accept headers.
@@ -23,9 +24,8 @@ class MimeTypeMatcher implements RouteFilterInterface {
    */
   public function filter(RouteCollection $collection, Request $request) {
     // Generates a list of Symfony formats matching the acceptable MIME types.
-    // @todo replace by proper content negotiation library.
-    $acceptable_mime_types = $request->getAcceptableContentTypes();
-    $acceptable_formats = array_map(array($request, 'getFormat'), $acceptable_mime_types);
+    $acceptable_mime_types = Mimeparse::getWeightedAcceptableContentTypes($request);
+    $acceptable_formats = array_map(array($request, 'getFormat'), array_keys($acceptable_mime_types));
 
     $filtered_collection = new RouteCollection();
 
diff --git a/core/vendor/bitworking/mimeparse/.gitignore b/core/vendor/bitworking/mimeparse/.gitignore
new file mode 100644
index 0000000..7e8f330
--- /dev/null
+++ b/core/vendor/bitworking/mimeparse/.gitignore
@@ -0,0 +1,6 @@
+.DS_Store
+phpunit.xml
+composer.lock
+build
+vendor
+*.phar
diff --git a/core/vendor/bitworking/mimeparse/.travis.yml b/core/vendor/bitworking/mimeparse/.travis.yml
new file mode 100644
index 0000000..4414a94
--- /dev/null
+++ b/core/vendor/bitworking/mimeparse/.travis.yml
@@ -0,0 +1,11 @@
+language: php
+
+php:
+  - 5.3
+  - 5.4
+
+before_script:
+  - curl -s http://getcomposer.org/installer | php -- --quiet
+  - php composer.phar install
+
+script: phpunit
diff --git a/core/vendor/bitworking/mimeparse/LICENSE b/core/vendor/bitworking/mimeparse/LICENSE
new file mode 100644
index 0000000..c337658
--- /dev/null
+++ b/core/vendor/bitworking/mimeparse/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Joe Gregorio
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/core/vendor/bitworking/mimeparse/README.md b/core/vendor/bitworking/mimeparse/README.md
new file mode 100644
index 0000000..02b1232
--- /dev/null
+++ b/core/vendor/bitworking/mimeparse/README.md
@@ -0,0 +1,68 @@
+# Bitworking\Mimeparse
+
+[![Build Status](https://secure.travis-ci.org/ramsey/mimeparse.png)](http://travis-ci.org/ramsey/mimeparse)
+
+This library provides basic functionality for parsing mime-types names and
+matching them against a list of media-ranges. See [section 14.1][http-accept] of
+[RFC 2616 (the HTTP specification)][http] for a complete explanation. More
+information on the library can be found in the XML.com article
+"[Just use Media Types?][jgregorio-restful]"
+
+This library was taken from the [original mimeparse library][mimeparse]
+on Google Project Hosting and has been cleaned up to conform to [PSR-0][],
+[PSR-1][], and [PSR-2][] standards. It also now has support for [Composer][].
+The Bitworking namespace is a nod to [Joe Gregorio][jgregorio], the original
+author of this library.
+
+## Examples
+
+Use Mimeparse to specify a list of media types your application supports and
+compare that to the list of media types the user agent accepts (via the
+[HTTP Accept][http-accept] header; `$_SERVER['HTTP_ACCEPT']`). Mimeparse will
+give you the best match to send back to the user agent for your list of
+supported types or `null` if there is no best match.
+
+```php
+<?php
+$supportedTypes = array('application/xbel+xml', 'text/xml');
+$httpAcceptHeader = 'text/*;q=0.5,*/*; q=0.1';
+$mimeType = \Bitworking\Mimeparse::bestMatch($supportedTypes, $httpAcceptHeader);
+echo $mimeType; // Should echo "text/xml"
+```
+
+You may also use Mimeparse to get the quality value of a specific media type
+when compared against a range of media types (from the Accept header, for example).
+
+```php
+<?php
+$httpAcceptHeader = 'text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, *\/*;q=0.5';
+$quality = \Bitworking\Mimeparse::quality('text/html', $httpAcceptHeader);
+echo $quality; // Should echo 0.7
+```
+
+## Installation
+
+The preferred method of installation is via [Packagist][], as this provides
+the PSR-0 autoloader functionality. The following `composer.json` will download
+and install the latest version of the Mimeparse library into your project:
+
+```json
+{
+    "require": {
+        "bitworking/mimeparse": "*"
+    }
+}
+```
+
+
+[http-accept]: http://tools.ietf.org/html/rfc2616#section-14.1
+[http]: http://tools.ietf.org/html/rfc2616
+[jgregorio-restful]: http://www.xml.com/pub/a/2005/06/08/restful.html
+[mimeparse]: http://code.google.com/p/mimeparse/
+[PSR-0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
+[PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
+[PSR-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
+[composer]: http://getcomposer.org/
+[jgregorio]: http://bitworking.org/
+[packagist]: http://packagist.org/
+
diff --git a/core/vendor/bitworking/mimeparse/composer.json b/core/vendor/bitworking/mimeparse/composer.json
new file mode 100644
index 0000000..d9246b3
--- /dev/null
+++ b/core/vendor/bitworking/mimeparse/composer.json
@@ -0,0 +1,31 @@
+{
+    "name": "bitworking/mimeparse",
+    "description": "Basic functions for handling mime-types, forked from Joe Gregorio's mimeparse library <http://code.google.com/p/mimeparse/>.",
+    "type": "library",
+    "keywords": ["http", "accept", "mime"],
+    "homepage": "http://code.google.com/p/mimeparse/",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Joe Gregorio",
+            "homepage": "http://bitworking.org"
+        },
+        {
+            "name": "Andrew \"Venom\" K."
+        },
+        {
+            "name": "Ben Ramsey",
+            "homepage": "http://benramsey.com"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/ramsey/mimeparse/issues",
+        "source": "https://github.com/ramsey/mimeparse"
+    },
+    "require": {
+        "php": ">=5.3.3"
+    },
+    "autoload": {
+        "psr-0": { "Bitworking": "src/" }
+    }
+}
diff --git a/core/vendor/bitworking/mimeparse/phpunit.xml.dist b/core/vendor/bitworking/mimeparse/phpunit.xml.dist
new file mode 100644
index 0000000..d3ce1a2
--- /dev/null
+++ b/core/vendor/bitworking/mimeparse/phpunit.xml.dist
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./tests/bootstrap.php" colors="true">
+    <testsuites>
+        <testsuite>
+            <directory>./tests</directory>
+        </testsuite>
+    </testsuites>
+    <filter>
+        <whitelist>
+            <directory suffix=".php">./src</directory>
+        </whitelist>
+    </filter>
+    <logging>
+        <log type="coverage-html" target="build/coverage" title="Bitworking\Mimeparse"
+            charset="UTF-8" yui="true" highlight="true"
+            lowUpperBound="35" highLowerBound="70"/>
+        <log type="coverage-clover" target="build/logs/clover.xml"/>
+        <log type="junit" target="build/logs/junit.xml"
+            logIncompleteSkipped="false"/>
+    </logging>
+</phpunit>
+
diff --git a/core/vendor/bitworking/mimeparse/src/Bitworking/Mimeparse.php b/core/vendor/bitworking/mimeparse/src/Bitworking/Mimeparse.php
new file mode 100644
index 0000000..1b25caa
--- /dev/null
+++ b/core/vendor/bitworking/mimeparse/src/Bitworking/Mimeparse.php
@@ -0,0 +1,248 @@
+<?php
+/**
+ * Mimeparse class. Provides basic functions for handling mime-types. It can
+ * match mime-types against a list of media-ranges. See section 14.1 of the
+ * HTTP specification [RFC 2616] for a complete explanation.
+ *
+ * It's a PHP port of the original Python code
+ * (http://code.google.com/p/mimeparse/).
+ *
+ * Ported from version 0.1.2. Comments are mostly excerpted from the original.
+ *
+ * @author Joe Gregorio
+ * @author Andrew "Venom" K.
+ * @author Ben Ramsey
+ */
+namespace Bitworking;
+
+class Mimeparse
+{
+    /**
+     * Parses a media-range and returns an array with its components.
+     *
+     * The returned array contains:
+     *
+     * 1. type: The type categorization.
+     * 2. subtype: The subtype categorization.
+     * 3. params: An associative array of all the parameters for the
+     *    media-range.
+     * 4. generic subtype: A more generic subtype, if one is present. See
+     *    http://tools.ietf.org/html/rfc3023#appendix-A.12
+     *
+     * For example, the media-range "application/xhtml+xml;q=0.5" would get
+     * parsed into:
+     *
+     * array("application", "xhtml+xml", array( "q" => "0.5" ), "xml")
+     *
+     * @param string $mediaRange
+     * @return array ($type, $subtype, $params, $genericSubtype)
+     * @throws UnexpectedValueException when $mediaRange does not include a
+     * valid subtype
+     */
+    public static function parseMediaRange($mediaRange)
+    {
+        $parts = explode(';', $mediaRange);
+
+        $params = array();
+        foreach ($parts as $i => $param) {
+            if (strpos($param, '=') !== false) {
+                list($k, $v) = explode('=', trim($param));
+                $params[$k] = $v;
+            }
+        }
+
+        $fullType = trim($parts[0]);
+
+        // Java URLConnection class sends an Accept header that includes a
+        // single "*". Turn it into a legal wildcard.
+        if ($fullType == '*') {
+            $fullType = '*/*';
+        }
+
+        list($type, $subtype) = explode('/', $fullType);
+
+        if (!$subtype) {
+            throw new \UnexpectedValueException('Malformed media-range: '.$mediaRange);
+        }
+
+        $plusPos = strpos($subtype, '+');
+        if (false !== $plusPos) {
+            $genericSubtype = substr($subtype, $plusPos + 1);
+        } else {
+            $genericSubtype = $subtype;
+        }
+
+        return array(trim($type), trim($subtype), $params, $genericSubtype);
+    }
+
+
+    /**
+     * Parses a media-range via Mimeparse::parseMediaRange() and guarantees that
+     * there is a value for the "q" param, filling it in with a proper default
+     * if necessary.
+     *
+     * @param string $mediaRange
+     * @return array ($type, $subtype, $params, $genericSubtype)
+     */
+    protected static function parseAndNormalizeMediaRange($mediaRange)
+    {
+        $parsedMediaRange = self::parseMediaRange($mediaRange);
+        $params = $parsedMediaRange[2];
+
+        if (!isset($params['q'])
+            || !is_numeric($params['q'])
+            || floatval($params['q']) > 1
+            || floatval($params['q']) < 0
+        ) {
+            $parsedMediaRange[2]['q'] = '1';
+        }
+
+        return $parsedMediaRange;
+    }
+
+    /**
+     * Find the best match for a given mime-type against a list of
+     * media-ranges that have already been parsed by
+     * Mimeparse::parseAndNormalizeMediaRange()
+     *
+     * Returns the fitness and the "q" quality parameter of the best match, or
+     * an array [-1, 0] if no match was found. Just as for
+     * Mimeparse::quality(), $parsedRanges must be an array of parsed
+     * media-ranges.
+     *
+     * @param string $mimeType
+     * @param array  $parsedRanges
+     * @return array ($bestFitQuality, $bestFitness)
+     */
+    protected static function qualityAndFitnessParsed($mimeType, $parsedRanges)
+    {
+        $bestFitness = -1;
+        $bestFitQuality = 0;
+        list($targetType, $targetSubtype, $targetParams) = self::parseAndNormalizeMediaRange($mimeType);
+
+        foreach ($parsedRanges as $item) {
+            list($type, $subtype, $params) = $item;
+
+            if (($type == $targetType || $type == '*' || $targetType == '*')
+                && ($subtype == $targetSubtype || $subtype == '*' || $targetSubtype == '*')) {
+
+                $paramMatches = 0;
+                foreach ($targetParams as $k => $v) {
+                    if ($k != 'q' && isset($params[$k]) && $v == $params[$k]) {
+                        $paramMatches++;
+                    }
+                }
+
+                $fitness  = ($type == $targetType) ? 100 : 0;
+                $fitness += ($subtype == $targetSubtype) ? 10 : 0;
+                $fitness += $paramMatches;
+
+                if ($fitness > $bestFitness) {
+                    $bestFitness = $fitness;
+                    $bestFitQuality = $params['q'];
+                }
+            }
+        }
+
+        return array((float) $bestFitQuality, $bestFitness);
+    }
+
+    /**
+     * Find the best match for a given mime-type against a list of
+     * media-ranges that have already been parsed by
+     * Mimeparse::parseAndNormalizeMediaRange()
+     *
+     * Returns the "q" quality parameter of the best match, 0 if no match was
+     * found. This function behaves the same as Mimeparse::quality() except
+     * that $parsedRanges must be an array of parsed media-ranges.
+     *
+     * @param string $mimeType
+     * @param array  $parsedRanges
+     * @return float $q
+     */
+    protected static function qualityParsed($mimeType, $parsedRanges)
+    {
+        list($q, $fitness) = self::qualityAndFitnessParsed($mimeType, $parsedRanges);
+        return $q;
+    }
+
+    /**
+     * Returns the quality "q" of a mime-type when compared against the
+     * media-ranges in ranges. For example:
+     *
+     * Mimeparse::quality("text/html", "text/*;q=0.3, text/html;q=0.7,
+     * text/html;level=1, text/html;level=2;q=0.4, *\/*;q=0.5")
+     * => 0.7
+     *
+     * @param string $mimeType
+     * @param string $ranges
+     * @return float
+     */
+    public static function quality($mimeType, $ranges)
+    {
+        $parsedRanges = explode(',', $ranges);
+
+        foreach ($parsedRanges as $i => $r) {
+            $parsedRanges[$i] = self::parseAndNormalizeMediaRange($r);
+        }
+
+        return self::qualityParsed($mimeType, $parsedRanges);
+    }
+
+    /**
+     * Takes a list of supported mime-types and finds the best match for all
+     * the media-ranges listed in header. The value of $header must be a
+     * string that conforms to the format of the HTTP Accept: header. The
+     * value of $supported is an array of mime-types.
+     *
+     * In case of ties the mime-type with the lowest index in $supported will
+     * be used.
+     *
+     * Mimeparse::bestMatch(array("application/xbel+xml", "text/xml"), "text/*;q=0.5,*\/*; q=0.1")
+     * => "text/xml"
+     *
+     * @param  array  $supported
+     * @param  string $header
+     * @return mixed  $mimeType or NULL
+     */
+    public static function bestMatch($supported, $header)
+    {
+        $parsedHeader = explode(',', $header);
+
+        foreach ($parsedHeader as $i => $r) {
+            $parsedHeader[$i] = self::parseAndNormalizeMediaRange($r);
+        }
+
+        $weightedMatches = array();
+        foreach ($supported as $index => $mimeType) {
+            list($quality, $fitness) = self::qualityAndFitnessParsed($mimeType, $parsedHeader);
+            if (!empty($quality)) {
+                // Mime-types closer to the beginning of the array are 
+                // preferred. This preference score is used to break ties.
+                $preference = 0 - $index;
+                $weightedMatches[] = array(
+                    array($quality, $fitness, $preference),
+                    $mimeType
+                );
+            }
+        }
+
+        // Note that since fitness and preference are present in 
+        // $weightedMatches they will also be used when sorting (after quality 
+        // level).
+        array_multisort($weightedMatches);
+        $firstChoice = array_pop($weightedMatches);
+
+        return (empty($firstChoice[0][0]) ? null : $firstChoice[1]);
+    }
+
+    /**
+     * Disable access to constructor
+     *
+     * @codeCoverageIgnore
+     */
+    private function __construct()
+    {
+    }
+}
+
diff --git a/core/vendor/bitworking/mimeparse/tests/Bitworking/MimeparseTest.php b/core/vendor/bitworking/mimeparse/tests/Bitworking/MimeparseTest.php
new file mode 100644
index 0000000..5a47427
--- /dev/null
+++ b/core/vendor/bitworking/mimeparse/tests/Bitworking/MimeparseTest.php
@@ -0,0 +1,210 @@
+<?php
+namespace Bitworking;
+
+use Bitworking\Mimeparse;
+
+class MimeparseTest extends \PHPUnit_Framework_TestCase
+{
+    public function testParseMediaRange()
+    {
+        $expected = array(
+            'application',
+            'xml',
+            array('q' => '1'),
+            'xml'
+        );
+        
+        $this->assertEquals($expected, Mimeparse::parseMediaRange('application/xml; q=1'));
+    }
+    
+    public function testParseMediaRangeWithGenericSubtype()
+    {
+        $expected = array(
+            'application',
+            'xhtml+xml',
+            array('q' => '1'),
+            'xml'
+        );
+        
+        $this->assertEquals($expected, Mimeparse::parseMediaRange('application/xhtml+xml; q=1'));
+    }
+
+    public function testParseMediaRangeWithSingleWildCard()
+    {
+        $expected = array(
+            '*',
+            '*',
+            array(),
+            '*'
+        );
+
+        $this->assertEquals($expected, Mimeparse::parseMediaRange('*'));
+    }
+
+    /**
+     * @expectedException UnexpectedValueException
+     * @expectedExceptionMessage Malformed media-range: application/;q=1
+     */
+    public function testParseMediaRangeWithMalformedMediaRange()
+    {
+        $parsed = Mimeparse::parseMediaRange('application/;q=1');
+    }
+
+    /**
+     * Testing this protected method because it includes a lot of parsing
+     * functionality that we wish to isolate from other tests.
+     *
+     * @covers Bitworking\Mimeparse::parseAndNormalizeMediaRange
+     */
+    public function testParseAndNormalizeMediaRange()
+    {
+        $method = new \ReflectionMethod('Bitworking\Mimeparse', 'parseAndNormalizeMediaRange');
+        $method->setAccessible(true);
+
+        $expected1 = array(
+            0 => 'application',
+            1 => 'xml',
+            2 => array('q' => '1'),
+            3 => 'xml',
+        );
+
+        $this->assertEquals($expected1, $method->invoke(null, 'application/xml;q=1'));
+        $this->assertEquals($expected1, $method->invoke(null, 'application/xml'));
+        $this->assertEquals($expected1, $method->invoke(null, 'application/xml;q='));
+
+        $expected2 = array(
+            0 => 'application',
+            1 => 'xml',
+            2 => array('q' => '1', 'b' => 'other'),
+            3 => 'xml',
+        );
+
+        $this->assertEquals($expected2, $method->invoke(null, 'application/xml ; q=1;b=other'));
+        $this->assertEquals($expected2, $method->invoke(null, 'application/xml ; q=2;b=other'));
+
+        // Java URLConnection class sends an Accept header that includes a single "*"
+        $this->assertEquals(array(
+            0 => '*',
+            1 => '*',
+            2 => array('q' => '.2'),
+            3 => '*',
+        ), $method->invoke(null, ' *; q=.2'));
+    }
+
+    /**
+     * @covers Bitworking\Mimeparse::quality
+     * @covers Bitworking\Mimeparse::qualityParsed
+     * @covers Bitworking\Mimeparse::qualityAndFitnessParsed
+     */
+    public function testQuality()
+    {
+        $accept = 'text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5';
+
+        $this->assertEquals(1, Mimeparse::quality('text/html;level=1', $accept));
+        $this->assertEquals(0.7, Mimeparse::quality('text/html', $accept));
+        $this->assertEquals(0.3, Mimeparse::quality('text/plain', $accept));
+        $this->assertEquals(0.5, Mimeparse::quality('image/jpeg', $accept));
+        $this->assertEquals(0.4, Mimeparse::quality('text/html;level=2', $accept));
+        $this->assertEquals(0.7, Mimeparse::quality('text/html;level=3', $accept));
+    }
+
+    /**
+     * @covers Bitworking\Mimeparse::bestMatch
+     */
+    public function testBestMatch()
+    {
+        $supportedMimeTypes1 = array('application/xbel+xml', 'application/xml');
+
+        // direct match
+        $this->assertEquals('application/xbel+xml', Mimeparse::bestMatch($supportedMimeTypes1, 'application/xbel+xml'));
+
+        // direct match with a q parameter
+        $this->assertEquals('application/xbel+xml', Mimeparse::bestMatch($supportedMimeTypes1, 'application/xbel+xml; q=1'));
+
+        // direct match of our second choice with a q parameter
+        $this->assertEquals('application/xml', Mimeparse::bestMatch($supportedMimeTypes1, 'application/xml; q=1'));
+
+        // match using a subtype wildcard
+        $this->assertEquals('application/xbel+xml', Mimeparse::bestMatch($supportedMimeTypes1, 'application/*; q=1'));
+
+        // match using a type wildcard
+        $this->assertEquals('application/xbel+xml', Mimeparse::bestMatch($supportedMimeTypes1, '* / *'));
+
+
+        $supportedMimeTypes2 = array('application/xbel+xml', 'text/xml');
+
+        // match using a type versus a lower weighted subtype
+        $this->assertEquals('text/xml', Mimeparse::bestMatch($supportedMimeTypes2, 'text/ *;q=0.5,* / *;q=0.1'));
+
+        // fail to match anything
+        $this->assertEquals(null, Mimeparse::bestMatch($supportedMimeTypes2, 'text/html,application/atom+xml; q=0.9'));
+
+
+        $supportedMimeTypes3 = array('application/json', 'text/html');
+
+        // common Ajax scenario
+        $this->assertEquals('application/json', Mimeparse::bestMatch($supportedMimeTypes3, 'application/json, text/javascript, */*'));
+
+        // verify fitness sorting
+        $this->assertEquals('application/json', Mimeparse::bestMatch($supportedMimeTypes3, 'application/json, text/html;q=0.9'));
+
+
+        $supportedMimeTypes4 = array('image/*', 'application/xml');
+
+        // match using a type wildcard
+        $this->assertEquals('image/*', Mimeparse::bestMatch($supportedMimeTypes4, 'image/png'));
+
+        // match using a wildcard for both requested and supported
+        $this->assertEquals('image/*', Mimeparse::bestMatch($supportedMimeTypes4, 'image/*'));
+    }
+
+    /**
+     * @covers Bitworking\Mimeparse::bestMatch
+     * @see http://shiflett.org/blog/2011/may/the-accept-header
+     * @see http://code.google.com/p/mimeparse/issues/detail?id=15
+     */
+    public function testZeroQuality()
+    {
+        $supportedMimeTypes = array('application/json');
+        $httpAcceptHeader = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json;q=0.0';
+
+        $this->assertNull(Mimeparse::bestMatch($supportedMimeTypes, $httpAcceptHeader));
+        $this->assertNull(Mimeparse::bestMatch($supportedMimeTypes, 'application/xml,*/*;q=0'));
+    }
+
+    /**
+     * @covers Bitworking\Mimeparse::bestMatch
+     */
+    public function testStarSlashStarWithItemOfZeroQuality()
+    {
+        $supportedMimeTypes = array('text/plain', 'application/json');
+        $httpAcceptHeader = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json;q=0.0';
+
+        $this->assertEquals('text/plain', Mimeparse::bestMatch($supportedMimeTypes, $httpAcceptHeader));
+    }
+
+    /**
+     * @covers Bitworking\Mimeparse::bestMatch
+     * @see http://code.google.com/p/mimeparse/issues/detail?id=10
+     */
+    public function testStarSlashStarWithHigherQualityThanMoreSpecificType()
+    {
+        $supportedMimeTypes = array('image/jpeg', 'text/plain');
+        $httpAcceptHeader = 'text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5';
+
+        $this->assertEquals('image/jpeg', Mimeparse::bestMatch($supportedMimeTypes, $httpAcceptHeader));
+    }
+
+    /**
+     * @covers Bitworking\Mimeparse::bestMatch
+     */
+    public function testBestMatchWithTies()
+    {
+        $supportedMimeTypes1 = array('text/html', 'application/json', 'application/hal+xml', 'application/hal+json');
+        $supportedMimeTypes2 = array('text/html', 'application/hal+json', 'application/json', 'application/hal+xml');
+        $httpAcceptHeader = 'application/*, text/*;q=0.8';
+
+        $this->assertEquals('application/json', Mimeparse::bestMatch($supportedMimeTypes1, $httpAcceptHeader));
+        $this->assertEquals('application/hal+json', Mimeparse::bestMatch($supportedMimeTypes2, $httpAcceptHeader));
+    }
+}
diff --git a/core/vendor/bitworking/mimeparse/tests/bootstrap.php b/core/vendor/bitworking/mimeparse/tests/bootstrap.php
new file mode 100644
index 0000000..19834b8
--- /dev/null
+++ b/core/vendor/bitworking/mimeparse/tests/bootstrap.php
@@ -0,0 +1,13 @@
+<?php
+
+error_reporting(E_ALL | E_STRICT);
+
+// Ensure that composer has installed all dependencies
+if (!file_exists(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'composer.lock')) {
+    die("Dependencies must be installed using composer:\n\nphp composer.phar install --dev\n\n"
+        . "See http://getcomposer.org for help with installing composer\n");
+}
+
+// Include the Composer autoloader
+include realpath(dirname(__FILE__) . '/../vendor/autoload.php');
+
diff --git a/core/vendor/composer/autoload_namespaces.php b/core/vendor/composer/autoload_namespaces.php
index 87cf570..a3d525c 100644
--- a/core/vendor/composer/autoload_namespaces.php
+++ b/core/vendor/composer/autoload_namespaces.php
@@ -6,32 +6,33 @@
 $baseDir = dirname(dirname($vendorDir));
 
 return array(
-    'Zend\\Stdlib\\' => array($vendorDir . '/zendframework/zend-stdlib'),
-    'Zend\\Feed\\' => array($vendorDir . '/zendframework/zend-feed'),
-    'Zend\\Escaper\\' => array($vendorDir . '/zendframework/zend-escaper'),
-    'Twig_' => array($vendorDir . '/twig/twig/lib'),
-    'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
-    'Symfony\\Component\\Validator\\' => array($vendorDir . '/symfony/validator'),
-    'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
-    'Symfony\\Component\\Serializer\\' => array($vendorDir . '/symfony/serializer'),
-    'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
-    'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
-    'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
-    'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
-    'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
-    'Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'),
-    'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
-    'Symfony\\Component\\ClassLoader\\' => array($vendorDir . '/symfony/class-loader'),
-    'Symfony\\Cmf\\Component\\Routing' => array($vendorDir . '/symfony-cmf/routing'),
-    'Psr\\Log\\' => array($vendorDir . '/psr/log'),
-    'Guzzle\\Stream' => array($vendorDir . '/guzzle/stream'),
-    'Guzzle\\Parser' => array($vendorDir . '/guzzle/parser'),
-    'Guzzle\\Http' => array($vendorDir . '/guzzle/http'),
-    'Guzzle\\Common' => array($vendorDir . '/guzzle/common'),
-    'EasyRdf_' => array($vendorDir . '/easyrdf/easyrdf/lib'),
-    'Drupal\\Driver' => array($baseDir . '/drivers/lib'),
-    'Drupal\\Core' => array($baseDir . '/core/lib'),
-    'Drupal\\Component' => array($baseDir . '/core/lib'),
-    'Doctrine\\Common' => array($vendorDir . '/doctrine/common/lib'),
-    'Assetic' => array($vendorDir . '/kriswallsmith/assetic/src'),
+    'Zend\\Stdlib\\' => $vendorDir . '/zendframework/zend-stdlib/',
+    'Zend\\Feed\\' => $vendorDir . '/zendframework/zend-feed/',
+    'Zend\\Escaper\\' => $vendorDir . '/zendframework/zend-escaper/',
+    'Twig_' => $vendorDir . '/twig/twig/lib/',
+    'Symfony\\Component\\Yaml\\' => $vendorDir . '/symfony/yaml/',
+    'Symfony\\Component\\Validator\\' => $vendorDir . '/symfony/validator/',
+    'Symfony\\Component\\Translation\\' => $vendorDir . '/symfony/translation/',
+    'Symfony\\Component\\Serializer\\' => $vendorDir . '/symfony/serializer/',
+    'Symfony\\Component\\Routing\\' => $vendorDir . '/symfony/routing/',
+    'Symfony\\Component\\Process\\' => $vendorDir . '/symfony/process/',
+    'Symfony\\Component\\HttpKernel\\' => $vendorDir . '/symfony/http-kernel/',
+    'Symfony\\Component\\HttpFoundation\\' => $vendorDir . '/symfony/http-foundation/',
+    'Symfony\\Component\\EventDispatcher\\' => $vendorDir . '/symfony/event-dispatcher/',
+    'Symfony\\Component\\DependencyInjection\\' => $vendorDir . '/symfony/dependency-injection/',
+    'Symfony\\Component\\Debug\\' => $vendorDir . '/symfony/debug/',
+    'Symfony\\Component\\ClassLoader\\' => $vendorDir . '/symfony/class-loader/',
+    'Symfony\\Cmf\\Component\\Routing' => $vendorDir . '/symfony-cmf/routing/',
+    'Psr\\Log\\' => $vendorDir . '/psr/log/',
+    'Guzzle\\Stream' => $vendorDir . '/guzzle/stream/',
+    'Guzzle\\Parser' => $vendorDir . '/guzzle/parser/',
+    'Guzzle\\Http' => $vendorDir . '/guzzle/http/',
+    'Guzzle\\Common' => $vendorDir . '/guzzle/common/',
+    'EasyRdf_' => $vendorDir . '/easyrdf/easyrdf/lib/',
+    'Drupal\\Driver' => $baseDir . '/drivers/lib/',
+    'Drupal\\Core' => $baseDir . '/core/lib/',
+    'Drupal\\Component' => $baseDir . '/core/lib/',
+    'Doctrine\\Common' => $vendorDir . '/doctrine/common/lib/',
+    'Bitworking' => $vendorDir . '/bitworking/mimeparse/src/',
+    'Assetic' => $vendorDir . '/kriswallsmith/assetic/src/',
 );
diff --git a/core/vendor/composer/installed.json b/core/vendor/composer/installed.json
index 322247d..0debc09 100644
--- a/core/vendor/composer/installed.json
+++ b/core/vendor/composer/installed.json
@@ -1731,5 +1731,56 @@
             "feed",
             "zf2"
         ]
+    },
+    {
+        "name": "bitworking/mimeparse",
+        "version": "2.0.0",
+        "version_normalized": "2.0.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/ramsey/mimeparse",
+            "reference": "2.0.0"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://github.com/ramsey/mimeparse/zipball/2.0.0",
+            "reference": "2.0.0",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3"
+        },
+        "time": "2012-09-18 09:55:34",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Bitworking": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Joe Gregorio",
+                "homepage": "http://bitworking.org"
+            },
+            {
+                "name": "Andrew \"Venom\" K."
+            },
+            {
+                "name": "Ben Ramsey",
+                "homepage": "http://benramsey.com"
+            }
+        ],
+        "description": "Basic functions for handling mime-types, forked from Joe Gregorio's mimeparse library <http://code.google.com/p/mimeparse/>.",
+        "homepage": "http://code.google.com/p/mimeparse/",
+        "keywords": [
+            "accept",
+            "http",
+            "mime"
+        ]
     }
 ]
