[svn-commits] kharwell: branch kharwell/pimp_sip_security r392720 - in /team/kharwell/pimp_...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Jun 24 09:33:51 CDT 2013


Author: kharwell
Date: Mon Jun 24 09:33:41 2013
New Revision: 392720

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392720
Log:
Multiple revisions 392669,392689,392703

........
  r392669 | root | 2013-06-23 14:17:38 -0500 (Sun, 23 Jun 2013) | 5 lines
  
  Add some more missing ast_sorcery_generic_alloc conversions.
  ........
  
  Merged revisions 392667 from file:///srv/subversion/repos/asterisk/trunk
........
  r392689 | root | 2013-06-23 15:17:39 -0500 (Sun, 23 Jun 2013) | 13 lines
  
  Properly pack the parameters into ast_json_pack when sending a send fax message
  
  This patch properly packs the parameters into the send fax message so that it
  actually work.
  
  Missing a ',' between two string fields can be difficult to debug, particularly
  when the actual packing succeeds. Interestingly enough, this didn't actually
  crash until the JSON blob we deref'd and disposed of. Since that happened in
  a different thread, it was pretty tough to track down.
  ........
  
  Merged revisions 392676 from file:///srv/subversion/repos/asterisk/trunk
........
  r392703 | root | 2013-06-24 09:18:22 -0500 (Mon, 24 Jun 2013) | 23 lines
  
  Index installed sounds and implement ARI sounds queries
  
  This adds support for stasis/sounds and stasis/sounds/{ID} queries via
  the Asterisk RESTful Interface (ARI, formerly Stasis-HTTP).
  
  The following changes have been made to accomplish this:
  * A modular indexer was created for local media.
  * A new function to get an ast_format associated with a file extension
    was added.  
  * Modifications were made to the built-in HTTP server so that URI
    decoding could be deferred to the URI handler when necessary.
  * The Stasis-HTTP sounds JSON documentation was modified to handle
    cases where multiple languages are installed in different formats.
  * Register and Unregister events for formats were added to the system
    topic.
  
  (closes issue ASTERISK-21584)
  (closes issue ASTERISK-21585)
  Review: https://reviewboard.asterisk.org/r/2507/
  ........
  
  Merged revisions 392700 from file:///srv/subversion/repos/asterisk/trunk
........

Merged revisions 392669,392689,392703 from http://svn.asterisk.org/svn/asterisk/team/group/pimp_my_sip

Added:
    team/kharwell/pimp_sip_security/include/asterisk/media_index.h
      - copied unchanged from r392703, team/group/pimp_my_sip/include/asterisk/media_index.h
    team/kharwell/pimp_sip_security/include/asterisk/sounds_index.h
      - copied unchanged from r392703, team/group/pimp_my_sip/include/asterisk/sounds_index.h
    team/kharwell/pimp_sip_security/main/media_index.c
      - copied unchanged from r392703, team/group/pimp_my_sip/main/media_index.c
    team/kharwell/pimp_sip_security/main/sounds_index.c
      - copied unchanged from r392703, team/group/pimp_my_sip/main/sounds_index.c
Modified:
    team/kharwell/pimp_sip_security/   (props changed)
    team/kharwell/pimp_sip_security/include/asterisk/_private.h
    team/kharwell/pimp_sip_security/include/asterisk/file.h
    team/kharwell/pimp_sip_security/include/asterisk/format.h
    team/kharwell/pimp_sip_security/include/asterisk/http.h
    team/kharwell/pimp_sip_security/main/asterisk.c
    team/kharwell/pimp_sip_security/main/file.c
    team/kharwell/pimp_sip_security/main/http.c
    team/kharwell/pimp_sip_security/res/res_fax.c
    team/kharwell/pimp_sip_security/res/res_sip_acl.c
    team/kharwell/pimp_sip_security/res/res_sip_endpoint_identifier_ip.c
    team/kharwell/pimp_sip_security/res/res_sip_outbound_registration.c
    team/kharwell/pimp_sip_security/res/res_stasis_http.c
    team/kharwell/pimp_sip_security/res/stasis_http/resource_sounds.c
    team/kharwell/pimp_sip_security/rest-api/api-docs/sounds.json

Propchange: team/kharwell/pimp_sip_security/
------------------------------------------------------------------------------
--- pimp_sip_security-integrated (original)
+++ pimp_sip_security-integrated Mon Jun 24 09:33:41 2013
@@ -1,1 +1,1 @@
-/team/group/pimp_my_sip:1-392649
+/team/group/pimp_my_sip:1-392719

Propchange: team/kharwell/pimp_sip_security/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Jun 24 09:33:41 2013
@@ -1,1 +1,1 @@
-/trunk:1-392648
+/trunk:1-392702

Modified: team/kharwell/pimp_sip_security/include/asterisk/_private.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/include/asterisk/_private.h?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/include/asterisk/_private.h (original)
+++ team/kharwell/pimp_sip_security/include/asterisk/_private.h Mon Jun 24 09:33:41 2013
@@ -140,4 +140,7 @@
  * \since 12.0.0
  */
 int ast_parking_stasis_init(void);
+
+/*! \brief initialize the sounds index */
+int ast_sounds_index_init(void);
 #endif /* _ASTERISK__PRIVATE_H */

Modified: team/kharwell/pimp_sip_security/include/asterisk/file.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/include/asterisk/file.h?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/include/asterisk/file.h (original)
+++ team/kharwell/pimp_sip_security/include/asterisk/file.h Mon Jun 24 09:33:41 2013
@@ -376,6 +376,17 @@
  */
 char *ast_format_str_reduce(char *fmts);
 
+/*!
+ * \brief Get the ast_format associated with the given file extension
+ * \since 12
+ *
+ * \param file_ext The file extension for which to find the format
+ *
+ * \retval NULL if not found
+ * \retval A pointer to the ast_format associated with this file extension
+ */
+const struct ast_format *ast_get_format_for_file_ext(const char *file_ext);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/kharwell/pimp_sip_security/include/asterisk/format.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/include/asterisk/format.h?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/include/asterisk/format.h (original)
+++ team/kharwell/pimp_sip_security/include/asterisk/format.h Mon Jun 24 09:33:41 2013
@@ -471,4 +471,22 @@
  * \brief Get the best slinear format id for a given sample rate
  */
 enum ast_format_id ast_format_slin_by_rate(unsigned int rate);
+
+/*!
+ * \since 12
+ * \brief Get the message type used for signaling a format registration
+ *
+ * \retval Stasis message type for format registration
+ * \retval NULL on error
+ */
+struct stasis_message_type *ast_format_register_type(void);
+
+/*!
+ * \since 12
+ * \brief Get the message type used for signaling a format unregistration
+ *
+ * \retval Stasis message type for format unregistration
+ * \retval NULL on error
+ */
+struct stasis_message_type *ast_format_unregister_type(void);
 #endif /* _AST_FORMAT_H */

Modified: team/kharwell/pimp_sip_security/include/asterisk/http.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/include/asterisk/http.h?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/include/asterisk/http.h (original)
+++ team/kharwell/pimp_sip_security/include/asterisk/http.h Mon Jun 24 09:33:41 2013
@@ -101,6 +101,8 @@
 	unsigned int mallocd:1;
 	/*! Data structure is malloc'd */
 	unsigned int dmallocd:1;
+	/*! Don't automatically decode URI before passing it to the callback */
+	unsigned int no_decode_uri:1;
 	/*! Data to bind to the uri if needed */
 	void *data;
 	/*! Key to be used for unlinking if multiple URIs registered */

Modified: team/kharwell/pimp_sip_security/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/main/asterisk.c?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/main/asterisk.c (original)
+++ team/kharwell/pimp_sip_security/main/asterisk.c Mon Jun 24 09:33:41 2013
@@ -4396,6 +4396,11 @@
 		exit(1);
 	}
 
+	if (ast_sounds_index_init()) {
+		printf("%s", term_quit());
+		exit(1);
+	}
+
 	if ((moduleresult = load_modules(0))) {		/* Load modules */
 		printf("%s", term_quit());
 		exit(moduleresult == -2 ? 2 : 1);

Modified: team/kharwell/pimp_sip_security/main/file.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/main/file.c?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/main/file.c (original)
+++ team/kharwell/pimp_sip_security/main/file.c Mon Jun 24 09:33:41 2013
@@ -51,6 +51,8 @@
 #include "asterisk/module.h"
 #include "asterisk/astobj2.h"
 #include "asterisk/test.h"
+#include "asterisk/stasis.h"
+#include "asterisk/json.h"
 
 /*! \brief
  * The following variable controls the layout of localized sound files.
@@ -66,6 +68,55 @@
 
 static AST_RWLIST_HEAD_STATIC(formats, ast_format_def);
 
+STASIS_MESSAGE_TYPE_DEFN(ast_format_register_type);
+STASIS_MESSAGE_TYPE_DEFN(ast_format_unregister_type);
+
+static struct ast_json *json_array_from_list(const char *list, const char *sep)
+{
+	RAII_VAR(struct ast_json *, array, ast_json_array_create(), ast_json_unref);
+	RAII_VAR(char *, stringp, ast_strdup(list), ast_free);
+	char *ext;
+
+	if (!array || !stringp) {
+		return NULL;
+	}
+
+	while ((ext = strsep(&stringp, sep))) {
+		if (ast_json_array_append(array, ast_json_string_create(ext))) {
+			return NULL;
+		}
+	}
+
+	return ast_json_ref(array);
+}
+
+static int publish_format_update(const struct ast_format_def *f, struct stasis_message_type *type)
+{
+	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_json_payload *, json_payload, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
+
+	json_object = ast_json_pack("{s: s, s: o}",
+		"format", f->name,
+		"extensions", json_array_from_list(f->exts, "|"));
+	if (!json_object) {
+		return -1;
+	}
+
+	json_payload = ast_json_payload_create(json_object);
+	if (!json_payload) {
+		return -1;
+	}
+
+	msg = stasis_message_create(type, json_payload);
+	if (!msg) {
+		return -1;
+	}
+
+	stasis_publish(ast_system_topic(), msg);
+	return 0;
+}
+
 int __ast_format_def_register(const struct ast_format_def *f, struct ast_module *mod)
 {
 	struct ast_format_def *tmp;
@@ -99,6 +150,7 @@
 	AST_RWLIST_INSERT_HEAD(&formats, tmp, list);
 	AST_RWLIST_UNLOCK(&formats);
 	ast_verb(2, "Registered file format %s, extension(s) %s\n", f->name, f->exts);
+	publish_format_update(f, ast_format_register_type());
 
 	return 0;
 }
@@ -112,6 +164,7 @@
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&formats, tmp, list) {
 		if (!strcasecmp(name, tmp->name)) {
 			AST_RWLIST_REMOVE_CURRENT(list);
+			publish_format_update(tmp, ast_format_unregister_type());
 			ast_free(tmp);
 			res = 0;
 		}
@@ -1672,6 +1725,19 @@
 #undef FORMAT2
 }
 
+const struct ast_format *ast_get_format_for_file_ext(const char *file_ext)
+{
+	struct ast_format_def *f;
+	SCOPED_RDLOCK(lock, &formats.lock);
+	AST_RWLIST_TRAVERSE(&formats, f, list) {
+		if (exts_compare(f->exts, file_ext)) {
+			return &f->format;
+		}
+	}
+
+	return NULL;
+}
+
 static struct ast_cli_entry cli_file[] = {
 	AST_CLI_DEFINE(handle_cli_core_show_file_formats, "Displays file formats")
 };
@@ -1679,10 +1745,14 @@
 static void file_shutdown(void)
 {
 	ast_cli_unregister_multiple(cli_file, ARRAY_LEN(cli_file));
+	STASIS_MESSAGE_TYPE_CLEANUP(ast_format_register_type);
+	STASIS_MESSAGE_TYPE_CLEANUP(ast_format_unregister_type);
 }
 
 int ast_file_init(void)
 {
+	STASIS_MESSAGE_TYPE_INIT(ast_format_register_type);
+	STASIS_MESSAGE_TYPE_INIT(ast_format_unregister_type);
 	ast_cli_register_multiple(cli_file, ARRAY_LEN(cli_file));
 	ast_register_atexit(file_shutdown);
 	return 0;

Modified: team/kharwell/pimp_sip_security/main/http.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/main/http.c?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/main/http.c (original)
+++ team/kharwell/pimp_sip_security/main/http.c Mon Jun 24 09:33:41 2013
@@ -718,7 +718,6 @@
 			}
 		}
 	}
-	ast_uri_decode(uri, ast_uri_http_legacy);
 
 	AST_RWLIST_RDLOCK(&uri_redirects);
 	AST_RWLIST_TRAVERSE(&uri_redirects, redirect, entry) {
@@ -760,6 +759,9 @@
 		AST_RWLIST_UNLOCK(&uris);
 	}
 	if (urih) {
+		if (!urih->no_decode_uri) {
+			ast_uri_decode(uri, ast_uri_http_legacy);
+		}
 		res = urih->callback(ser, urih, uri, method, get_vars, headers);
 	} else {
 		ast_http_error(ser, 404, "Not Found", "The requested URL was not found on this server.");

Modified: team/kharwell/pimp_sip_security/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/res/res_fax.c?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/res/res_fax.c (original)
+++ team/kharwell/pimp_sip_security/res/res_fax.c Mon Jun 24 09:33:41 2013
@@ -2308,9 +2308,8 @@
 		if (!ast_strlen_zero(fax_bitrate)) {
 			fax_bitrate = ast_strdupa(fax_bitrate);
 		}
-
 		json_obj = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
-				"type", "send"
+				"type", "send",
 				"remote_station_id", S_OR(remote_station_id, ""),
 				"local_station_id", S_OR(local_station_id, ""),
 				"fax_pages", S_OR(fax_pages, ""),

Modified: team/kharwell/pimp_sip_security/res/res_sip_acl.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/res/res_sip_acl.c?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/res/res_sip_acl.c (original)
+++ team/kharwell/pimp_sip_security/res/res_sip_acl.c Mon Jun 24 09:33:41 2013
@@ -77,12 +77,18 @@
 					<synopsis>List of IP-domains to allow access from</synopsis>
 				</configOption>
 				<configOption name="type">
-					<synopsis>Must be of type 'security'.</synopsis>
+					<synopsis>Must be of type 'acl'.</synopsis>
 				</configOption>
 			</configObject>
 		</configFile>
 	</configInfo>
  ***/
+
+struct sip_acl {
+	SORCERY_OBJECT(details);
+	struct ast_acl_list *acl;
+	struct ast_acl_list *contact_acl;
+};
 
 static int apply_acl(pjsip_rx_data *rdata, struct ast_acl_list *acl)
 {
@@ -155,10 +161,10 @@
 
 static int check_acls(void *obj, void *arg, int flags)
 {
-	struct ast_sip_security *security = obj;
+	struct sip_acl *acl = obj;
 	pjsip_rx_data *rdata = arg;
 
-	if (apply_acl(rdata, security->acl) || apply_contact_acl(rdata, security->contact_acl)) {
+	if (apply_acl(rdata, acl->acl) || apply_contact_acl(rdata, acl->contact_acl)) {
 		return CMP_MATCH | CMP_STOP;
 	}
 	return 0;
@@ -166,17 +172,22 @@
 
 static pj_bool_t acl_on_rx_msg(pjsip_rx_data *rdata)
 {
-	RAII_VAR(struct ao2_container *, acls, ast_sorcery_retrieve_by_fields(
-		ast_sip_get_sorcery(), SIP_SORCERY_SECURITY_TYPE,
-		AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL), ao2_cleanup);
-	RAII_VAR(struct ast_sip_security *, matched_acl, NULL, ao2_cleanup);
-
+	int forbidden = 0;
+	struct ao2_container *acls = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "acl", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+	struct sip_acl *matched_acl;
 	if (!acls) {
 		ast_log(LOG_ERROR, "Unable to retrieve ACL sorcery data\n");
 		return PJ_FALSE;
 	}
 
-	if ((matched_acl = ao2_callback(acls, 0, check_acls, rdata))) {
+	matched_acl = ao2_callback(acls, 0, check_acls, rdata);
+	if (matched_acl) {
+		forbidden = 1;
+		ao2_ref(matched_acl, -1);
+	}
+	ao2_ref(acls, -1);
+
+	if (forbidden) {
 		if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
 			pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
 		}
@@ -193,8 +204,60 @@
 	.on_rx_request = acl_on_rx_msg,
 };
 
+static int acl_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+	struct sip_acl *acl = obj;
+	int error;
+	int ignore;
+	if (!strncmp(var->name, "contact", 7)) {
+		ast_append_acl(var->name + 7, var->value, &acl->contact_acl, &error, &ignore);
+	} else {
+		ast_append_acl(var->name, var->value, &acl->acl, &error, &ignore);
+	}
+	return error;
+}
+
+static void sip_acl_destructor(void *obj)
+{
+	struct sip_acl *acl = obj;
+	acl->acl = ast_free_acl_list(acl->acl);
+	acl->contact_acl = ast_free_acl_list(acl->contact_acl);
+}
+
+static void *sip_acl_alloc(const char *name)
+{
+	struct sip_acl *acl = ast_sorcery_generic_alloc(sizeof(*acl), sip_acl_destructor);
+	if (!acl) {
+		return NULL;
+	}
+	return acl;
+}
+
+static int load_acls(void)
+{
+	ast_sorcery_apply_default(ast_sip_get_sorcery(), "acl", "config", "res_sip.conf,criteria=type=acl");
+	if (ast_sorcery_object_register(ast_sip_get_sorcery(), "acl", sip_acl_alloc, NULL, NULL)) {
+		ast_log(LOG_ERROR, "Failed to register SIP ACL object with sorcery\n");
+		return -1;
+	}
+	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "acl", "type", "", OPT_NOOP_T, 0, 0);
+	ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "acl", "permit", "", acl_handler, NULL, 0, 0);
+	ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "acl", "deny", "", acl_handler, NULL, 0, 0);
+	ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "acl", "acl", "", acl_handler, NULL, 0, 0);
+	ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "acl", "contactpermit", "", acl_handler, NULL, 0, 0);
+	ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "acl", "contactdeny", "", acl_handler, NULL, 0, 0);
+	ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "acl", "contactacl", "", acl_handler, NULL, 0, 0);
+
+	/* XXX Is there a more selective way to do this? (i.e. Just reload a specific object type?) */
+	ast_sorcery_reload(ast_sip_get_sorcery());
+	return 0;
+}
+
 static int load_module(void)
 {
+	if (load_acls()) {
+		return AST_MODULE_LOAD_DECLINE;
+	}
 	ast_sip_register_service(&acl_module);
 	return AST_MODULE_LOAD_SUCCESS;
 }

Modified: team/kharwell/pimp_sip_security/res/res_sip_endpoint_identifier_ip.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/res/res_sip_endpoint_identifier_ip.c?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/res/res_sip_endpoint_identifier_ip.c (original)
+++ team/kharwell/pimp_sip_security/res/res_sip_endpoint_identifier_ip.c Mon Jun 24 09:33:41 2013
@@ -74,7 +74,7 @@
 /*! \brief Allocator function for a matching object */
 static void *ip_identify_alloc(const char *name)
 {
-	struct ip_identify_match *identify = ao2_alloc(sizeof(*identify), ip_identify_destroy);
+	struct ip_identify_match *identify = ast_sorcery_generic_alloc(sizeof(*identify), ip_identify_destroy);
 
 	if (!identify || ast_string_field_init(identify, 256)) {
 		ao2_cleanup(identify);

Modified: team/kharwell/pimp_sip_security/res/res_sip_outbound_registration.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/res/res_sip_outbound_registration.c?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/res/res_sip_outbound_registration.c (original)
+++ team/kharwell/pimp_sip_security/res/res_sip_outbound_registration.c Mon Jun 24 09:33:41 2013
@@ -469,7 +469,7 @@
 /*! \brief Allocator function for registration information */
 static void *sip_outbound_registration_alloc(const char *name)
 {
-	struct sip_outbound_registration *registration = ao2_alloc(sizeof(*registration), sip_outbound_registration_destroy);
+	struct sip_outbound_registration *registration = ast_sorcery_generic_alloc(sizeof(*registration), sip_outbound_registration_destroy);
 
 	if (!registration || ast_string_field_init(registration, 256)) {
 		ao2_cleanup(registration);

Modified: team/kharwell/pimp_sip_security/res/res_stasis_http.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/res/res_stasis_http.c?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/res/res_stasis_http.c (original)
+++ team/kharwell/pimp_sip_security/res/res_stasis_http.c Mon Jun 24 09:33:41 2013
@@ -506,7 +506,7 @@
 	struct stasis_rest_handlers *handler;
 	struct ast_variable *path_vars = NULL;
 	char *path = ast_strdupa(uri);
-	const char *path_segment;
+	char *path_segment;
 	stasis_rest_callback callback;
 
 	root = handler = get_root_handler();
@@ -515,6 +515,7 @@
 	while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {
 		struct stasis_rest_handlers *found_handler = NULL;
 		int i;
+		ast_uri_decode(path_segment, ast_uri_http_legacy);
 		ast_debug(3, "Finding handler for %s\n", path_segment);
 		for (i = 0; found_handler == NULL && i < handler->num_children; ++i) {
 			struct stasis_rest_handlers *child = handler->children[i];
@@ -863,6 +864,7 @@
 	.has_subtree = 1,
 	.data = NULL,
 	.key = __FILE__,
+	.no_decode_uri = 1,
 };
 
 static int load_module(void)

Modified: team/kharwell/pimp_sip_security/res/stasis_http/resource_sounds.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/res/stasis_http/resource_sounds.c?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/res/stasis_http/resource_sounds.c (original)
+++ team/kharwell/pimp_sip_security/res/stasis_http/resource_sounds.c Mon Jun 24 09:33:41 2013
@@ -28,12 +28,193 @@
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "resource_sounds.h"
+#include "asterisk/media_index.h"
+#include "asterisk/sounds_index.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cap.h"
+#include "asterisk/json.h"
+
+/*! \brief arguments that are necessary for adding format/lang pairs */
+struct lang_format_info {
+	struct ast_json *format_list;	/*!< The embedded array to which format/lang pairs should be added */
+	const char *filename;		/*!< Name of the file for which to add format/lang pairs */
+	const char *format_filter;	/*!< Format filter provided in the request */
+};
+
+/*! \brief Add format/lang pairs to the array embedded in the sound object */
+static int add_format_information_cb(void *obj, void *arg, int flags)
+{
+	char *language = obj;
+	struct lang_format_info *args = arg;
+	struct ast_format format;
+	RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
+	RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);
+
+	if (!sounds_index) {
+		return CMP_STOP;
+	}
+
+	cap = ast_media_get_format_cap(sounds_index, args->filename, language);
+	if (!cap) {
+		return CMP_STOP;
+	}
+
+	ast_format_cap_iter_start(cap);
+	while (!ast_format_cap_iter_next(cap, &format)) {
+		struct ast_json *lang_format_pair;
+		const char *format_name = ast_getformatname(&format);
+
+		if (!ast_strlen_zero(args->format_filter)
+			&& strcmp(args->format_filter, format_name)) {
+			continue;
+		}
+
+		lang_format_pair = ast_json_pack("{s: s, s: s}",
+			"language", language,
+			"format", format_name);
+		if (!lang_format_pair) {
+			ast_format_cap_iter_end(cap);
+			return CMP_STOP;
+		}
+
+		ast_json_array_append(args->format_list, lang_format_pair);
+	}
+	ast_format_cap_iter_end(cap);
+	return 0;
+}
+
+/*! \brief Filter out all languages not matching the specified language */
+static int filter_langs_cb(void *obj, void *arg, int flags)
+{
+	char *lang_filter = arg;
+	char *lang = obj;
+	if (strcmp(lang, lang_filter)) {
+		return CMP_MATCH;
+	}
+	return 0;
+}
+
+/*! \brief Generate a Sound structure as documented in sounds.json for the specified filename */
+static struct ast_json *create_sound_blob(const char *filename, struct ast_get_sounds_args *args)
+{
+	RAII_VAR(struct ast_json *, sound, NULL, ast_json_unref);
+	RAII_VAR(struct ao2_container *, languages, NULL, ao2_cleanup);
+	const char *description;
+	struct ast_json *format_lang_list;
+	struct lang_format_info info;
+	RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);
+
+	if (!sounds_index) {
+		return NULL;
+	}
+
+	description = ast_media_get_description(sounds_index, filename, "en");
+	if (ast_strlen_zero(description)) {
+		sound = ast_json_pack("{s: s, s: []}",
+			"id", filename,
+			"formats");
+	} else {
+		sound = ast_json_pack("{s: s, s: s, s: []}",
+			"id", filename,
+			"text", description,
+			"formats");
+	}
+	if (!sound) {
+		return NULL;
+	}
+
+	format_lang_list = ast_json_object_get(sound, "formats");
+	if (!format_lang_list) {
+		return NULL;
+	}
+
+	languages = ast_media_get_variants(sounds_index, filename);
+	if (!languages || !ao2_container_count(languages)) {
+		return NULL;
+	}
+
+	/* filter requested languages */
+	if (args && !ast_strlen_zero(args->lang)) {
+		char *lang_filter = ast_strdupa(args->lang);
+		ao2_callback(languages, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, filter_langs_cb, lang_filter);
+		if (!languages || !ao2_container_count(languages)) {
+			return NULL;
+		}
+	}
+
+	info.filename = filename;
+	info.format_list = format_lang_list;
+	info.format_filter = NULL;
+	if (args) {
+		info.format_filter = args->format;
+	}
+	ao2_callback(languages, OBJ_NODATA, add_format_information_cb, &info);
+
+	/* no format/lang pairs for this sound so nothing to return */
+	if (!ast_json_array_size(format_lang_list)) {
+		return NULL;
+	}
+
+	return ast_json_ref(sound);
+}
+
+/*! \brief Generate a Sound structure and append it to the output blob */
+static int append_sound_cb(void *obj, void *arg, void *data, int flags)
+{
+	struct ast_json *sounds_array = arg;
+	char *filename = obj;
+	struct ast_get_sounds_args *args = data;
+	struct ast_json *sound_blob = create_sound_blob(filename, args);
+	if (!sound_blob) {
+		return 0;
+	}
+
+	ast_json_array_append(sounds_array, sound_blob);
+	return 0;
+}
 
 void stasis_http_get_sounds(struct ast_variable *headers, struct ast_get_sounds_args *args, struct stasis_http_response *response)
 {
-	ast_log(LOG_ERROR, "TODO: stasis_http_get_sounds\n");
-}
+	RAII_VAR(struct ao2_container *, sound_files, NULL, ao2_cleanup);
+	struct ast_json *sounds_blob;
+	RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);
+
+	if (!sounds_index) {
+		stasis_http_response_error(response, 500, "Internal Error", "Sounds index not available");
+		return;
+	}
+
+	sound_files = ast_media_get_media(sounds_index);
+	if (!sound_files) {
+		stasis_http_response_error(response, 500, "Internal Error", "Allocation Error");
+		return;
+	}
+
+	sounds_blob = ast_json_array_create();
+	if (!sounds_blob) {
+		stasis_http_response_error(response, 500, "Internal Error", "Allocation Error");
+		return;
+	}
+
+	ao2_callback_data(sound_files, OBJ_NODATA, append_sound_cb, sounds_blob, args);
+
+	if (!ast_json_array_size(sounds_blob)) {
+		stasis_http_response_error(response, 404, "Not Found", "No sounds found that matched the query");
+		return;
+	}
+
+	stasis_http_response_ok(response, sounds_blob);
+}
+
 void stasis_http_get_stored_sound(struct ast_variable *headers, struct ast_get_stored_sound_args *args, struct stasis_http_response *response)
 {
-	ast_log(LOG_ERROR, "TODO: stasis_http_get_stored_sound\n");
-}
+	struct ast_json *sound_blob;
+
+	sound_blob = create_sound_blob(args->sound_id, NULL);
+	if (!sound_blob) {
+		stasis_http_response_error(response, 404, "Not Found", "Sound not found");
+		return;
+	}
+
+	stasis_http_response_ok(response, sound_blob);
+}

Modified: team/kharwell/pimp_sip_security/rest-api/api-docs/sounds.json
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_security/rest-api/api-docs/sounds.json?view=diff&rev=392720&r1=392719&r2=392720
==============================================================================
--- team/kharwell/pimp_sip_security/rest-api/api-docs/sounds.json (original)
+++ team/kharwell/pimp_sip_security/rest-api/api-docs/sounds.json Mon Jun 24 09:33:41 2013
@@ -58,6 +58,19 @@
 		}
 	],
 	"models": {
+		"FormatLangPair": {
+			"id": "FormatLangPair",
+			"properties": {
+				"language": {
+					"required": true,
+					"type": "string"
+				},
+				"format": {
+					"required": true,
+					"type": "string"
+				}
+			}
+		},
 		"Sound": {
 			"id": "Sound",
 			"properties": {
@@ -71,13 +84,10 @@
 					"description": "Text description of the sound, usually the words spoken.",
 					"type": "string"
 				},
-				"lang": {
-					"required": true,
-					"type": "string"
-				},
 				"formats": {
 					"required": true,
-					"type": "List[string]"
+					"description": "The formats and languages in which this sound is available.",
+					"type": "List[FormatLangPair]"
 				}
 			}
 		}




More information about the svn-commits mailing list