[svn-commits] rmudgett: trunk r430435 - in /trunk: ./ apps/ channels/ include/asterisk/ mai...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jan 9 12:17:01 CST 2015


Author: rmudgett
Date: Fri Jan  9 12:16:54 2015
New Revision: 430435

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=430435
Log:
AMI: Make AMI actions that generate event lists consistent.

* Made the following AMI actions use list API calls for consistency:
Agents
BridgeInfo
BridgeList
BridgeTechnologyList
ConfbridgeLIst
ConfbridgeLIstRooms
CoreShowChannels
DAHDIShowChannels
DBGet
DeviceStateList
ExtensionStateList
FAXSessions
Hangup
IAXpeerlist
IAXpeers
IAXregistry
MeetmeList
MeetmeListRooms
MWIGet
ParkedCalls
Parkinglots
PJSIPShowEndpoint
PJSIPShowEndpoints
PJSIPShowRegistrationsInbound
PJSIPShowRegistrationsOutbound
PJSIPShowResourceLists
PJSIPShowSubscriptionsInbound
PJSIPShowSubscriptionsOutbound
PresenceStateList
PRIShowSpans
QueueStatus
QueueSummary
ShowDialPlan
SIPpeers
SIPpeerstatus
SIPshowregistry
SKINNYdevices
SKINNYlines
Status
VoicemailUsersList

* Incremented the AMI version to 2.7.0.

* Changed astman_send_listack() to not use the listflag parameter and
always set the value to "Start" so the start capitalization is consistent.
i.e., The FAXSessions used "Start" while the rest of the system used
"start".  The corresponding complete event always used "Complete".

* Fixed ami_show_resource_lists() "PJSIPShowResourceLists" to output the
AMI ActionID for all of its list events.

* Fixed off-nominal AMI protocol error in manager_bridge_info(),
manager_parking_status_single_lot(), and
manager_parking_status_all_lots().  Use of astman_send_error() after
responding to the original AMI action request violates the action response
pattern by sending two responses.

* Fixed minor protocol error in action_getconfig() when no requested
categories are found.  Each line needs to be formatted as "Header: text".

* Fixed off-nominal memory leak in manager_build_parked_call_string().

* Eliminated unnecessary use of RAII_VAR() in ami_subscription_detail().

ASTERISK-24049 #close
Reported by: Jonathan Rose

Review: https://reviewboard.asterisk.org/r/4315/
........

Merged revisions 430434 from http://svn.asterisk.org/svn/asterisk/branches/13

Modified:
    trunk/   (props changed)
    trunk/CHANGES
    trunk/apps/app_agent_pool.c
    trunk/apps/app_confbridge.c
    trunk/apps/app_meetme.c
    trunk/apps/app_queue.c
    trunk/apps/app_voicemail.c
    trunk/channels/chan_dahdi.c
    trunk/channels/chan_iax2.c
    trunk/channels/chan_sip.c
    trunk/channels/chan_skinny.c
    trunk/include/asterisk/manager.h
    trunk/main/bridge.c
    trunk/main/db.c
    trunk/main/manager.c
    trunk/main/manager_bridges.c
    trunk/main/pbx.c
    trunk/res/parking/parking_manager.c
    trunk/res/res_fax.c
    trunk/res/res_manager_devicestate.c
    trunk/res/res_manager_presencestate.c
    trunk/res/res_mwi_external_ami.c
    trunk/res/res_pjsip/pjsip_configuration.c
    trunk/res/res_pjsip_outbound_registration.c
    trunk/res/res_pjsip_pubsub.c
    trunk/res/res_pjsip_registrar.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-13-merged' - no diff available.

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Fri Jan  9 12:16:54 2015
@@ -98,7 +98,6 @@
 --- Functionality changes from Asterisk 13.1.0 to Asterisk 13.2.0 ------------
 ------------------------------------------------------------------------------
 
-=======
  * New 'PJSIP_AOR' and 'PJSIP_CONTACT' dialplan functions have been added which
    allow examining PJSIP AORs or contacts from the dialplan.
 
@@ -144,6 +143,10 @@
 ------------------
  * "Language" (the default spoken language for the channel) is now included in
    the standard channel state output for suitable events.
+
+ * AMI actions that return a list of events have been made to return consistent
+   headers for the action response event starting the list and the list complete
+   event.  The AMI version has been bumped to 2.7.0 as a result.
 
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.0.0 to Asterisk 13.1.0 ------------

Modified: trunk/apps/app_agent_pool.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_agent_pool.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/apps/app_agent_pool.c (original)
+++ trunk/apps/app_agent_pool.c Fri Jan  9 12:16:54 2015
@@ -2525,13 +2525,14 @@
 	struct ao2_iterator iter;
 	struct agent_pvt *agent;
 	struct ast_str *out = ast_str_alloca(4096);
+	int num_agents = 0;
 
 	if (!ast_strlen_zero(id)) {
 		snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
 	} else {
 		id_text[0] = '\0';
 	}
-	astman_send_ack(s, m, "Agents will follow");
+	astman_send_listack(s, m, "Agents will follow", "start");
 
 	iter = ao2_iterator_init(agents, 0);
 	for (; (agent = ao2_iterator_next(&iter)); ao2_ref(agent, -1)) {
@@ -2586,12 +2587,12 @@
 		astman_append(s, "Event: Agents\r\n"
 			"%s%s\r\n",
 			ast_str_buffer(out), id_text);
+		++num_agents;
 	}
 	ao2_iterator_destroy(&iter);
 
-	astman_append(s, "Event: AgentsComplete\r\n"
-		"%s"
-		"\r\n", id_text);
+	astman_send_list_complete_start(s, m, "AgentsComplete", num_agents);
+	astman_send_list_complete_end(s);
 	return 0;
 }
 

Modified: trunk/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_confbridge.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/apps/app_confbridge.c (original)
+++ trunk/apps/app_confbridge.c Fri Jan  9 12:16:54 2015
@@ -2897,12 +2897,8 @@
 	ao2_unlock(conference);
 	ao2_ref(conference, -1);
 
-	astman_append(s,
-	"Event: ConfbridgeListComplete\r\n"
-	"EventList: Complete\r\n"
-	"ListItems: %d\r\n"
-	"%s"
-	"\r\n", total, id_text);
+	astman_send_list_complete_start(s, m, "ConfbridgeListComplete", total);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }
@@ -2952,12 +2948,8 @@
 	ao2_iterator_destroy(&iter);
 
 	/* Send final confirmation */
-	astman_append(s,
-	"Event: ConfbridgeListRoomsComplete\r\n"
-	"EventList: Complete\r\n"
-	"ListItems: %d\r\n"
-	"%s"
-	"\r\n", totalitems, id_text);
+	astman_send_list_complete_start(s, m, "ConfbridgeListRoomsComplete", totalitems);
+	astman_send_list_complete_end(s);
 	return 0;
 }
 

Modified: trunk/apps/app_meetme.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_meetme.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/apps/app_meetme.c (original)
+++ trunk/apps/app_meetme.c Fri Jan  9 12:16:54 2015
@@ -5577,13 +5577,10 @@
 		ao2_iterator_destroy(&user_iter);
 	}
 	AST_LIST_UNLOCK(&confs);
+
 	/* Send final confirmation */
-	astman_append(s,
-	"Event: MeetmeListComplete\r\n"
-	"EventList: Complete\r\n"
-	"ListItems: %d\r\n"
-	"%s"
-	"\r\n", total, idText);
+	astman_send_list_complete_start(s, m, "MeetmeListComplete", total);
+	astman_send_list_complete_end(s);
 	return 0;
 }
 
@@ -5645,12 +5642,8 @@
 	AST_LIST_UNLOCK(&confs);
 
 	/* Send final confirmation */
-	astman_append(s,
-	"Event: MeetmeListRoomsComplete\r\n"
-	"EventList: Complete\r\n"
-	"ListItems: %d\r\n"
-	"%s"
-	"\r\n", totalitems, idText);
+	astman_send_list_complete_start(s, m, "MeetmeListRoomsComplete", totalitems);
+	astman_send_list_complete_end(s);
 	return 0;
 }
 

Modified: trunk/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_queue.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/apps/app_queue.c (original)
+++ trunk/apps/app_queue.c Fri Jan  9 12:16:54 2015
@@ -9462,19 +9462,21 @@
 	int qmemavail = 0;
 	int qchancount = 0;
 	int qlongestholdtime = 0;
+	int qsummaries = 0;
 	const char *id = astman_get_header(m, "ActionID");
 	const char *queuefilter = astman_get_header(m, "Queue");
-	char idText[256] = "";
+	char idText[256];
 	struct call_queue *q;
 	struct queue_ent *qe;
 	struct member *mem;
 	struct ao2_iterator queue_iter;
 	struct ao2_iterator mem_iter;
 
-	astman_send_ack(s, m, "Queue summary will follow");
+	astman_send_listack(s, m, "Queue summary will follow", "start");
 	time(&now);
+	idText[0] = '\0';
 	if (!ast_strlen_zero(id)) {
-		snprintf(idText, 256, "ActionID: %s\r\n", id);
+		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
 	}
 	queue_iter = ao2_iterator_init(queues, 0);
 	while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
@@ -9517,15 +9519,15 @@
 				"%s"
 				"\r\n",
 				q->name, qmemcount, qmemavail, qchancount, q->holdtime, q->talktime, qlongestholdtime, idText);
+			++qsummaries;
 		}
 		ao2_unlock(q);
 		queue_t_unref(q, "Done with iterator");
 	}
 	ao2_iterator_destroy(&queue_iter);
-	astman_append(s,
-		"Event: QueueSummaryComplete\r\n"
-		"%s"
-		"\r\n", idText);
+
+	astman_send_list_complete_start(s, m, "QueueSummaryComplete", qsummaries);
+	astman_send_list_complete_end(s);
 
 	return RESULT_SUCCESS;
 }
@@ -9535,10 +9537,11 @@
 {
 	time_t now;
 	int pos;
+	int q_items = 0;
 	const char *id = astman_get_header(m,"ActionID");
 	const char *queuefilter = astman_get_header(m,"Queue");
 	const char *memberfilter = astman_get_header(m,"Member");
-	char idText[256] = "";
+	char idText[256];
 	struct call_queue *q;
 	struct queue_ent *qe;
 	float sl = 0;
@@ -9546,8 +9549,9 @@
 	struct ao2_iterator queue_iter;
 	struct ao2_iterator mem_iter;
 
-	astman_send_ack(s, m, "Queue status will follow");
+	astman_send_listack(s, m, "Queue status will follow", "start");
 	time(&now);
+	idText[0] = '\0';
 	if (!ast_strlen_zero(id)) {
 		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
 	}
@@ -9575,6 +9579,8 @@
 				"\r\n",
 				q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted,
 				q->callsabandoned, q->servicelevel, sl, q->weight, idText);
+			++q_items;
+
 			/* List Queue Members */
 			mem_iter = ao2_iterator_init(q->members, 0);
 			while ((mem = ao2_iterator_next(&mem_iter))) {
@@ -9594,10 +9600,12 @@
 						"\r\n",
 						q->name, mem->membername, mem->interface, mem->state_interface, mem->dynamic ? "dynamic" : "static",
 						mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
+					++q_items;
 				}
 				ao2_ref(mem, -1);
 			}
 			ao2_iterator_destroy(&mem_iter);
+
 			/* List Queue Entries */
 			pos = 1;
 			for (qe = q->head; qe; qe = qe->next) {
@@ -9619,6 +9627,7 @@
 					S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),
 					S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
 					(long) (now - qe->start), idText);
+				++q_items;
 			}
 		}
 		ao2_unlock(q);
@@ -9626,10 +9635,8 @@
 	}
 	ao2_iterator_destroy(&queue_iter);
 
-	astman_append(s,
-		"Event: QueueStatusComplete\r\n"
-		"%s"
-		"\r\n",idText);
+	astman_send_list_complete_start(s, m, "QueueStatusComplete", q_items);
+	astman_send_list_complete_end(s);
 
 	return RESULT_SUCCESS;
 }

Modified: trunk/apps/app_voicemail.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_voicemail.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/apps/app_voicemail.c (original)
+++ trunk/apps/app_voicemail.c Fri Jan  9 12:16:54 2015
@@ -13049,10 +13049,13 @@
 {
 	struct ast_vm_user *vmu = NULL;
 	const char *id = astman_get_header(m, "ActionID");
-	char actionid[128] = "";
-
-	if (!ast_strlen_zero(id))
+	char actionid[128];
+	int num_users = 0;
+
+	actionid[0] = '\0';
+	if (!ast_strlen_zero(id)) {
 		snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
+	}
 
 	AST_LIST_LOCK(&users);
 
@@ -13062,20 +13065,20 @@
 		return RESULT_SUCCESS;
 	}
 	
-	astman_send_ack(s, m, "Voicemail user list will follow");
+	astman_send_listack(s, m, "Voicemail user list will follow", "start");
 	
 	AST_LIST_TRAVERSE(&users, vmu, list) {
 		char dirname[256];
-
 #ifdef IMAP_STORAGE
 		int new, old;
+
 		inboxcount(vmu->mailbox, &new, &old);
 #endif
 		
 		make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
 		astman_append(s,
+			"Event: VoicemailUserEntry\r\n"
 			"%s"
-			"Event: VoicemailUserEntry\r\n"
 			"VMContext: %s\r\n"
 			"VoiceMailbox: %s\r\n"
 			"Fullname: %s\r\n"
@@ -13144,8 +13147,11 @@
 			count_messages(vmu, dirname)
 #endif
 			);
+		++num_users;
 	}		
-	astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
+
+	astman_send_list_complete_start(s, m, "VoicemailUserEntryComplete", num_users);
+	astman_send_list_complete_end(s);
 
 	AST_LIST_UNLOCK(&users);
 

Modified: trunk/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_dahdi.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/channels/chan_dahdi.c (original)
+++ trunk/channels/chan_dahdi.c Fri Jan  9 12:16:54 2015
@@ -16068,7 +16068,7 @@
 	struct dahdi_pvt *tmp = NULL;
 	const char *id = astman_get_header(m, "ActionID");
 	const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
-	char idText[256] = "";
+	char idText[256];
 	int channels = 0;
 	int dahdichanquery;
 
@@ -16077,9 +16077,12 @@
 		dahdichanquery = -1;
 	}
 
-	astman_send_ack(s, m, "DAHDI channel status will follow");
-	if (!ast_strlen_zero(id))
+	idText[0] = '\0';
+	if (!ast_strlen_zero(id)) {
 		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
+	}
+
+	astman_send_listack(s, m, "DAHDI channel status will follow", "start");
 
 	ast_mutex_lock(&iflock);
 
@@ -16142,13 +16145,9 @@
 
 	ast_mutex_unlock(&iflock);
 
-	astman_append(s,
-		"Event: DAHDIShowChannelsComplete\r\n"
-		"%s"
-		"Items: %d\r\n"
-		"\r\n",
-		idText,
-		channels);
+	astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
+	astman_append(s, "Items: %d\r\n", channels);
+	astman_send_list_complete_end(s);
 	return 0;
 }
 
@@ -16177,7 +16176,7 @@
 		action_id[0] = '\0';
 	}
 
-	astman_send_ack(s, m, "Span status will follow");
+	astman_send_listack(s, m, "Span status will follow", "start");
 
 	count = 0;
 	for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
@@ -16194,14 +16193,9 @@
 		}
 	}
 
-	astman_append(s,
-		"Event: %sComplete\r\n"
-		"Items: %d\r\n"
-		"%s"
-		"\r\n",
-		show_cmd,
-		count,
-		action_id);
+	astman_send_list_complete_start(s, m, "PRIShowSpansComplete", count);
+	astman_append(s, "Items: %d\r\n", count);
+	astman_send_list_complete_end(s);
 	return 0;
 }
 #endif	/* defined(HAVE_PRI) */

Modified: trunk/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_iax2.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/channels/chan_iax2.c (original)
+++ trunk/channels/chan_iax2.c Fri Jan  9 12:16:54 2015
@@ -6872,31 +6872,23 @@
 	}
 
 	if (s) {
-
 		if (cont->peerlist) { /* IAXpeerlist */
-
 			astman_append(s,
 				"Event: PeerEntry\r\n%s"
 				"Channeltype: IAX\r\n",
 				cont->idtext);
-
 			if (!ast_strlen_zero(peer->username)) {
-
 				astman_append(s,
 					"ObjectName: %s\r\n"
 					"ObjectUsername: %s\r\n",
 					peer->name,
 					peer->username);
-
 			} else {
-
 				astman_append(s,
 					"ObjectName: %s\r\n",
 					name);
 			}
-
 		} else { /* IAXpeers */
-
 			astman_append(s,
 				"Event: PeerEntry\r\n%s"
 				"Channeltype: IAX2\r\n"
@@ -6904,28 +6896,21 @@
 				cont->idtext,
 				name);
 		}
-
 		astman_append(s,
 			"ChanObjectType: peer\r\n"
 			"IPaddress: %s\r\n",
 			tmp_host);
-
 		if (cont->peerlist) { /* IAXpeerlist */
-
 			astman_append(s,
 				"Mask: %s\r\n"
 				"Port: %s\r\n",
 				tmp_mask,
 				tmp_port);
-
 		} else { /* IAXpeers */
-
 			astman_append(s,
 				"IPport: %s\r\n",
 				tmp_port);
-
-		}
-
+		}
 		astman_append(s,
 			"Dynamic: %s\r\n"
 			"Trunk: %s\r\n"
@@ -6935,19 +6920,13 @@
 			ast_test_flag64(peer, IAX_TRUNK) ? "yes" : "no",
 			peer->encmethods ? ast_str_buffer(encmethods) : "no",
 			status);
-
 		if (cont->peerlist) { /* IAXpeerlist */
-
 			astman_append(s, "\r\n");
-
 		} else { /* IAXpeers */
-
 			astman_append(s,
 				"Description: %s\r\n\r\n",
 				peer->description);
-
-		}
-
+		}
 	} else {
 		ast_cli(fd, PEERS_FORMAT,
 			name,
@@ -6962,7 +6941,6 @@
 	}
 
 	cont->total_peers++;
-
 }
 
 static int __iax2_show_peers(int fd, int *total, struct mansession *s, const int argc, const char * const argv[])
@@ -7275,16 +7253,14 @@
 		snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
 
 	astman_send_listack(s, m, "Peer status list will follow", "start");
-        /* List the peers in separate manager events */
+
+	/* List the peers in separate manager events */
 	__iax2_show_peers(-1, &total, s, 3, a);
-        /* Send final confirmation */
-        astman_append(s,
-        "Event: PeerlistComplete\r\n"
-        "EventList: Complete\r\n"
-        "ListItems: %d\r\n"
-        "%s"
-        "\r\n", total, idtext);
-        return 0;
+
+	/* Send final confirmation */
+	astman_send_list_complete_start(s, m, "PeerlistComplete", total);
+	astman_send_list_complete_end(s);
+	return 0;
 }
 
 /*! \brief callback to display iax peers in manager format */
@@ -7312,25 +7288,16 @@
 		snprintf(cont.idtext, sizeof(cont.idtext), "ActionID: %s\r\n", id);
 	}
 
-	astman_append(s,
-		"Response: Success\r\n"
-		"%sMessage: IAX Peer status list will follow\r\n\r\n",
-		cont.idtext);
-
+	astman_send_listack(s, m, "IAX Peer status list will follow", "start");
 
 	i = ao2_iterator_init(peers, 0);
 	for (; (peer = ao2_iterator_next(&i)); peer_unref(peer)) {
-
 		_iax2_show_peers_one(-1, s, &cont, peer);
-
 	}
 	ao2_iterator_destroy(&i);
 
-	astman_append(s,
-		"Event: PeerlistComplete\r\n"
-		"%sListItems: %d\r\n\r\n",
-		cont.idtext,
-		cont.total_peers);
+	astman_send_list_complete_start(s, m, "PeerlistComplete", cont.total_peers);
+	astman_send_list_complete_end(s);
 
 	return RESULT_SUCCESS;
 }
@@ -7435,12 +7402,8 @@
 	}
 	AST_LIST_UNLOCK(&registrations);
 
-	astman_append(s,
-		"Event: RegistrationsComplete\r\n"
-		"EventList: Complete\r\n"
-		"ListItems: %d\r\n"
-		"%s"
-		"\r\n", total, idtext);
+	astman_send_list_complete_start(s, m, "RegistrationsComplete", total);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Fri Jan  9 12:16:54 2015
@@ -19257,12 +19257,8 @@
 	}
 	ao2_iterator_destroy(&iter);
 
-	astman_append(s,
-		"Event: RegistrationsComplete\r\n"
-		"EventList: Complete\r\n"
-		"ListItems: %d\r\n"
-		"%s"
-		"\r\n", total, idtext);
+	astman_send_list_complete_start(s, m, "RegistrationsComplete", total);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }
@@ -19280,15 +19276,13 @@
 		snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
 
 	astman_send_listack(s, m, "Peer status list will follow", "start");
+
 	/* List the peers in separate manager events */
 	_sip_show_peers(-1, &total, s, m, 3, a);
+
 	/* Send final confirmation */
-	astman_append(s,
-	"Event: PeerlistComplete\r\n"
-	"EventList: Complete\r\n"
-	"ListItems: %d\r\n"
-	"%s"
-	"\r\n", total, idtext);
+	astman_send_list_complete_start(s, m, "PeerlistComplete", total);
+	astman_send_list_complete_end(s);
 	return 0;
 }
 
@@ -20051,9 +20045,11 @@
 {
 	const char *id = astman_get_header(m,"ActionID");
 	const char *peer_name = astman_get_header(m,"Peer");
-	char idText[256] = "";
+	char idText[256];
 	struct sip_peer *peer = NULL;
-
+	int num_peers = 0;
+
+	idText[0] = '\0';
 	if (!ast_strlen_zero(id)) {
 		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
 	}
@@ -20071,15 +20067,17 @@
 		}
 	}
 
-	astman_send_ack(s, m, "Peer status will follow");
+	astman_send_listack(s, m, "Peer status will follow", "start");
 
 	if (!peer) {
 		struct ao2_iterator i = ao2_iterator_init(peers, 0);
+
 		while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table for SIPpeerstatus"))) {
 			ao2_lock(peer);
 			send_manager_peer_status(s, peer, idText);
 			ao2_unlock(peer);
 			sip_unref_peer(peer, "unref peer for SIPpeerstatus");
+			++num_peers;
 		}
 		ao2_iterator_destroy(&i);
 	} else {
@@ -20087,14 +20085,11 @@
 		send_manager_peer_status(s, peer, idText);
 		ao2_unlock(peer);
 		sip_unref_peer(peer, "unref peer for SIPpeerstatus");
-	}
-
-
-	astman_append(s,
-	"Event: SIPpeerstatusComplete\r\n"
-	"%s"
-	"\r\n",
-	idText);
+		++num_peers;
+	}
+
+	astman_send_list_complete_start(s, m, "SIPpeerstatusComplete", num_peers);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }

Modified: trunk/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_skinny.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/channels/chan_skinny.c (original)
+++ trunk/channels/chan_skinny.c Fri Jan  9 12:16:54 2015
@@ -4135,24 +4135,17 @@
 /*    Inspired from chan_sip */
 static int manager_skinny_show_devices(struct mansession *s, const struct message *m)
 {
-	const char *id = astman_get_header(m, "ActionID");
 	const char *a[] = {"skinny", "show", "devices"};
-	char idtext[256] = "";
 	int total = 0;
 
-	if (!ast_strlen_zero(id))
-		snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
-
 	astman_send_listack(s, m, "Device status list will follow", "start");
+
 	/* List the devices in separate manager events */
 	_skinny_show_devices(-1, &total, s, m, 3, a);
+
 	/* Send final confirmation */
-	astman_append(s,
-	"Event: DevicelistComplete\r\n"
-	"EventList: Complete\r\n"
-	"ListItems: %d\r\n"
-	"%s"
-	"\r\n", total, idtext);
+	astman_send_list_complete_start(s, m, "DevicelistComplete", total);
+	astman_send_list_complete_end(s);
 	return 0;
 }
 
@@ -4384,24 +4377,17 @@
 /*    Inspired from chan_sip */
 static int manager_skinny_show_lines(struct mansession *s, const struct message *m)
 {
-	const char *id = astman_get_header(m, "ActionID");
 	const char *a[] = {"skinny", "show", "lines"};
-	char idtext[256] = "";
 	int total = 0;
 
-	if (!ast_strlen_zero(id))
-		snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
-
 	astman_send_listack(s, m, "Line status list will follow", "start");
+
 	/* List the lines in separate manager events */
 	_skinny_show_lines(-1, &total, s, m, 3, a);
+
 	/* Send final confirmation */
-	astman_append(s,
-	"Event: LinelistComplete\r\n"
-	"EventList: Complete\r\n"
-	"ListItems: %d\r\n"
-	"%s"
-	"\r\n", total, idtext);
+	astman_send_list_complete_start(s, m, "LinelistComplete", total);
+	astman_send_list_complete_end(s);
 	return 0;
 }
 

Modified: trunk/include/asterisk/manager.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/manager.h?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/include/asterisk/manager.h (original)
+++ trunk/include/asterisk/manager.h Fri Jan  9 12:16:54 2015
@@ -54,7 +54,7 @@
 - \ref manager.c Main manager code file
  */
 
-#define AMI_VERSION                     "2.6.0"
+#define AMI_VERSION                     "2.7.0"
 #define DEFAULT_MANAGER_PORT 5038	/* Default port for Asterisk management via TCP */
 #define DEFAULT_MANAGER_TLS_PORT 5039	/* Default port for Asterisk management via TCP */
 
@@ -299,8 +299,57 @@
 /*! \brief Send ack in manager transaction */
 void astman_send_ack(struct mansession *s, const struct message *m, char *msg);
 
-/*! \brief Send ack in manager list transaction */
+/*!
+ * \brief Send ack in manager transaction to begin a list.
+ *
+ * \param s - AMI session control struct.
+ * \param m - AMI action request that started the list.
+ * \param msg - Message contents describing the list to follow.
+ * \param listflag - Not used.  Historically always set to "start".
+ *
+ * \note You need to call astman_send_list_complete_start() and
+ * astman_send_list_complete_end() to send the AMI list completion event.
+ *
+ * \return Nothing
+ */
 void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag);
+
+/*!
+ * \brief Start the list complete event.
+ * \since 13.2.0
+ *
+ * \param s - AMI session control struct.
+ * \param m - AMI action request that started the list.
+ * \param event_name - AMI list complete event name.
+ * \param count - Number of items in the list.
+ *
+ * \note You need to call astman_send_list_complete_end() to end
+ * the AMI list completion event.
+ *
+ * \note Between calling astman_send_list_complete_start() and
+ * astman_send_list_complete_end() you can add additonal headers
+ * using astman_append().
+ *
+ * \return Nothing
+ */
+void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count);
+
+/*!
+ * \brief End the list complete event.
+ * \since 13.2.0
+ *
+ * \param s - AMI session control struct.
+ *
+ * \note You need to call astman_send_list_complete_start() to start
+ * the AMI list completion event.
+ *
+ * \note Between calling astman_send_list_complete_start() and
+ * astman_send_list_complete_end() you can add additonal headers
+ * using astman_append().
+ *
+ * \return Nothing
+ */
+void astman_send_list_complete_end(struct mansession *s);
 
 void __attribute__((format(printf, 2, 3))) astman_append(struct mansession *s, const char *fmt, ...);
 

Modified: trunk/main/bridge.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridge.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/main/bridge.c (original)
+++ trunk/main/bridge.c Fri Jan  9 12:16:54 2015
@@ -5198,6 +5198,7 @@
 	const char *id = astman_get_header(m, "ActionID");
 	RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free);
 	struct ast_bridge_technology *cur;
+	int num_items = 0;
 
 	if (!id_text) {
 		astman_send_error(s, m, "Internal error");
@@ -5208,7 +5209,7 @@
 		ast_str_set(&id_text, 0, "ActionID: %s\r\n", id);
 	}
 
-	astman_send_ack(s, m, "Bridge technology listing will follow");
+	astman_send_listack(s, m, "Bridge technology listing will follow", "start");
 
 	AST_RWLIST_RDLOCK(&bridge_technologies);
 	AST_RWLIST_TRAVERSE(&bridge_technologies, cur, entry) {
@@ -5226,14 +5227,12 @@
 			"\r\n",
 			cur->name, type, cur->preference, AST_YESNO(cur->suspended),
 			ast_str_buffer(id_text));
+		++num_items;
 	}
 	AST_RWLIST_UNLOCK(&bridge_technologies);
 
-	astman_append(s,
-		"Event: BridgeTechnologyListComplete\r\n"
-		"%s"
-		"\r\n",
-		ast_str_buffer(id_text));
+	astman_send_list_complete_start(s, m, "BridgeTechnologyListComplete", num_items);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }

Modified: trunk/main/db.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/db.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/main/db.c (original)
+++ trunk/main/db.c Fri Jan  9 12:16:54 2015
@@ -841,7 +841,7 @@
 static int manager_dbget(struct mansession *s, const struct message *m)
 {
 	const char *id = astman_get_header(m,"ActionID");
-	char idText[256] = "";
+	char idText[256];
 	const char *family = astman_get_header(m, "Family");
 	const char *key = astman_get_header(m, "Key");
 	char tmp[MAX_DB_FIELD];
@@ -856,6 +856,7 @@
 		return 0;
 	}
 
+	idText[0] = '\0';
 	if (!ast_strlen_zero(id))
 		snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
 
@@ -863,7 +864,8 @@
 	if (res) {
 		astman_send_error(s, m, "Database entry not found");
 	} else {
-		astman_send_ack(s, m, "Result will follow");
+		astman_send_listack(s, m, "Result will follow", "start");
+
 		astman_append(s, "Event: DBGetResponse\r\n"
 				"Family: %s\r\n"
 				"Key: %s\r\n"
@@ -871,10 +873,9 @@
 				"%s"
 				"\r\n",
 				family, key, tmp, idText);
-		astman_append(s, "Event: DBGetComplete\r\n"
-				"%s"
-				"\r\n",
-				idText);
+
+		astman_send_list_complete_start(s, m, "DBGetComplete", 1);
+		astman_send_list_complete_end(s);
 	}
 	return 0;
 }

Modified: trunk/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/manager.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/main/manager.c (original)
+++ trunk/main/manager.c Fri Jan  9 12:16:54 2015
@@ -2921,7 +2921,26 @@
 
 void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
 {
-	astman_send_response_full(s, m, "Success", msg, listflag);
+	astman_send_response_full(s, m, "Success", msg, "Start");
+}
+
+void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
+{
+	const char *id = astman_get_header(m, "ActionID");
+
+	astman_append(s, "Event: %s\r\n", event_name);
+	if (!ast_strlen_zero(id)) {
+		astman_append(s, "ActionID: %s\r\n", id);
+	}
+	astman_append(s,
+		"EventList: Complete\r\n"
+		"ListItems: %d\r\n",
+		count);
+}
+
+void astman_send_list_complete_end(struct mansession *s)
+{
+	astman_append(s, "\r\n");
 }
 
 /*! \brief Lock the 'mansession' structure. */
@@ -3347,7 +3366,7 @@
 	}
 
 	if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
-		astman_append(s, "No categories found\r\n");
+		astman_append(s, "Error: No categories found\r\n");
 	}
 
 	ast_config_destroy(cfg);
@@ -3385,7 +3404,7 @@
 	}
 
 	if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
-		astman_append(s, "Error: no categories found\r\n");
+		astman_append(s, "Error: No categories found\r\n");
 	}
 
 	ast_config_destroy(cfg);
@@ -4214,12 +4233,8 @@
 	regfree(&regexbuf);
 	ast_free(regex_string);
 
-	astman_append(s,
-		"Event: ChannelsHungupListComplete\r\n"
-		"EventList: Complete\r\n"
-		"ListItems: %d\r\n"
-		"%s"
-		"\r\n", channels_matched, idText);
+	astman_send_list_complete_start(s, m, "ChannelsHungupListComplete", channels_matched);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }
@@ -4309,7 +4324,7 @@
 	return 0;
 }
 
-static void generate_status(struct mansession *s, struct ast_channel *chan, char **vars, int varc, int all_variables, char *id_text)
+static void generate_status(struct mansession *s, struct ast_channel *chan, char **vars, int varc, int all_variables, char *id_text, int *count)
 {
 	struct timeval now;
 	long elapsed_seconds;
@@ -4339,7 +4354,6 @@
 	} else {
 		variable_str = ast_str_create(1024);
 	}
-
 	if (!variable_str) {
 		return;
 	}
@@ -4421,6 +4435,7 @@
 		(long)elapsed_seconds,
 		ast_str_buffer(variable_str),
 		id_text);
+	++*count;
 
 	ao2_cleanup(bridge);
 }
@@ -4466,7 +4481,7 @@
 		}
 	}
 
-	astman_send_ack(s, m, "Channel status will follow");
+	astman_send_listack(s, m, "Channel status will follow", "start");
 
 	if (!ast_strlen_zero(id)) {
 		snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
@@ -4482,8 +4497,7 @@
 	for (; chan; all ? chan = ast_channel_iterator_next(it_chans) : 0) {
 		ast_channel_lock(chan);
 
-		generate_status(s, chan, vars.name, vars.argc, all_variables, id_text);
-		channels++;
+		generate_status(s, chan, vars.name, vars.argc, all_variables, id_text, &channels);
 
 		ast_channel_unlock(chan);
 		chan = ast_channel_unref(chan);
@@ -4493,11 +4507,9 @@
 		ast_channel_iterator_destroy(it_chans);
 	}
 
-	astman_append(s,
-		"Event: StatusComplete\r\n"
-		"%s"
-		"Items: %d\r\n"
-		"\r\n", id_text, channels);
+	astman_send_list_complete_start(s, m, "StatusComplete", channels);
+	astman_append(s, "Items: %d\r\n", channels);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }
@@ -5940,12 +5952,8 @@
 	}
 	ao2_iterator_destroy(&it_chans);
 
-	astman_append(s,
-		"Event: CoreShowChannelsComplete\r\n"
-		"EventList: Complete\r\n"
-		"ListItems: %d\r\n"
-		"%s"
-		"\r\n", numchans, idText);
+	astman_send_list_complete_start(s, m, "CoreShowChannelsComplete", numchans);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }

Modified: trunk/main/manager_bridges.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/manager_bridges.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/main/manager_bridges.c (original)
+++ trunk/main/manager_bridges.c Fri Jan  9 12:16:54 2015
@@ -364,12 +364,17 @@
 	return strcmp(bridge_type, snapshot->technology) ? CMP_MATCH : 0;
 }
 
+struct bridge_list_data {
+	const char *id_text;
+	int count;
+};
+
 static int send_bridge_list_item_cb(void *obj, void *arg, void *data, int flags)
 {
 	struct ast_bridge_snapshot *snapshot = stasis_message_data(obj);
 	struct mansession *s = arg;
-	char *id_text = data;
-	RAII_VAR(struct ast_str *, bridge_info, ast_manager_build_bridge_state_string(snapshot), ast_free_ptr);
+	struct bridge_list_data *list_data = data;
+	RAII_VAR(struct ast_str *, bridge_info, ast_manager_build_bridge_state_string(snapshot), ast_free);
 
 	if (!bridge_info) {
 		return 0;
@@ -380,8 +385,9 @@
 		"%s"
 		"%s"
 		"\r\n",
-		ast_str_buffer(bridge_info),
-		id_text);
+		list_data->id_text,
+		ast_str_buffer(bridge_info));
+	++list_data->count;
 	return 0;
 }
 
@@ -391,6 +397,7 @@
 	const char *type_filter = astman_get_header(m, "BridgeType");
 	RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free);
 	RAII_VAR(struct ao2_container *, bridges, NULL, ao2_cleanup);
+	struct bridge_list_data list_data;
 
 	if (!id_text) {
 		astman_send_error(s, m, "Internal error");
@@ -407,20 +414,21 @@
 		return -1;
 	}
 
-	astman_send_ack(s, m, "Bridge listing will follow");
+	astman_send_listack(s, m, "Bridge listing will follow", "start");
 
 	if (!ast_strlen_zero(type_filter)) {
 		char *type_filter_dup = ast_strdupa(type_filter);
-		ao2_callback(bridges, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK, filter_bridge_type_cb, type_filter_dup);
-	}
-
-	ao2_callback_data(bridges, OBJ_NODATA, send_bridge_list_item_cb, s, ast_str_buffer(id_text));
-
-	astman_append(s,
-		"Event: BridgeListComplete\r\n"
-		"%s"
-		"\r\n",
-		ast_str_buffer(id_text));
+
+		ao2_callback(bridges, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK,
+			filter_bridge_type_cb, type_filter_dup);
+	}
+
+	list_data.id_text = ast_str_buffer(id_text);
+	list_data.count = 0;
+	ao2_callback_data(bridges, OBJ_NODATA, send_bridge_list_item_cb, s, &list_data);
+
+	astman_send_list_complete_start(s, m, "BridgeListComplete", list_data.count);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }
@@ -429,13 +437,13 @@
 {
 	char *uniqueid = obj;
 	struct mansession *s = arg;
-	char *id_text = data;
+	struct bridge_list_data *list_data = data;
 	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
 	struct ast_channel_snapshot *snapshot;
 	RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
+
 	msg = stasis_cache_get(ast_channel_cache(),
 		ast_channel_snapshot_type(), uniqueid);
-
 	if (!msg) {
 		return 0;
 	}
@@ -455,8 +463,9 @@
 		"%s"
 		"%s"
 		"\r\n",
-		ast_str_buffer(channel_text),
-		id_text);
+		list_data->id_text,
+		ast_str_buffer(channel_text));
+	++list_data->count;
 	return 0;
 }
 
@@ -468,6 +477,7 @@
 	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_str *, bridge_info, NULL, ast_free);
 	struct ast_bridge_snapshot *snapshot;
+	struct bridge_list_data list_data;
 
 	if (!id_text) {
 		astman_send_error(s, m, "Internal error");
@@ -489,20 +499,24 @@
 		return 0;
 	}
 
-	astman_send_ack(s, m, "Bridge channel listing will follow");
-
 	snapshot = stasis_message_data(msg);
 	bridge_info = ast_manager_build_bridge_state_string(snapshot);
-
-	ao2_callback_data(snapshot->channels, OBJ_NODATA, send_bridge_info_item_cb, s, ast_str_buffer(id_text));
-
-	astman_append(s,
-		"Event: BridgeInfoComplete\r\n"
-		"%s"
-		"%s"
-		"\r\n",
-		S_COR(bridge_info, ast_str_buffer(bridge_info), ""),
-		ast_str_buffer(id_text));
+	if (!bridge_info) {
+		astman_send_error(s, m, "Internal error");
+		return -1;
+	}
+
+	astman_send_listack(s, m, "Bridge channel listing will follow", "start");
+
+	list_data.id_text = ast_str_buffer(id_text);
+	list_data.count = 0;
+	ao2_callback_data(snapshot->channels, OBJ_NODATA, send_bridge_info_item_cb, s, &list_data);
+
+	astman_send_list_complete_start(s, m, "BridgeInfoComplete", list_data.count);
+	if (!ast_strlen_zero(ast_str_buffer(bridge_info))) {
+		astman_append(s, "%s", ast_str_buffer(bridge_info));
+	}
+	astman_send_list_complete_end(s);
 
 	return 0;
 }

Modified: trunk/main/pbx.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/pbx.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/main/pbx.c (original)
+++ trunk/main/pbx.c Fri Jan  9 12:16:54 2015
@@ -8333,14 +8333,13 @@
 		manager_dpsendack(s, m);
 	}
 
-	astman_append(s, "Event: ShowDialPlanComplete\r\n"
-		"EventList: Complete\r\n"
-		"ListItems: %d\r\n"
+	astman_send_list_complete_start(s, m, "ShowDialPlanComplete", counters.total_items);
+	astman_append(s,
 		"ListExtensions: %d\r\n"
 		"ListPriorities: %d\r\n"
-		"ListContexts: %d\r\n"
-		"%s"
-		"\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
+		"ListContexts: %d\r\n",
+		counters.total_exten, counters.total_prio, counters.total_context);
+	astman_send_list_complete_end(s);
 
 	/* everything ok */
 	return 0;
@@ -12047,15 +12046,12 @@
 		   ast_extension_state2str(hint->laststate));
 		ao2_unlock(hint);
 	}
-	astman_append(s, "Event: ExtensionStateListComplete\r\n");
-	if (!ast_strlen_zero(action_id)) {
-		astman_append(s, "ActionID: %s\r\n", action_id);
-	}
-	astman_append(s, "EventList: Complete\r\n"
-		"ListItems: %d\r\n\r\n", hint_count);
 
 	ao2_iterator_destroy(&it_hints);
 	ao2_unlock(hints);
+
+	astman_send_list_complete_start(s, m, "ExtensionStateListComplete", hint_count);
+	astman_send_list_complete_end(s);
 
 	return 0;
 }

Modified: trunk/res/parking/parking_manager.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/parking/parking_manager.c?view=diff&rev=430435&r1=430434&r2=430435
==============================================================================
--- trunk/res/parking/parking_manager.c (original)
+++ trunk/res/parking/parking_manager.c Fri Jan  9 12:16:54 2015
@@ -210,11 +210,16 @@
 
 	parkee_string = ast_manager_build_channel_state_string_prefix(payload->parkee, "Parkee");
 	if (!parkee_string) {
+		ast_free(out);
 		return NULL;
 	}
 
 	if (payload->retriever) {
 		retriever_string = ast_manager_build_channel_state_string_prefix(payload->retriever, "Retriever");
+		if (!retriever_string) {
+			ast_free(out);
+			return NULL;
+		}
 	}
 
 	ast_str_set(&out, 0,
@@ -250,7 +255,7 @@
 		return;
 	}
 
-	astman_send_ack(s, m, "Parked calls will follow");
+	astman_send_listack(s, m, "Parked calls will follow", "start");
 
 	iter_users = ao2_iterator_init(curlot->parked_users, 0);
 	while ((curuser = ao2_iterator_next(&iter_users))) {
@@ -260,17 +265,13 @@
 		payload = parked_call_payload_from_parked_user(curuser, PARKED_CALL);
 		if (!payload) {
 			ao2_ref(curuser, -1);
-			ao2_iterator_destroy(&iter_users);
-			astman_send_error(s, m, "Failed to retrieve parking data about a parked user.");
-			return;
+			break;
 		}
 
 		parked_call_string = manager_build_parked_call_string(payload);
 		if (!parked_call_string) {
 			ao2_ref(curuser, -1);
-			ao2_iterator_destroy(&iter_users);
-			astman_send_error(s, m, "Failed to retrieve parking data about a parked user.");
-			return;
+			break;
 		}
 

[... 471 lines stripped ...]



More information about the svn-commits mailing list