Index: main/utils.c
===================================================================
@@ -1555,3 +1555,113 @@
 #endif
 	return 0;
 }
+
+
+/*!
+ *\brief Parse digest authorization header.
+ *\return Returns -1 if we have no auth or something wrong with digest.
+ *\note	This function may be used for Digest request and responce header.
+ * request arg is set to nonzero, if we parse Digest Request.
+ * pedantic arg can be set to nonzero if we need to do addition Digest check.
+ */
+int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic) {
+	int i;
+	char *c, key[512], val[512], tmp[512];
+
+	if(ast_strlen_zero(digest) || d == NULL)
+		return -1;
+
+	ast_copy_string(tmp, digest, sizeof(tmp));
+
+	c = ast_skip_blanks(tmp);
+	
+	if (strncasecmp(tmp, "Digest ", strlen("Digest "))) {
+		ast_log(LOG_WARNING, "Missing Digest.\n");
+		return -1;
+	}
+	c += strlen("Digest ");
+
+	/* clear digest data */
+	memset(d, 0, sizeof(struct ast_http_digest));
+
+	/* lookup for keys/value pair */
+        while (*c && *(c = ast_skip_blanks(c))) {
+
+		/* find key */
+		i = 0;
+		while (*c && *c != '=' && *c != ',' && !isspace(*c) )
+			key[i++] = *c++;
+		key[i] = '\0';
+		c = ast_skip_blanks(c);
+		if (*c == '=') {
+			c = ast_skip_blanks(++c);
+			i = 0;
+			if (*c == '\"') {
+				/* in quotes. Skip first and look for last */
+				c++;
+				while (*c && *c != '\"') {
+					if (*c == '\\' && c[1] != '\0') /* unescape chars */
+						c++;
+					val[i++] = *c++;
+				}
+			} else {
+				/* token */
+				while (*c && *c != ',' && !isspace(*c) )
+					val[i++] = *c++;
+			}
+			val[i] = '\0';
+		}
+
+		while (*c && *c != ',')
+			c++;
+		if (*c)
+			c++;
+
+		if (!strcasecmp(key, "username"))
+			strncpy(d->username, val, sizeof(d->username)-1);
+		else if (!strcasecmp(key, "realm"))
+			strncpy(d->realm, val, sizeof(d->realm)-1);
+		else if (!strcasecmp(key, "nonce"))
+			strncpy(d->nonce, val, sizeof(d->nonce)-1);
+		else if (!strcasecmp(key, "uri"))
+			strncpy(d->uri, val, sizeof(d->uri)-1);
+		else if (!strcasecmp(key, "domain"))
+			strncpy(d->domain, val, sizeof(d->domain)-1);
+		else if (!strcasecmp(key, "response"))
+			strncpy(d->response, val, sizeof(d->response)-1);
+		else if (!strcasecmp(key, "algorithm")) {
+			if (strcasecmp(val, "MD5")) {
+				ast_log(LOG_WARNING, "Digest algorithm: \"%s\" not supported.\n", val);
+				return -1;
+			}
+		} else if (!strcasecmp(key, "cnonce"))
+			strncpy(d->cnonce, val, sizeof(d->cnonce)-1);
+		else if (!strcasecmp(key, "opaque"))
+			strncpy(d->opaque, val, sizeof(d->opaque)-1);
+		else if (!strcasecmp(key, "qop") && !strcasecmp(val, "auth"))
+			d->qop = 1;
+		else if (!strcasecmp(key, "nc")) {
+			unsigned long u;
+			if (sscanf(val, "%lx", &u) != 1) {
+				ast_log(LOG_WARNING, "Incorrect Digest nc value: \"%s\".\n", val);
+				return -1;
+			}
+			strncpy(d->nc, val, sizeof(d->nc)-1);
+		}
+	}
+	/* Digest checkout */
+	if (!*d->realm || !*d->nonce)
+		return -1; /* "realm" and "nonce" MUST be always exist */
+
+	if (!request) {
+		/* Additional check for Digest response */
+		if (!*d->username || !*d->uri || !*d->response)
+			return -1;
+		
+		if(pedantic && d->qop && (!*d->cnonce || !*d->nc))
+			return -1;
+	}
+	
+	return 0;
+}
+
Index: include/asterisk/utils.h
===================================================================
--- include/asterisk/utils.h	(revision 94168)
+++ include/asterisk/utils.h	(working copy)
@@ -652,6 +652,33 @@
 
 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
 
+
+
+/* Definition for Digest authorization */
+struct ast_http_digest {
+	char username[80];
+	char nonce[32];
+	char uri[256];
+	char realm[256];
+	char domain[256];
+	char response[256];
+	int qop;		/* Flag set to 1, if we send/recv qop="quth" */
+	char cnonce[256];
+	char opaque[32];
+	char nc[32];
+};
+
+/*!
+ *\brief Parse digest authorization header.
+ *\return Returns -1 if we have no auth or something wrong with digest.
+ *\note This function may be used for Digest request and responce header.
+ * request arg is set to nonzero, if we parse Digest Request.
+ * pedantic arg can be set to nonzero if we need to do addition Digest check.
+ */
+int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic);
+
+
+
 #include "asterisk/strings.h"
 
 #endif /* _ASTERISK_UTILS_H */
