mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-07-13 02:27:48 +00:00
rss feeds of your voicemail
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6417 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
86b0bde562
commit
60c783c636
@ -763,6 +763,8 @@ SWITCH_DECLARE(switch_size_t) switch_file_get_size(switch_file_t *thefile);
|
|||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_file_exists(const char *filename, switch_memory_pool_t *pool);
|
SWITCH_DECLARE(switch_status_t) switch_file_exists(const char *filename, switch_memory_pool_t *pool);
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_directory_exists(const char *dirname, switch_memory_pool_t *pool);
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_dir_make(const char *path, switch_fileperms_t perm,
|
SWITCH_DECLARE(switch_status_t) switch_dir_make(const char *path, switch_fileperms_t perm,
|
||||||
switch_memory_pool_t *pool);
|
switch_memory_pool_t *pool);
|
||||||
SWITCH_DECLARE(switch_status_t) switch_dir_make_recursive(const char *path, switch_fileperms_t perm,
|
SWITCH_DECLARE(switch_status_t) switch_dir_make_recursive(const char *path, switch_fileperms_t perm,
|
||||||
|
@ -49,6 +49,7 @@ SWITCH_BEGIN_EXTERN_C
|
|||||||
s.end = s.data; \
|
s.end = s.data; \
|
||||||
s.data_size = SWITCH_CMD_CHUNK_LEN; \
|
s.data_size = SWITCH_CMD_CHUNK_LEN; \
|
||||||
s.write_function = switch_console_stream_write; \
|
s.write_function = switch_console_stream_write; \
|
||||||
|
s.raw_write_function = switch_console_stream_raw_write; \
|
||||||
s.alloc_len = SWITCH_CMD_CHUNK_LEN; \
|
s.alloc_len = SWITCH_CMD_CHUNK_LEN; \
|
||||||
s.alloc_chunk = SWITCH_CMD_CHUNK_LEN
|
s.alloc_chunk = SWITCH_CMD_CHUNK_LEN
|
||||||
|
|
||||||
@ -63,6 +64,8 @@ SWITCH_DECLARE(void) switch_console_loop(void);
|
|||||||
SWITCH_DECLARE(void) switch_console_printf(switch_text_channel_t channel, const char *file, const char *func, int line,
|
SWITCH_DECLARE(void) switch_console_printf(switch_text_channel_t channel, const char *file, const char *func, int line,
|
||||||
const char *fmt, ...) PRINTF_FUNCTION(5, 6);
|
const char *fmt, ...) PRINTF_FUNCTION(5, 6);
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_console_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief A method akin to printf for dealing with api streams
|
\brief A method akin to printf for dealing with api streams
|
||||||
*/
|
*/
|
||||||
|
@ -81,6 +81,7 @@ struct switch_state_handler_table {
|
|||||||
|
|
||||||
struct switch_stream_handle {
|
struct switch_stream_handle {
|
||||||
switch_stream_handle_write_function_t write_function;
|
switch_stream_handle_write_function_t write_function;
|
||||||
|
switch_stream_handle_raw_write_function_t raw_write_function;
|
||||||
void *data;
|
void *data;
|
||||||
void *end;
|
void *end;
|
||||||
switch_size_t data_size;
|
switch_size_t data_size;
|
||||||
|
@ -1090,6 +1090,7 @@ typedef void (*switch_scheduler_func_t) (switch_scheduler_task_t *task);
|
|||||||
typedef switch_status_t (*switch_state_handler_t) (switch_core_session_t *);
|
typedef switch_status_t (*switch_state_handler_t) (switch_core_session_t *);
|
||||||
typedef struct switch_stream_handle switch_stream_handle_t;
|
typedef struct switch_stream_handle switch_stream_handle_t;
|
||||||
typedef switch_status_t (*switch_stream_handle_write_function_t) (switch_stream_handle_t *handle, const char *fmt, ...);
|
typedef switch_status_t (*switch_stream_handle_write_function_t) (switch_stream_handle_t *handle, const char *fmt, ...);
|
||||||
|
typedef switch_status_t (*switch_stream_handle_raw_write_function_t) (switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen);
|
||||||
|
|
||||||
typedef switch_status_t (*switch_api_function_t) (const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream);
|
typedef switch_status_t (*switch_api_function_t) (const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream);
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ SWITCH_DECLARE(unsigned char) switch_char_to_rfc2833(char key);
|
|||||||
*/
|
*/
|
||||||
#define is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119)
|
#define is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119)
|
||||||
|
|
||||||
|
#define end_of(_s) *(_s + strlen(_s) - 1)
|
||||||
/*!
|
/*!
|
||||||
\brief Test for the existance of a flag on an arbitary object
|
\brief Test for the existance of a flag on an arbitary object
|
||||||
\param obj the object to test
|
\param obj the object to test
|
||||||
|
@ -2119,9 +2119,423 @@ static void message_query_handler(switch_event_t *event)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VOICEMAIL_SYNTAX "rss [<host> <port> <uri> <user> <domain>]"
|
||||||
|
|
||||||
|
struct holder {
|
||||||
|
vm_profile_t *profile;
|
||||||
|
switch_memory_pool_t *pool;
|
||||||
|
switch_stream_handle_t *stream;
|
||||||
|
switch_xml_t xml;
|
||||||
|
switch_xml_t x_item;
|
||||||
|
switch_xml_t x_channel;
|
||||||
|
int items;
|
||||||
|
char *user;
|
||||||
|
char *domain;
|
||||||
|
char *host;
|
||||||
|
char *port;
|
||||||
|
char *uri;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int del_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||||
|
{
|
||||||
|
if (argc > 8) {
|
||||||
|
unlink(argv[8]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int play_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||||
|
{
|
||||||
|
switch_file_t *fd;
|
||||||
|
struct holder *holder = (struct holder *) pArg;
|
||||||
|
char *fname, *ext;
|
||||||
|
switch_size_t flen;
|
||||||
|
uint8_t chunk[1024];
|
||||||
|
const char *mime_type = "audio/inline", *new_type;
|
||||||
|
|
||||||
|
if ((fname = strrchr(argv[8], '/'))) {
|
||||||
|
fname++;
|
||||||
|
} else {
|
||||||
|
fname = argv[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ext = strrchr(fname, '.'))) {
|
||||||
|
ext++;
|
||||||
|
if ((new_type = switch_core_mime_ext2type(ext))) {
|
||||||
|
mime_type = new_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_file_open(&fd, argv[8], SWITCH_FOPEN_READ, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, holder->pool) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
flen = switch_file_get_size(fd);
|
||||||
|
holder->stream->write_function(holder->stream, "Content-type: %s\n", mime_type);
|
||||||
|
holder->stream->write_function(holder->stream, "Content-length: %ld\n\n", (long)flen);
|
||||||
|
for(;;) {
|
||||||
|
switch_status_t status;
|
||||||
|
|
||||||
|
flen = sizeof(chunk);
|
||||||
|
status = switch_file_read(fd, chunk, &flen);
|
||||||
|
if (status != SWITCH_STATUS_SUCCESS || flen == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
holder->stream->raw_write_function(holder->stream, chunk, flen);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_file_close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_play(vm_profile_t *profile, char *user, char *domain, char *file, switch_stream_handle_t *stream)
|
||||||
|
{
|
||||||
|
char *sql;
|
||||||
|
struct holder holder;
|
||||||
|
|
||||||
|
sql = switch_mprintf("update voicemail_data set read_epoch=%ld where user='%s' and domain='%s' and file_path like '%%%s'",
|
||||||
|
(long)time(NULL), user, domain, file);
|
||||||
|
|
||||||
|
vm_execute_sql(profile, sql, profile->mutex);
|
||||||
|
free(sql);
|
||||||
|
|
||||||
|
sql = switch_mprintf("select * from voicemail_data where user='%s' and domain='%s' and file_path like '%%%s'", user, domain, file);
|
||||||
|
memset(&holder, 0, sizeof(holder));
|
||||||
|
holder.profile = profile;
|
||||||
|
holder.stream = stream;
|
||||||
|
switch_core_new_memory_pool(&holder.pool);
|
||||||
|
vm_execute_sql_callback(profile, profile->mutex, sql, play_callback, &holder);
|
||||||
|
switch_core_destroy_memory_pool(&holder.pool);
|
||||||
|
switch_safe_free(sql);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void do_del(vm_profile_t *profile, char *user, char *domain, char *file, switch_stream_handle_t *stream)
|
||||||
|
{
|
||||||
|
char *sql;
|
||||||
|
struct holder holder;
|
||||||
|
char *uri, *host, *port;
|
||||||
|
|
||||||
|
host = port = uri = NULL;
|
||||||
|
|
||||||
|
if (stream->event) {
|
||||||
|
host = switch_event_get_header(stream->event, "http-host");
|
||||||
|
port = switch_event_get_header(stream->event, "http-port");
|
||||||
|
uri = switch_event_get_header(stream->event, "http-uri");
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = switch_mprintf("select * from voicemail_data where user='%s' and domain='%s' and file_path like '%%%s'", user, domain, file);
|
||||||
|
memset(&holder, 0, sizeof(holder));
|
||||||
|
holder.profile = profile;
|
||||||
|
holder.stream = stream;
|
||||||
|
vm_execute_sql_callback(profile, profile->mutex, sql, del_callback, &holder);
|
||||||
|
|
||||||
|
switch_safe_free(sql);
|
||||||
|
sql = switch_mprintf("delete from voicemail_data where user='%s' and domain='%s' and file_path like '%%%s'", user, domain, file);
|
||||||
|
vm_execute_sql(profile, sql, profile->mutex);
|
||||||
|
free(sql);
|
||||||
|
|
||||||
|
if (host && port && uri) {
|
||||||
|
stream->write_function(stream,"Content-type: text/html\n\n<h2>Message Deleted</h2>\n"
|
||||||
|
"<META http-equiv=\"refresh\" content=\"1;URL=http://%s:%s%s/rss\">", host, port, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rss_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||||
|
{
|
||||||
|
struct holder *holder = (struct holder *) pArg;
|
||||||
|
switch_xml_t x_tmp, x_link;
|
||||||
|
char *tmp, *del;
|
||||||
|
switch_time_exp_t tm;
|
||||||
|
char create_date[80] = "";
|
||||||
|
char read_date[80] = "";
|
||||||
|
char rss_date[80] = "";
|
||||||
|
switch_size_t retsize;
|
||||||
|
const char *mime_type = "audio/inline", *new_type;
|
||||||
|
char *ext;
|
||||||
|
char *fname;
|
||||||
|
switch_size_t flen;
|
||||||
|
switch_file_t *fd;
|
||||||
|
long l_created = 0;
|
||||||
|
long l_read = 0;
|
||||||
|
long l_duration = 0;
|
||||||
|
switch_core_time_duration_t duration;
|
||||||
|
char duration_str[80];
|
||||||
|
const char *fmt = "%a, %e %b %Y %T %z";
|
||||||
|
char heard[80];
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
l_created = atol(argv[0]) * 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
l_read = atol(argv[1]) * 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 9) {
|
||||||
|
l_duration = atol(argv[9]) * 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_core_measure_time(l_duration, &duration);
|
||||||
|
duration.day += duration.yr * 365;
|
||||||
|
duration.hr += duration.day * 24;
|
||||||
|
|
||||||
|
snprintf(duration_str, sizeof(duration_str), "%.2u:%.2u:%.2u",
|
||||||
|
duration.hr,
|
||||||
|
duration.min,
|
||||||
|
duration.sec
|
||||||
|
);
|
||||||
|
|
||||||
|
if (l_created) {
|
||||||
|
switch_time_exp_lt(&tm, l_created);
|
||||||
|
switch_strftime(create_date, &retsize, sizeof(create_date), fmt, &tm);
|
||||||
|
switch_strftime(rss_date, &retsize, sizeof(create_date), fmt, &tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l_read) {
|
||||||
|
switch_time_exp_lt(&tm, l_read);
|
||||||
|
switch_strftime(read_date, &retsize, sizeof(read_date), fmt, &tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder->x_item = switch_xml_add_child_d(holder->x_channel, "item", holder->items++);
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder->x_item, "title", 0);
|
||||||
|
tmp = switch_mprintf("Message from %s %s on %s", argv[5], argv[6], create_date);
|
||||||
|
switch_xml_set_txt_d(x_tmp, tmp);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder->x_item, "description", 0);
|
||||||
|
|
||||||
|
snprintf(heard, sizeof(heard), switch_strlen_zero(read_date) ? "never" : read_date);
|
||||||
|
|
||||||
|
if ((fname = strrchr(argv[8], '/'))) {
|
||||||
|
fname++;
|
||||||
|
} else {
|
||||||
|
fname = argv[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
del = switch_mprintf("http://%s:%s%s/del/%s", holder->host, holder->port, holder->uri, fname);
|
||||||
|
x_link = switch_xml_add_child_d(holder->x_item, "fsvm:rmlink", 0);
|
||||||
|
switch_xml_set_txt_d(x_link, del);
|
||||||
|
|
||||||
|
|
||||||
|
tmp = switch_mprintf("<![CDATA[Priority: %s<br>Last Heard: %s<br>Duration: %s<br><a href=%s>Delete This Message</a>]]>",
|
||||||
|
strcmp(argv[10], URGENT_FLAG_STRING) ? "normal" : "urgent", heard, duration_str, del);
|
||||||
|
|
||||||
|
|
||||||
|
switch_xml_set_txt_d(x_tmp, tmp);
|
||||||
|
free(tmp);
|
||||||
|
free(del);
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder->x_item, "pubDate", 0);
|
||||||
|
switch_xml_set_txt_d(x_tmp, rss_date);
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder->x_item, "itunes:duration", 0);
|
||||||
|
switch_xml_set_txt_d(x_tmp, duration_str);
|
||||||
|
|
||||||
|
|
||||||
|
tmp = switch_mprintf("http://%s:%s%s/get/%s", holder->host, holder->port, holder->uri, fname);
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder->x_item, "guid", 0);
|
||||||
|
switch_xml_set_txt_d(x_tmp, tmp);
|
||||||
|
|
||||||
|
x_link = switch_xml_add_child_d(holder->x_item, "link", 0);
|
||||||
|
switch_xml_set_txt_d(x_link, tmp);
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder->x_item, "enclosure", 0);
|
||||||
|
switch_xml_set_attr_d(x_tmp, "url", tmp);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (switch_file_open(&fd, argv[8], SWITCH_FOPEN_READ, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, holder->pool) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
flen = switch_file_get_size(fd);
|
||||||
|
tmp = switch_mprintf("%ld", (long) flen);
|
||||||
|
switch_xml_set_attr_d(x_tmp, "length", tmp);
|
||||||
|
free(tmp);
|
||||||
|
switch_file_close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ext = strrchr(fname, '.'))) {
|
||||||
|
ext++;
|
||||||
|
if ((new_type = switch_core_mime_ext2type(ext))) {
|
||||||
|
mime_type = new_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch_xml_set_attr_d(x_tmp, "type", mime_type);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void do_rss(vm_profile_t *profile, char *user, char *domain, char *host, char *port, char *uri, switch_stream_handle_t *stream)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct holder holder;
|
||||||
|
switch_xml_t x_tmp;
|
||||||
|
char *sql, *xmlstr;
|
||||||
|
char *tmp = NULL;
|
||||||
|
|
||||||
|
stream->write_function(stream, "Content-type: text/xml\n\n");
|
||||||
|
memset(&holder, 0, sizeof(holder));
|
||||||
|
holder.profile = profile;
|
||||||
|
holder.stream = stream;
|
||||||
|
holder.xml = switch_xml_new("rss");
|
||||||
|
holder.user = user;
|
||||||
|
holder.domain = domain;
|
||||||
|
holder.host = host;
|
||||||
|
holder.port = port;
|
||||||
|
holder.uri = uri;
|
||||||
|
|
||||||
|
switch_core_new_memory_pool(&holder.pool);
|
||||||
|
assert(holder.xml);
|
||||||
|
|
||||||
|
switch_xml_set_attr_d(holder.xml, "xmlns:itunes", "http://www.itunes.com/dtds/podcast-1.0.dtd");
|
||||||
|
switch_xml_set_attr_d(holder.xml, "xmlns:fsvm", "http://www.freeswitch.org/dtd/fsvm.dtd");
|
||||||
|
switch_xml_set_attr_d(holder.xml, "version", "2.0");
|
||||||
|
holder.x_channel = switch_xml_add_child_d(holder.xml, "channel", 0);
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder.x_channel, "title", 0);
|
||||||
|
tmp = switch_mprintf("FreeSWITCH Voicemail for %s@%s", user, domain);
|
||||||
|
switch_xml_set_txt_d(x_tmp, tmp);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder.x_channel, "link", 0);
|
||||||
|
switch_xml_set_txt_d(x_tmp, "http://www.freeswitch.org");
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder.x_channel, "description", 0);
|
||||||
|
switch_xml_set_txt_d(x_tmp, "http://www.freeswitch.org");
|
||||||
|
|
||||||
|
x_tmp = switch_xml_add_child_d(holder.x_channel, "ttl", 0);
|
||||||
|
switch_xml_set_txt_d(x_tmp, "15");
|
||||||
|
|
||||||
|
|
||||||
|
sql = switch_mprintf("select * from voicemail_data where user='%s' and domain='%s' order by read_flags", user, domain);
|
||||||
|
vm_execute_sql_callback(profile, profile->mutex, sql, rss_callback, &holder);
|
||||||
|
|
||||||
|
xmlstr = switch_xml_toxml(holder.xml);
|
||||||
|
|
||||||
|
stream->write_function(stream, "%s", xmlstr);
|
||||||
|
|
||||||
|
switch_safe_free(sql);
|
||||||
|
switch_safe_free(xmlstr);
|
||||||
|
switch_xml_free(holder.xml);
|
||||||
|
switch_core_destroy_memory_pool(&holder.pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_STANDARD_API(voicemail_api_function)
|
||||||
|
{
|
||||||
|
int argc = 0;
|
||||||
|
char *mydata = NULL, *argv[6];
|
||||||
|
char *host = NULL, *port = NULL, *uri = NULL;
|
||||||
|
char *user = NULL, *domain = NULL;
|
||||||
|
int ct = 0;
|
||||||
|
vm_profile_t *profile = NULL;
|
||||||
|
char *path_info = NULL;
|
||||||
|
int rss = 0, xarg = 0;
|
||||||
|
|
||||||
|
if (stream->event) {
|
||||||
|
host = switch_event_get_header(stream->event, "http-host");
|
||||||
|
port = switch_event_get_header(stream->event, "http-port");
|
||||||
|
uri = switch_event_get_header(stream->event, "http-uri");
|
||||||
|
user = switch_event_get_header(stream->event, "freeswitch-user");
|
||||||
|
domain = switch_event_get_header(stream->event, "freeswitch-domain");
|
||||||
|
path_info = switch_event_get_header(stream->event, "http-path-info");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!switch_strlen_zero(cmd)) {
|
||||||
|
mydata = strdup(cmd);
|
||||||
|
assert(mydata);
|
||||||
|
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
if (!strcasecmp(argv[0], "rss")) {
|
||||||
|
rss++;
|
||||||
|
xarg++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!host) {
|
||||||
|
if (argc - rss < 5) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
host = argv[xarg++];
|
||||||
|
port = argv[xarg++];
|
||||||
|
uri = argv[xarg++];
|
||||||
|
user = argv[xarg++];
|
||||||
|
domain = argv[xarg++];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(host && port && uri && user && domain)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile = switch_core_hash_find(globals.profile_hash, domain);
|
||||||
|
|
||||||
|
if (!profile) {
|
||||||
|
profile = switch_core_hash_find(globals.profile_hash, "default");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!profile) {
|
||||||
|
switch_hash_index_t *hi;
|
||||||
|
void *val;
|
||||||
|
|
||||||
|
for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
|
||||||
|
switch_hash_this(hi, NULL, NULL, &val);
|
||||||
|
profile = (vm_profile_t *) val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!profile) {
|
||||||
|
stream->write_function(stream, "Can't find profile.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (path_info) {
|
||||||
|
if (!strncasecmp(path_info, "get/", 4)) {
|
||||||
|
do_play(profile, user, domain, path_info + 4, stream);
|
||||||
|
} else if (!strncasecmp(path_info, "del/", 4)) {
|
||||||
|
do_del(profile, user, domain, path_info + 4, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rss || (path_info && !strncasecmp(path_info, "rss", 3))) {
|
||||||
|
do_rss(profile, user, domain, host, port, uri, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (host) {
|
||||||
|
if (!ct) {
|
||||||
|
stream->write_function(stream, "Content-type: text/html\n\n<h2>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream->write_function(stream, "Error: %s\n", VOICEMAIL_SYNTAX);
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
switch_safe_free(mydata);
|
||||||
|
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SWITCH_MODULE_LOAD_FUNCTION(mod_voicemail_load)
|
SWITCH_MODULE_LOAD_FUNCTION(mod_voicemail_load)
|
||||||
{
|
{
|
||||||
switch_application_interface_t *app_interface;
|
switch_application_interface_t *app_interface;
|
||||||
|
switch_api_interface_t *commands_api_interface;
|
||||||
switch_status_t status;
|
switch_status_t status;
|
||||||
|
|
||||||
if ((status = load_config()) != SWITCH_STATUS_SUCCESS) {
|
if ((status = load_config()) != SWITCH_STATUS_SUCCESS) {
|
||||||
@ -2137,6 +2551,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_voicemail_load)
|
|||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
|
||||||
return SWITCH_STATUS_GENERR;
|
return SWITCH_STATUS_GENERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SWITCH_ADD_API(commands_api_interface, "voicemail", "voicemail", voicemail_api_function, VOICEMAIL_SYNTAX);
|
||||||
|
|
||||||
/* indicate that the module should continue to be loaded */
|
/* indicate that the module should continue to be loaded */
|
||||||
return SWITCH_STATUS_NOUNLOAD;
|
return SWITCH_STATUS_NOUNLOAD;
|
||||||
|
@ -3339,7 +3339,16 @@ static void js_thread_launch(const char *text)
|
|||||||
SWITCH_STANDARD_API(jsapi_function)
|
SWITCH_STANDARD_API(jsapi_function)
|
||||||
{
|
{
|
||||||
struct request_obj ro = {0};
|
struct request_obj ro = {0};
|
||||||
|
char *path_info = NULL;
|
||||||
|
|
||||||
|
if (stream->event) {
|
||||||
|
path_info = switch_event_get_header(stream->event, "http-path-info");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_strlen_zero(cmd) && path_info) {
|
||||||
|
cmd = path_info;
|
||||||
|
}
|
||||||
|
|
||||||
if (switch_strlen_zero(cmd)) {
|
if (switch_strlen_zero(cmd)) {
|
||||||
stream->write_function(stream, "USAGE: %s\n", jsapi_interface.syntax);
|
stream->write_function(stream, "USAGE: %s\n", jsapi_interface.syntax);
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
#include <switch_version.h>
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(disable:4142)
|
#pragma warning(disable:4142)
|
||||||
#endif
|
#endif
|
||||||
@ -117,6 +118,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_xml_rpc_load)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static switch_status_t http_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen)
|
||||||
|
{
|
||||||
|
TSession *r = handle->data;
|
||||||
|
|
||||||
|
return HTTPWrite(r, (char *)data, (uint32_t) datalen) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static switch_status_t http_stream_write(switch_stream_handle_t *handle, const char *fmt, ...)
|
static switch_status_t http_stream_write(switch_stream_handle_t *handle, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@ -146,7 +155,8 @@ static abyss_bool http_directory_auth(TSession *r, char *domain_name)
|
|||||||
char *pass;
|
char *pass;
|
||||||
const char *mypass1 = NULL, *mypass2 = NULL;
|
const char *mypass1 = NULL, *mypass2 = NULL;
|
||||||
switch_xml_t x_domain, x_domain_root = NULL, x_user, x_params, x_param;
|
switch_xml_t x_domain, x_domain_root = NULL, x_user, x_params, x_param;
|
||||||
|
const char *box;
|
||||||
|
|
||||||
p = RequestHeaderValue(r, "authorization");
|
p = RequestHeaderValue(r, "authorization");
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
@ -162,16 +172,21 @@ static abyss_bool http_directory_auth(TSession *r, char *domain_name)
|
|||||||
*pass++ = '\0';
|
*pass++ = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switch_xml_locate_user(user, domain_name, NULL, &x_domain_root, &x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) {
|
if (switch_xml_locate_user(user, domain_name, NULL, &x_domain_root, &x_domain, &x_user, "mailbox=check") != SWITCH_STATUS_SUCCESS) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain_name);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain_name);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResponseAddField(r, "freeswitch-user", user);
|
||||||
|
ResponseAddField(r, "freeswitch-domain", domain_name);
|
||||||
|
|
||||||
|
box = switch_xml_attr_soft(x_user, "mailbox");
|
||||||
|
|
||||||
if (!(x_params = switch_xml_child(x_user, "params"))) {
|
if (!(x_params = switch_xml_child(x_user, "params"))) {
|
||||||
goto authed;
|
goto authed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
|
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
|
||||||
const char *var = switch_xml_attr_soft(x_param, "name");
|
const char *var = switch_xml_attr_soft(x_param, "name");
|
||||||
const char *val = switch_xml_attr_soft(x_param, "value");
|
const char *val = switch_xml_attr_soft(x_param, "value");
|
||||||
@ -184,23 +199,53 @@ static abyss_bool http_directory_auth(TSession *r, char *domain_name)
|
|||||||
ResponseAddField(r, (char *)var, (char *)val);
|
ResponseAddField(r, (char *)var, (char *)val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(z, "%s:%s", user, mypass1);
|
|
||||||
Base64Encode(z, t);
|
|
||||||
|
|
||||||
if (!strcmp(p, t)) {
|
if (!(mypass1 && mypass2)) {
|
||||||
r->user=strdup(user);
|
r->user=strdup(user);
|
||||||
goto authed;
|
goto authed;
|
||||||
}
|
} else {
|
||||||
|
if (mypass1) {
|
||||||
|
sprintf(z, "%s:%s", user, mypass1);
|
||||||
|
Base64Encode(z, t);
|
||||||
|
|
||||||
|
if (!strcmp(p, t)) {
|
||||||
|
r->user=strdup(user);
|
||||||
|
goto authed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sprintf(z, "%s:%s", user, mypass2);
|
if (mypass2) {
|
||||||
Base64Encode(z, t);
|
sprintf(z, "%s:%s", user, mypass2);
|
||||||
|
Base64Encode(z, t);
|
||||||
|
|
||||||
if (!strcmp(p, t)) {
|
if (!strcmp(p, t)) {
|
||||||
r->user=strdup(user);
|
r->user=strdup(user);
|
||||||
goto authed;
|
goto authed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (box) {
|
||||||
|
if (mypass1) {
|
||||||
|
sprintf(z, "%s:%s", box, mypass1);
|
||||||
|
Base64Encode(z, t);
|
||||||
|
|
||||||
|
if (!strcmp(p, t)) {
|
||||||
|
r->user=strdup(box);
|
||||||
|
goto authed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mypass2) {
|
||||||
|
sprintf(z, "%s:%s", box, mypass2);
|
||||||
|
Base64Encode(z, t);
|
||||||
|
|
||||||
|
if (!strcmp(p, t)) {
|
||||||
|
r->user=strdup(box);
|
||||||
|
goto authed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
||||||
@ -242,15 +287,64 @@ abyss_bool auth_hook(TSession * r)
|
|||||||
*e++ = '\0';
|
*e++ = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(domain_name, "this")) {
|
||||||
|
free(domain_name);
|
||||||
|
domain_name = strdup(r->host);
|
||||||
|
}
|
||||||
|
|
||||||
ret = !http_directory_auth(r, domain_name);
|
ret = !http_directory_auth(r, domain_name);
|
||||||
|
|
||||||
free(domain_name);
|
free(domain_name);
|
||||||
} else {
|
} else {
|
||||||
if (globals.realm) {
|
char tmp[512];
|
||||||
if (!RequestAuth(r, globals.realm, globals.user, globals.pass)) {
|
const char *list[2] = {"index.html", "index.txt"};
|
||||||
ret = TRUE;
|
int x;
|
||||||
|
|
||||||
|
if (!strncmp(r->uri, "/pub", 4)) {
|
||||||
|
char *p = r->uri;
|
||||||
|
char *new_uri = p + 4;
|
||||||
|
if (!new_uri) {
|
||||||
|
new_uri = "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s%s",
|
||||||
|
SWITCH_GLOBAL_dirs.htdocs_dir,
|
||||||
|
new_uri
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if (switch_directory_exists(tmp, NULL) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
for (x = 0; x < 2; x++) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s%s%s%s",
|
||||||
|
SWITCH_GLOBAL_dirs.htdocs_dir,
|
||||||
|
new_uri,
|
||||||
|
end_of(new_uri) == *SWITCH_PATH_SEPARATOR ? "" : SWITCH_PATH_SEPARATOR,
|
||||||
|
list[x]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (switch_file_exists(tmp, NULL) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s%s%s",
|
||||||
|
new_uri,
|
||||||
|
end_of(new_uri) == '/' ? "" : "/",
|
||||||
|
list[x]
|
||||||
|
);
|
||||||
|
new_uri = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r->uri = strdup(new_uri);
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (globals.realm && strncmp(r->uri, "/pub", 4)) {
|
||||||
|
if (!RequestAuth(r, globals.realm, globals.user, globals.pass)) {
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -265,56 +359,71 @@ abyss_bool handler_hook(TSession * r)
|
|||||||
int i, j = 0;
|
int i, j = 0;
|
||||||
TTableItem *ti;
|
TTableItem *ti;
|
||||||
char *dup = NULL;
|
char *dup = NULL;
|
||||||
|
int auth = 0;
|
||||||
|
char *fs_user = NULL, *fs_domain = NULL;
|
||||||
|
char *path_info = NULL;
|
||||||
|
abyss_bool ret = TRUE;
|
||||||
|
|
||||||
stream.data = r;
|
stream.data = r;
|
||||||
stream.write_function = http_stream_write;
|
stream.write_function = http_stream_write;
|
||||||
|
stream.raw_write_function = http_stream_raw_write;
|
||||||
|
|
||||||
if ((command = strstr(r->uri, "/api/"))) {
|
if ((command = strstr(r->uri, "/api/"))) {
|
||||||
command += 5;
|
command += 5;
|
||||||
} else {
|
} else {
|
||||||
return FALSE;
|
ret = FALSE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((path_info = strchr(command, '/'))) {
|
||||||
|
*path_info++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(r->uri, "/domains/", 9)) {
|
||||||
|
goto auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0;i<r->response_headers.size;i++) {
|
for (i=0;i<r->response_headers.size;i++) {
|
||||||
ti=&r->response_headers.item[i];
|
ti=&r->response_headers.item[i];
|
||||||
if (!strcasecmp(ti->name, "http-allowed-api")) {
|
if (!strcasecmp(ti->name, "freeswitch-user")) {
|
||||||
|
fs_user = ti->value;
|
||||||
|
} else if (!strcasecmp(ti->name, "freeswitch-domain")) {
|
||||||
|
fs_domain = ti->value;
|
||||||
|
} else if (!strcasecmp(ti->name, "http-allowed-api")) {
|
||||||
int argc, x;
|
int argc, x;
|
||||||
char *argv[256] = { 0 };
|
char *argv[256] = { 0 };
|
||||||
j++;
|
j++;
|
||||||
|
|
||||||
if (!strcasecmp(ti->value, "any")) {
|
if (!strcasecmp(ti->value, "any")) {
|
||||||
goto auth;
|
auth++;
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcasecmp(ti->value, "none")) {
|
|
||||||
goto unauth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dup = strdup(ti->value);
|
dup = strdup(ti->value);
|
||||||
argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
|
argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||||
|
|
||||||
for (x = 0; x < argc; x++) {
|
for (x = 0; x < argc; x++) {
|
||||||
if (!strcasecmp(command, argv[x])) {
|
if (!strcasecmp(command, argv[x])) {
|
||||||
goto auth;
|
auth++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
goto unauth;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r->user && !j) {
|
if (!switch_strlen_zero(r->user) && !j) {
|
||||||
goto unauth;
|
auth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth) {
|
||||||
|
goto auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto auth;
|
//unauth:
|
||||||
|
|
||||||
unauth:
|
|
||||||
ResponseStatus(r, 403);
|
ResponseStatus(r, 403);
|
||||||
ResponseError(r);
|
ResponseError(r);
|
||||||
switch_safe_free(dup);
|
switch_safe_free(dup);
|
||||||
|
|
||||||
return TRUE;
|
ret = TRUE;
|
||||||
|
goto end;
|
||||||
|
|
||||||
auth:
|
auth:
|
||||||
|
|
||||||
@ -322,7 +431,12 @@ abyss_bool handler_hook(TSession * r)
|
|||||||
if (switch_event_create(&stream.event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
|
if (switch_event_create(&stream.event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
|
||||||
const char * const content_length = RequestHeaderValue(r, "content-length");
|
const char * const content_length = RequestHeaderValue(r, "content-length");
|
||||||
|
|
||||||
|
if (fs_user)
|
||||||
|
switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", "%s", fs_user);
|
||||||
|
if (fs_domain)
|
||||||
|
switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", "%s", fs_domain);
|
||||||
|
if (path_info)
|
||||||
|
switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", "%s", path_info);
|
||||||
if (r->uri)
|
if (r->uri)
|
||||||
switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "HTTP-URI", "%s", r->uri);
|
switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "HTTP-URI", "%s", r->uri);
|
||||||
if (r->query)
|
if (r->query)
|
||||||
@ -434,7 +548,7 @@ abyss_bool handler_hook(TSession * r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Generation of the server field */
|
/* Generation of the server field */
|
||||||
ResponseAddField(r,"Server", SERVER_HVERSION);
|
ResponseAddField(r,"Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc");
|
||||||
|
|
||||||
for (i=0;i<r->response_headers.size;i++) {
|
for (i=0;i<r->response_headers.size;i++) {
|
||||||
ti=&r->response_headers.item[i];
|
ti=&r->response_headers.item[i];
|
||||||
@ -453,7 +567,10 @@ abyss_bool handler_hook(TSession * r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//HTTPWriteEnd(r);
|
//HTTPWriteEnd(r);
|
||||||
return TRUE;
|
|
||||||
|
end:
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -364,6 +364,28 @@ SWITCH_DECLARE(switch_size_t) switch_file_get_size(switch_file_t *thefile)
|
|||||||
return apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile) == SWITCH_STATUS_SUCCESS ? (switch_size_t)finfo.size : 0;
|
return apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile) == SWITCH_STATUS_SUCCESS ? (switch_size_t)finfo.size : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_directory_exists(const char *dirname, switch_memory_pool_t *pool)
|
||||||
|
{
|
||||||
|
apr_dir_t *dir_handle;
|
||||||
|
switch_memory_pool_t *our_pool = NULL;
|
||||||
|
switch_status_t status;
|
||||||
|
|
||||||
|
if (!pool) {
|
||||||
|
switch_core_new_memory_pool(&our_pool);
|
||||||
|
pool = our_pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status = apr_dir_open(&dir_handle, dirname, pool)) == APR_SUCCESS) {
|
||||||
|
apr_dir_close(dir_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (our_pool) {
|
||||||
|
switch_core_destroy_memory_pool(&our_pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_file_exists(const char *filename, switch_memory_pool_t *pool)
|
SWITCH_DECLARE(switch_status_t) switch_file_exists(const char *filename, switch_memory_pool_t *pool)
|
||||||
{
|
{
|
||||||
int32_t wanted = APR_FINFO_TYPE;
|
int32_t wanted = APR_FINFO_TYPE;
|
||||||
|
@ -34,6 +34,17 @@
|
|||||||
#include <switch_version.h>
|
#include <switch_version.h>
|
||||||
#define CMD_BUFLEN 1024;
|
#define CMD_BUFLEN 1024;
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_console_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen)
|
||||||
|
{
|
||||||
|
FILE *out = switch_core_get_console();
|
||||||
|
|
||||||
|
if (out) {
|
||||||
|
fwrite(data, datalen, 1, out);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_console_stream_write(switch_stream_handle_t *handle, const char *fmt, ...)
|
SWITCH_DECLARE(switch_status_t) switch_console_stream_write(switch_stream_handle_t *handle, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -551,6 +551,9 @@ SWITCH_DECLARE(void) switch_core_runtime_loop(int bg)
|
|||||||
|
|
||||||
SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext)
|
SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext)
|
||||||
{
|
{
|
||||||
|
if (!ext) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return (const char *) switch_core_hash_find(runtime.mime_types, ext);
|
return (const char *) switch_core_hash_find(runtime.mime_types, ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1457,7 +1457,8 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_cfg(const char *file_path, switch_x
|
|||||||
static char *switch_xml_ampencode(const char *s, switch_size_t len, char **dst, switch_size_t *dlen, switch_size_t *max, short a)
|
static char *switch_xml_ampencode(const char *s, switch_size_t len, char **dst, switch_size_t *dlen, switch_size_t *max, short a)
|
||||||
{
|
{
|
||||||
const char *e = NULL;
|
const char *e = NULL;
|
||||||
|
int immune = 0;
|
||||||
|
|
||||||
if (len) {
|
if (len) {
|
||||||
e = s + len;
|
e = s + len;
|
||||||
}
|
}
|
||||||
@ -1466,13 +1467,24 @@ static char *switch_xml_ampencode(const char *s, switch_size_t len, char **dst,
|
|||||||
while (*dlen + 10 > *max)
|
while (*dlen + 10 > *max)
|
||||||
*dst = (char *)realloc(*dst, *max += SWITCH_XML_BUFSIZE);
|
*dst = (char *)realloc(*dst, *max += SWITCH_XML_BUFSIZE);
|
||||||
|
|
||||||
switch (*s) {
|
if (immune) {
|
||||||
|
if (*s == '\0') {
|
||||||
|
return *dst;
|
||||||
|
}
|
||||||
|
(*dst)[(*dlen)++] = *s;
|
||||||
|
} else
|
||||||
|
switch (*s) {
|
||||||
case '\0':
|
case '\0':
|
||||||
return *dst;
|
return *dst;
|
||||||
case '&':
|
case '&':
|
||||||
*dlen += sprintf(*dst + *dlen, "&");
|
*dlen += sprintf(*dst + *dlen, "&");
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
|
if (*(s+1) == '!') {
|
||||||
|
(*dst)[(*dlen)++] = *s;
|
||||||
|
immune++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
*dlen += sprintf(*dst + *dlen, "<");
|
*dlen += sprintf(*dst + *dlen, "<");
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user