Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c	(revision 38029)
+++ channels/chan_sip.c	(working copy)
@@ -5,6 +5,10 @@
  *
  * Mark Spencer <markster@digium.com>
  *
+ * Modified July 21, 2006 Anthony Minessale <anthmct@yahoo.com>
+ * -Add SIP_HEADER_COUNT() dialplan function
+ * -Add optional index arguement to SIP_HEADER() dialplan function
+ *
  * See http://www.asterisk.org for more information about
  * the Asterisk project. Please do not directly contact
  * any of the maintainers of this project for assistance;
@@ -1335,6 +1339,7 @@
 static int sip_do_history(int fd, int argc, char *argv[]);
 static int sip_no_history(int fd, int argc, char *argv[]);
 static int func_header_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
+static int func_header_read_count(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
 static int func_check_sipdomain(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len);
 static int function_sippeer(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len);
 static int function_sipchaninfo_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len);
@@ -1408,8 +1413,9 @@
 static void parse_copy(struct sip_request *dst, const struct sip_request *src);
 static char *get_in_brackets(char *tmp);
 static const char *find_alias(const char *name, const char *_default);
-static const char *__get_header(const struct sip_request *req, const char *name, int *start);
+static const char *__get_header(const struct sip_request *req, const char *name, int *start, int32_t index);
 static const char *get_header(const struct sip_request *req, const char *name);
+static const uint32_t get_header_count(const struct sip_request *req, const char *name);
 static int lws2sws(char *msgbuf, int len);
 static void extract_uri(struct sip_pvt *p, struct sip_request *req);
 static int get_refer_info(struct sip_pvt *transferer, struct sip_request *outgoing_req);
@@ -3809,8 +3815,27 @@
 	return _default;
 }
 
-static const char *__get_header(const struct sip_request *req, const char *name, int *start)
+
+static const uint32_t get_header_count(const struct sip_request *req, const char *name)
 {
+	uint32_t pass, count = 0;
+
+	for (pass = 0; name && pass < 2;pass++) {
+		int x, len = strlen(name);
+		for (x=0; x<req->headers; x++) {
+			if (!strncasecmp(req->header[x], name, len)) {
+				count++;
+			}
+		}
+		if (pass == 0) /* Try aliases */
+			name = find_alias(name, NULL);
+	}
+
+	return count;
+}
+
+static const char *__get_header(const struct sip_request *req, const char *name, int *start, int32_t index)
+{
 	int pass;
 
 	/*
@@ -3831,8 +3856,10 @@
 					r = ast_skip_blanks(r);
 
 				if (*r == ':') {
-					*start = x+1;
-					return ast_skip_blanks(r+1);
+					if (--index <= 0) {
+						*start = x+1;
+						return ast_skip_blanks(r+1);
+					}
 				}
 			}
 		}
@@ -3848,9 +3875,16 @@
 static const char *get_header(const struct sip_request *req, const char *name)
 {
 	int start = 0;
-	return __get_header(req, name, &start);
+	return __get_header(req, name, &start, 0);
 }
 
+/*! \brief Get header from SIP request of a specific index */
+static const char *get_header_index(const struct sip_request *req, const char *name, int32_t index)
+{
+	int start = 0;
+	return __get_header(req, name, &start, index);
+}
+
 /*! \brief Read RTP from network */
 static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p, int *faxdetect)
 {
@@ -5074,7 +5108,7 @@
 	int start = 0;
 	int copied = 0;
 	for (;;) {
-		const char *tmp = __get_header(orig, field, &start);
+		const char *tmp = __get_header(orig, field, &start, 0);
 
 		if (ast_strlen_zero(tmp))
 			break;
@@ -5098,7 +5132,7 @@
 
 	for (;;) {
 		char new[256];
-		const char *oh = __get_header(orig, field, &start);
+		const char *oh = __get_header(orig, field, &start, 0);
 
 		if (ast_strlen_zero(oh))
 			break;
@@ -7567,7 +7601,7 @@
 	/* 1st we pass through all the hops in any Record-Route headers */
 	for (;;) {
 		/* Each Record-Route header */
-		rr = __get_header(req, "Record-Route", &start);
+		rr = __get_header(req, "Record-Route", &start, 0);
 		if (*rr == '\0')
 			break;
 		for (; (rr = strchr(rr, '<')) ; rr += len) { /* Each route entry */
@@ -10877,12 +10911,20 @@
 {
 	struct sip_pvt *p;
 	const char *content;
-	
+	char *header_name, *s;
+	int start = 0;
+	uint32_t index = 0;
+
  	if (!data) {
 		ast_log(LOG_WARNING, "This function requires a header name.\n");
 		return -1;
 	}
 
+	if (!(header_name = ast_strdupa(data))) {
+		ast_log(LOG_WARNING, "Memory Error!\n");
+		return -1;
+	}
+
 	ast_channel_lock(chan);
 	if (chan->tech != &sip_tech) {
 		ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n");
@@ -10897,9 +10939,16 @@
 		ast_channel_unlock(chan);
 		return -1;
 	}
+	
+	if ((s = strchr(header_name, ','))) {
+		*s++ = '\0';
+		index = atoi(s);
+		if (index > 100) { /*c'mon*/
+			index = 0;
+		}
+	}
+	content = __get_header(&p->initreq, header_name, &start, index);
 
-	content = get_header(&p->initreq, data);
-
 	if (ast_strlen_zero(content)) {
 		ast_channel_unlock(chan);
 		return -1;
@@ -10911,13 +10960,56 @@
 	return 0;
 }
 
+
+/*! \brief Read count of SIP header (dialplan function) */
+static int func_header_read_count(struct ast_channel *chan, char *function, char *data, char *buf, size_t len) 
+{
+	struct sip_pvt *p;
+	uint32_t count;
+	
+ 	if (!data) {
+		ast_log(LOG_WARNING, "This function requires a header name.\n");
+		return -1;
+	}
+
+	ast_channel_lock(chan);
+	if (chan->tech != &sip_tech) {
+		ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n");
+		ast_channel_unlock(chan);
+		return -1;
+	}
+
+	p = chan->tech_pvt;
+
+	/* If there is no private structure, this channel is no longer alive */
+	if (!p) {
+		ast_channel_unlock(chan);
+		return -1;
+	}
+
+	count = get_header_count(&p->initreq, data);
+
+	snprintf(buf, len, "%d", count);
+
+	ast_channel_unlock(chan);
+
+	return 0;
+}
+
 static struct ast_custom_function sip_header_function = {
 	.name = "SIP_HEADER",
 	.synopsis = "Gets or sets the specified SIP header",
-	.syntax = "SIP_HEADER(<name>)",
+	.syntax = "SIP_HEADER(<name>[,index])",
 	.read = func_header_read,
 };
 
+static struct ast_custom_function sip_header_count_function = {
+	.name = "SIP_HEADER_COUNT",
+	.synopsis = "Counts the instances of the specified SIP header",
+	.syntax = "SIP_HEADER_COUNT(<name>)",
+	.read = func_header_read_count,
+};
+
 /*! \brief  Dial plan function to check if domain is local */
 static int func_check_sipdomain(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
 {
@@ -11524,7 +11616,7 @@
 			const char *tmptmp = NULL;
 			int start = 0;
 			for(;;) {
-				contact = __get_header(req, "Contact", &start);
+				contact = __get_header(req, "Contact", &start, 0);
 				/* this loop ensures we get a contact header about our register request */
 				if(!ast_strlen_zero(contact)) {
 					if( (tmptmp=strstr(contact, p->our_contact))) {
@@ -16503,6 +16595,7 @@
 
 	/* Register dialplan functions */
 	ast_custom_function_register(&sip_header_function);
+	ast_custom_function_register(&sip_header_count_function);
 	ast_custom_function_register(&sippeer_function);
 	ast_custom_function_register(&sipchaninfo_function);
 	ast_custom_function_register(&checksipdomain_function);
@@ -16532,6 +16625,7 @@
 	ast_custom_function_unregister(&sipchaninfo_function);
 	ast_custom_function_unregister(&sippeer_function);
 	ast_custom_function_unregister(&sip_header_function);
+	ast_custom_function_unregister(&sip_header_count_function);
 	ast_custom_function_unregister(&checksipdomain_function);
 
 	ast_unregister_application(app_dtmfmode);
