Index: jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml
===================================================================
--- jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml	(revision 936184)
+++ jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml	(revision )
@@ -204,6 +204,10 @@
             The webdav servlet that connects HTTP request to the repository.
         </description>
         <servlet-class>org.apache.jackrabbit.j2ee.SimpleWebdavServlet</servlet-class>
+        <!--
+            To enable HTTP Digest authentication, change the class above to
+            <servlet-class>org.apache.jackrabbit.j2ee.DigestWebdavServlet</servlet-class>
+        -->
 
         <init-param>
             <param-name>resource-path-prefix</param-name>
Index: jackrabbit-core/src/test/resources/passwords.properties
===================================================================
--- jackrabbit-core/src/test/resources/passwords.properties	(revision )
+++ jackrabbit-core/src/test/resources/passwords.properties	(revision )
@@ -0,0 +1,2 @@
+#Digest of fakeuser:jackrabbit:fakepassword
+fakeuser=5d03107efa7fc691c6b34271fc28004c
\ No newline at end of file
Index: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/TestAll.java
===================================================================
--- jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/TestAll.java	(revision 961487)
+++ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/TestAll.java	(revision )
@@ -31,6 +31,7 @@
         suite.addTestSuite(SimpleCredentialsAuthenticationTest.class);
         suite.addTestSuite(CryptedSimpleCredentialsTest.class);
         suite.addTestSuite(LoginModuleTest.class);
+        suite.addTestSuite(DigestAuthenticationTest.class);
 
         return suite;
     }
Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DigestWebdavServlet.java
===================================================================
--- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DigestWebdavServlet.java	(revision )
+++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DigestWebdavServlet.java	(revision )
@@ -0,0 +1,77 @@
+/*
+ * 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.jackrabbit.j2ee;
+
+import org.apache.jackrabbit.server.CredentialsProvider;
+import org.apache.jackrabbit.server.DigestCredentialsProvider;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.WebdavRequest;
+import org.apache.jackrabbit.webdav.WebdavResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Extension of the standard WebDAV servlet to support HTTP Digest authentication.
+ */
+public class DigestWebdavServlet extends SimpleWebdavServlet {
+	
+	private static final long serialVersionUID = 7796841861774352679L;
+
+	private static final Logger log = LoggerFactory.getLogger(DigestWebdavServlet.class);
+	
+	private static final String key = "jackrabbit";
+
+    private static final String realmName = "jackrabbit";
+
+	@Override
+	protected void sendUnauthorized(WebdavRequest request,
+			WebdavResponse response, DavException error) throws IOException {
+		
+		String nOnce = generateNOnce(request);
+
+        String header = "Digest realm=\"" + realmName + "\", "
+        +  "qop=\"auth\", nonce=\"" + nOnce + "\", " + "opaque=\""
+        + Text.md5(nOnce) + "\"";
+
+		if (log.isDebugEnabled()) {
+            log.debug("WWW-Authenticate " + header);
+        }        
+		response.setHeader("WWW-Authenticate", header);
+		response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+	}
+	
+	@Override
+	protected CredentialsProvider getCredentialsProvider() {
+		return new DigestCredentialsProvider();
+	}
+
+    protected String generateNOnce(HttpServletRequest request) {
+
+        long currentTime = System.currentTimeMillis();
+
+        String nOnceValue = request.getRemoteAddr() + ":" +
+            currentTime + ":" + key;
+
+        return Text.md5(nOnceValue);
+    }
+
+}
Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/DigestPasswordUtil.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/DigestPasswordUtil.java	(revision )
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/DigestPasswordUtil.java	(revision )
@@ -0,0 +1,44 @@
+/*
+ * 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.jackrabbit.util;
+
+/**
+ * Utility to generate a password digest
+ */
+public class DigestPasswordUtil {
+
+    /**
+     * Generated the digest of the sequence <code>username:realm:password</code>.
+     * @param username The username
+     * @param realm The realm
+     * @param password The clear-text password
+     * @return Digest of the parameters
+     */
+    public static String digest(String username, String realm, String password) {
+          return Text.md5(username + ":" + realm + ":" + password);
+    }
+
+    public static void main(String args[]) {
+        if (args.length !=  3) {
+            System.out.println("Usage: " + DigestPasswordUtil.class.getName()
+                    + " <username> <realm> <password>");
+        } else {
+            System.out.println(args[0] + "=" + digest(args[0], args[1], args[2]));
+        }
+    }
+
+}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/DigestLoginModule.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/DigestLoginModule.java	(revision )
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/DigestLoginModule.java	(revision )
@@ -0,0 +1,89 @@
+/*
+ * 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.jackrabbit.core.security.simple;
+
+import org.apache.jackrabbit.commons.DigestCredentials;
+import org.apache.jackrabbit.core.security.authentication.Authentication;
+import org.apache.jackrabbit.core.security.authentication.DigestAuthentication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Map;
+
+/**
+ * Login module implementation to support HTTP Digest authentication
+ */
+public class DigestLoginModule extends SimpleLoginModule {
+
+	private static final Logger log = LoggerFactory
+			.getLogger(DigestLoginModule.class);
+
+    private static final String PASSWORDS_FILE_OPTION = "passwordsFile";
+
+    private String passwordsFile = "";
+
+    @Override
+    protected void doInit(CallbackHandler callbackHandler, Session session, Map options)
+            throws LoginException {
+        super.doInit(callbackHandler, session, options);
+
+        if (options.containsKey(PASSWORDS_FILE_OPTION)) {
+            passwordsFile = (String) options.get(PASSWORDS_FILE_OPTION);
+        } else {
+            throw new LoginException("The mandatory parameter '" + PASSWORDS_FILE_OPTION +
+                    "' is missing.");
+        }
+
+    }
+
+    @Override
+	protected Authentication getAuthentication(Principal principal,
+			Credentials creds) throws RepositoryException {
+		if (principal instanceof Group) {
+			return null;
+		}
+        try {
+            return new DigestAuthentication(new FileInputStream(passwordsFile));
+        } catch (FileNotFoundException e) {
+            throw new RepositoryException("The file '" + passwordsFile + "' could not be found.",e);
+        }
+    }
+
+    @Override
+    protected boolean supportsCredentials(Credentials creds) {
+        return creds instanceof DigestCredentials;
+    }
+
+    @Override
+    protected String getUserID(Credentials credentials) {
+        String userId = ((DigestCredentials) credentials).getUsername();
+        if (userId == null) {
+            return super.getUserID(credentials);
+        }
+        return userId;
+    }
+
+}
Index: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/DigestAuthenticationTest.java
===================================================================
--- jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/DigestAuthenticationTest.java	(revision )
+++ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/DigestAuthenticationTest.java	(revision )
@@ -0,0 +1,65 @@
+/*
+ * 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.jackrabbit.core.security.authentication;
+
+import org.apache.jackrabbit.commons.DigestCredentials;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.util.DigestPasswordUtil;
+import org.apache.jackrabbit.util.Text;
+
+import java.io.InputStream;
+
+public class DigestAuthenticationTest extends AbstractJCRTest {
+
+    private Authentication authentication;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        InputStream is = getClass().getResourceAsStream("/passwords.properties");
+        authentication = new DigestAuthentication(is);
+    }
+
+    public void testAuthenticationFailed() throws Exception {
+        DigestCredentials cred = new DigestCredentials();
+        cred.setUsername("foo");
+        assertFalse(authentication.authenticate(cred));
+        
+    }
+
+    public void testSuccessfulAuthentication() throws Exception {
+        DigestCredentials cred = new DigestCredentials();
+        cred.setUsername("fakeuser");
+        cred.setRealm("jackrabbit");
+
+        cred.setNonce("nonce");
+        cred.setNc("nc");
+        cred.setCnonce("cnonce");
+        cred.setQop("qop");
+        cred.setMd5a2("md5a2");
+
+        String passwordDigest = DigestPasswordUtil.digest("fakeuser", "jackrabbit", "fakepassword");
+
+        String clientDigest = Text.md5(passwordDigest + ":" + cred.getNonce() + ":" + cred.getNc()
+                + ":" + cred.getCnonce() + ":" + cred.getQop() + ":" + cred.getMd5a2());
+
+        cred.setClientDigest(clientDigest);
+
+        assertTrue(authentication.authenticate(cred));
+    }
+
+}
Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/DigestCredentials.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/DigestCredentials.java	(revision )
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/DigestCredentials.java	(revision )
@@ -0,0 +1,83 @@
+/*
+ * 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.jackrabbit.commons;
+
+import javax.jcr.Credentials;
+
+/**
+ * Credentials used for HTTP Digest authentication
+ */
+public class DigestCredentials implements Credentials {
+
+    private String username;
+    private String clientDigest;
+    private String nonce;
+    private String nc;
+    private String cnonce;
+    private String qop;
+    private String realm;
+    private String md5a2;
+    public String getUsername() {
+        return username;
+    }
+    public void setUsername(String username) {
+        this.username = username;
+    }
+    public String getClientDigest() {
+        return clientDigest;
+    }
+    public void setClientDigest(String clientDigest) {
+        this.clientDigest = clientDigest;
+    }
+    public String getNonce() {
+        return nonce;
+    }
+    public void setNonce(String nonce) {
+        this.nonce = nonce;
+    }
+    public String getNc() {
+        return nc;
+    }
+    public void setNc(String nc) {
+        this.nc = nc;
+    }
+    public String getCnonce() {
+        return cnonce;
+    }
+    public void setCnonce(String cnonce) {
+        this.cnonce = cnonce;
+    }
+    public String getQop() {
+        return qop;
+    }
+    public void setQop(String qop) {
+        this.qop = qop;
+    }
+    public String getRealm() {
+        return realm;
+    }
+    public void setRealm(String realm) {
+        this.realm = realm;
+    }
+    public String getMd5a2() {
+        return md5a2;
+    }
+    public void setMd5a2(String md5a2) {
+        this.md5a2 = md5a2;
+    }
+	    
+}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/DigestAuthentication.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/DigestAuthentication.java	(revision )
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/DigestAuthentication.java	(revision )
@@ -0,0 +1,91 @@
+/*
+ * 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.jackrabbit.core.security.authentication;
+
+import org.apache.jackrabbit.commons.DigestCredentials;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * Implementation of HTTP Digest authentication
+ */
+public class DigestAuthentication implements Authentication {
+
+    private static final Logger log = LoggerFactory
+			.getLogger(DigestAuthentication.class);
+
+    private Properties passwords;
+
+    public DigestAuthentication(InputStream is) {
+        passwords = new Properties();
+        try {
+            passwords.load(is);
+        } catch (IOException e) {
+            log.error("The passwords file could not be read.", e);
+        }
+    }
+
+    public boolean canHandle(Credentials credentials) {
+        return (credentials != null && credentials instanceof DigestCredentials);
+    }
+
+    public boolean authenticate(Credentials credentials)
+            throws RepositoryException {
+        DigestCredentials dc = (DigestCredentials) credentials;
+
+        return authenticate(dc.getUsername(), dc.getClientDigest(),
+                dc.getNonce(), dc.getNc(), dc.getCnonce(), dc.getQop(),
+                dc.getRealm(), dc.getMd5a2());
+    }
+
+    public boolean authenticate(String username, String clientDigest,
+            String nOnce, String nc, String cnonce, String qop,
+            String realm, String md5a2) {
+
+        String md5a1 = getDigestedPassword(username);
+
+
+        String serverDigestValue = md5a1 + ":" + nOnce + ":" + nc + ":"
+                + cnonce + ":" + qop + ":" + md5a2;
+
+        String serverDigest = Text.md5(serverDigestValue);
+
+        if (log.isDebugEnabled()) {
+            log.debug("Digest : " + clientDigest + " Username:" + username
+                    + " nOnce:" + nOnce
+                    + " nc:" + nc + " cnonce:" + cnonce + " qop:" + qop
+                    + " realm:" + realm + "md5a2:" + md5a2
+                    + " Server digest:" + serverDigest);
+        }
+
+        return (serverDigest.equals(clientDigest));
+    }
+
+    protected String getDigestedPassword(String user) {
+        return this.passwords.getProperty(user);
+    }
+
+}
Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/DigestCredentialsProvider.java
===================================================================
--- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/DigestCredentialsProvider.java	(revision )
+++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/DigestCredentialsProvider.java	(revision )
@@ -0,0 +1,146 @@
+/*
+ * 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.jackrabbit.server;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.jackrabbit.commons.DigestCredentials;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This Class implements a credentials provider that extracts the credentials
+ * from the 'WWW-Authenticate' header and only supports 'Digest' authentication.
+ */
+public class DigestCredentialsProvider implements CredentialsProvider {
+
+	private static final Logger log = LoggerFactory
+			.getLogger(DigestCredentialsProvider.class);
+
+	public Credentials getCredentials(HttpServletRequest request)
+			throws LoginException, ServletException {
+		String authorization = request.getHeader("authorization");
+		if (authorization == null || authorization.isEmpty()) {
+			// User is not logged in, prompt for credentials
+			throw new LoginException();
+		}
+		if (log.isDebugEnabled()) {
+            log.debug("authorization: " + authorization);
+        }
+		return createDigestCredentials(request, authorization);
+	}
+
+	protected DigestCredentials createDigestCredentials(
+			HttpServletRequest request, String authorization) {
+		if (authorization == null)
+			return (null);
+		if (!authorization.startsWith("Digest "))
+			return (null);
+		authorization = authorization.substring(7).trim();
+
+		String[] tokens = authorization.split(",(?=(?:[^\"]*\"[^\"]*\")+$)");
+
+		String userName = null;
+		String realmName = null;
+		String nOnce = null;
+		String nc = null;
+		String cnonce = null;
+		String qop = null;
+		String uri = null;
+		String response = null;
+		String method = request.getMethod();
+
+		for(String currentToken : tokens) {
+			if (currentToken.length() == 0)
+				continue;
+
+			int equalSign = currentToken.indexOf('=');
+			if (equalSign < 0)
+				return null;
+			String currentTokenName = currentToken.substring(0, equalSign)
+					.trim();
+			String currentTokenValue = currentToken.substring(equalSign + 1)
+					.trim();
+			if ("username".equals(currentTokenName))
+				userName = removeQuotes(currentTokenValue);
+			if ("realm".equals(currentTokenName))
+				realmName = removeQuotes(currentTokenValue, true);
+			if ("nonce".equals(currentTokenName))
+				nOnce = removeQuotes(currentTokenValue);
+			if ("nc".equals(currentTokenName))
+				nc = removeQuotes(currentTokenValue);
+			if ("cnonce".equals(currentTokenName))
+				cnonce = removeQuotes(currentTokenValue);
+			if ("qop".equals(currentTokenName))
+				qop = removeQuotes(currentTokenValue);
+			if ("uri".equals(currentTokenName))
+				uri = removeQuotes(currentTokenValue);
+			if ("response".equals(currentTokenName))
+				response = removeQuotes(currentTokenValue);
+		}
+
+		if ((userName == null) || (realmName == null) || (nOnce == null)
+				|| (uri == null) || (response == null))
+			return null;
+
+		// Second MD5 digest used to calculate the digest :
+		// MD5(Method + ":" + uri)
+		String a2 = method + ":" + uri;
+		String md5a2 = Text.md5(a2);
+
+		DigestCredentials dc = new DigestCredentials();
+		dc.setUsername(userName);
+		dc.setClientDigest(response);
+		dc.setNonce(nOnce);
+		dc.setNc(nc);
+		dc.setCnonce(cnonce);
+		dc.setQop(qop);
+		dc.setRealm(realmName);
+		dc.setMd5a2(md5a2);
+		return dc;
+
+	}
+
+    /**
+     * Removes the quotes on a string. RFC2617 states quotes are optional for
+     * all parameters except realm.
+     */
+    protected static String removeQuotes(String quotedString,
+                                         boolean quotesRequired) {
+        //support both quoted and non-quoted
+        if (quotedString.length() > 0 && quotedString.charAt(0) != '"' &&
+                !quotesRequired) {
+            return quotedString;
+        } else if (quotedString.length() > 2) {
+            return quotedString.substring(1, quotedString.length() - 1);
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * Removes the quotes on a string.
+     */
+    protected static String removeQuotes(String quotedString) {
+        return removeQuotes(quotedString, false);
+    }
+
+}
