diff --git a/tika-core/src/main/java/org/apache/tika/mime/MediaType.java b/tika-core/src/main/java/org/apache/tika/mime/MediaType.java
index c95731d..15c3ef3 100644
--- a/tika-core/src/main/java/org/apache/tika/mime/MediaType.java
+++ b/tika-core/src/main/java/org/apache/tika/mime/MediaType.java
@@ -16,12 +16,12 @@
  */
 package org.apache.tika.mime;
 
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.SortedMap;
 import java.util.TreeMap;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
@@ -38,6 +38,16 @@ public final class MediaType {
     private static final Pattern SPECIAL_OR_WHITESPACE =
         Pattern.compile("[\\(\\)<>@,;:\\\\\"/\\[\\]\\?=\\s]");
 
+    // TIKA-350: handle charset as first element in content-type
+    // See http://www.ietf.org/rfc/rfc2045.txt for valid mime-type characters.
+    private static final String VALID_MIMETYPE_CHARS = "[^\\c\\(\\)<>@,;:\\\\\"/\\[\\]\\?=\\s]";
+    private static final String MIME_TYPE_PATTERN_STRING = "(" + VALID_MIMETYPE_CHARS + "+)"
+                    + "\\s*/\\s*" + "(" + VALID_MIMETYPE_CHARS + "+)";
+    private static final Pattern CONTENT_TYPE_PATTERN = Pattern.compile(
+                    "(?is)\\s*" + MIME_TYPE_PATTERN_STRING + "\\s*($|;.*)");
+    private static final Pattern CONTENT_TYPE_CHARSET_FIRST_PATTERN = Pattern.compile(
+                    "(?i)\\s*(charset\\s*=\\s*[^\\c;\\s]+)\\s*;\\s*" + MIME_TYPE_PATTERN_STRING);
+
     public static final MediaType OCTET_STREAM =
         new MediaType("application", "octet-stream", NO_PARAMETERS);
 
@@ -49,46 +59,49 @@ public final class MediaType {
 
     /**
      * Parses the given string to a media type. The string is expected to be of
-     * the form "type/subtype(; parameter=...)*" as defined in RFC 2045.
+     * the form "type/subtype(; parameter=...)*" as defined in RFC 2045, though
+     * we also handle "charset=xxx; type/subtype" for broken web servers.
      * 
      * @param string
      *            media type string to be parsed
      * @return parsed media type, or <code>null</code> if parsing fails
      */
     public static MediaType parse(String string) {
-        int colon = string.indexOf(';');
-        if (colon != -1 && colon != string.length()-1) {
-            String primarySubString = string.substring(0, colon);
-            String parameters = string
-                    .substring(colon + 1, string.length());
-
-            MediaType type = parseNoParams(primarySubString);
-            String[] paramBases = parameters.split(";");
-            for (int i = 0; i < paramBases.length; i++) {
-                String[] paramToks = paramBases[i].split("=");
-                String paramName = paramToks[0].trim();
-                String paramValue = paramToks[1].trim();
-                type.parameters.put(paramName, paramValue);
+        String type;
+        String subtype;
+        String params;
+        
+        Matcher m = CONTENT_TYPE_PATTERN.matcher(string);
+        if (m.matches()) {
+            type = m.group(1);
+            subtype = m.group(2);
+            params = m.group(3);
+        } else {
+            m = CONTENT_TYPE_CHARSET_FIRST_PATTERN.matcher(string);
+            if (m.matches()) {
+                params = m.group(1);
+                type = m.group(2);
+                subtype = m.group(3);
+            } else {
+                return null;
             }
-
-            return type;
-
-        } else
-            return parseNoParams(string);
-
-    }
-
-    private static MediaType parseNoParams(String string) {
-        int slash = string.indexOf('/');
-        if (slash != -1) {
-            String type = string.substring(0, slash).trim();
-            String subtype = string.substring(slash + 1).trim();
-            if (type.length() > 0 && subtype.length() > 0) {
-                return new MediaType(type, subtype);
+        }
+        
+        MediaType result = new MediaType(type, subtype);
+        String[] paramPieces = params.split(";");
+        for (String paramPiece : paramPieces) {
+            String[] keyValue = paramPiece.split("=");
+            if (keyValue.length != 2) {
+                continue;
+            }
+            
+            String key = keyValue[0].trim();
+            if (key.length() > 0) {
+                result.parameters.put(key, keyValue[1].trim());
             }
         }
-
-        return null;
+        
+        return result;
     }
 
     private final String type;
diff --git a/tika-parsers/src/test/java/org/apache/tika/mime/MediaTypeTest.java b/tika-parsers/src/test/java/org/apache/tika/mime/MediaTypeTest.java
deleted file mode 100644
index f6194e0..0000000
--- a/tika-parsers/src/test/java/org/apache/tika/mime/MediaTypeTest.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tika.mime;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import junit.framework.TestCase;
-
-public class MediaTypeTest extends TestCase {
-
-    public void testBasics() {
-        assertEquals(
-                "application/octet-stream",
-                new MediaType("application", "octet-stream").toString());
-
-        assertEquals(
-                "text/plain",
-                new MediaType("text", "plain").toString());
-
-        Map<String, String> parameters = new HashMap<String, String>();
-        assertEquals(
-                "text/plain",
-                new MediaType("text", "plain", parameters).toString());
-
-        parameters.put("charset", "UTF-8");
-        assertEquals(
-                "text/plain; charset=UTF-8",
-                new MediaType("text", "plain", parameters).toString());
-
-        parameters.put("x-eol-style", "crlf");
-        assertEquals(
-                "text/plain; charset=UTF-8; x-eol-style=crlf",
-                new MediaType("text", "plain", parameters).toString());
-    }
-
-    public void testLowerCase() {
-        assertEquals(
-                "text/plain",
-                new MediaType("TEXT", "PLAIN").toString());
-        assertEquals(
-                "text/plain",
-                new MediaType("Text", "Plain").toString());
-
-        Map<String, String> parameters = new HashMap<String, String>();
-        assertEquals(
-                "text/plain",
-                new MediaType("text", "PLAIN", parameters).toString());
-
-        parameters.put("CHARSET", "UTF-8");
-        assertEquals(
-                "text/plain; charset=UTF-8",
-                new MediaType("TEXT", "plain", parameters).toString());
-
-        parameters.put("X-Eol-Style", "crlf");
-        assertEquals(
-                "text/plain; charset=UTF-8; x-eol-style=crlf",
-                new MediaType("TeXt", "PlAiN", parameters).toString());
-    }
-
-    public void testTrim() {
-        assertEquals(
-                "text/plain",
-                new MediaType(" text ", " plain ").toString());
-        assertEquals(
-                "text/plain",
-                new MediaType("\ttext", "plain\t").toString());
-
-        Map<String, String> parameters = new HashMap<String, String>();
-        assertEquals(
-                "text/plain",
-                new MediaType("text\r\n", " \tplain", parameters).toString());
-
-        parameters.put(" charset", "UTF-8");
-        assertEquals(
-                "text/plain; charset=UTF-8",
-                new MediaType("\n\ntext", "plain \r", parameters).toString());
-
-        parameters.put("\r\n\tx-eol-style  \t", "crlf");
-        assertEquals(
-                "text/plain; charset=UTF-8; x-eol-style=crlf",
-            new MediaType("    text", "\tplain ", parameters).toString());
-    }
-
-    public void testQuote() {
-        Map<String, String> parameters = new HashMap<String, String>();
-        parameters.put("a", " value with spaces ");
-        parameters.put("b", "text/plain");
-        parameters.put("c", "()<>@,;:\\\"/[]?=");
-        assertEquals(
-                "text/plain; a=\" value with spaces \"; b=\"text\\/plain\""
-                + "; c=\"\\(\\)\\<\\>\\@\\,\\;\\:\\\\\\\"\\/\\[\\]\\?\\=\"",
-                new MediaType("text", "plain", parameters).toString());
-    }
-    
-    /**
-     * @since TIKA-121
-     */
-    public void testParseWithParams() {
-        String mimeStringWithParams = "text/html;charset=UTF-8;foo=bar;foo2=bar2";
-
-        MediaType type = MediaType.parse(mimeStringWithParams);
-        assertNotNull(type);
-        assertNotNull(type.getParameters());
-        assertNotNull(type.getParameters().keySet());
-        assertEquals(3, type.getParameters().keySet().size());
-        boolean gotCharset = false, gotFoo = false, gotFoo2 = false;
-        for (String param : type.getParameters().keySet()) {
-            if (param.equals("charset")) {
-                gotCharset = true;
-            } else if (param.equals("foo")) {
-                gotFoo = true;
-            } else if (param.equals("foo2")) {
-                gotFoo2 = true;
-            }
-        }
-        assertTrue(gotCharset && gotFoo && gotFoo2);
-    }
-
-    /**
-     * @since TIKA-121
-     */
-    public void testParseNoParams() {
-        String mimeStringNoParams = "text/html";
-
-        MediaType type = MediaType.parse(mimeStringNoParams);
-        assertNotNull(type);
-        assertNotNull(type.getParameters());
-        assertNotNull(type.getParameters().keySet());
-        assertEquals(0, type.getParameters().keySet().size());
-    }
-
-    /**
-     * @since TIKA-121
-     */
-    public void testParseNoParamsWithSemi() {
-        String mimeStringNoParamsWithSemi = "text/html;";
-        MediaType type = MediaType.parse(mimeStringNoParamsWithSemi);
-        assertNotNull(type);
-        assertNotNull(type.getParameters());
-        assertNotNull(type.getParameters().keySet());
-        assertEquals(0, type.getParameters().keySet().size());
-    }
-
-    
-}
