Thu Jul 9 13:41:24 2009

Asterisk developer's documentation


manager.c File Reference

The Asterisk Management Interface - AMI. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <ctype.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/mman.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/manager.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "asterisk/tcptls.h"
#include "asterisk/http.h"
#include "asterisk/ast_version.h"
#include "asterisk/threadstorage.h"
#include "asterisk/linkedlists.h"
#include "asterisk/version.h"
#include "asterisk/term.h"
#include "asterisk/astobj2.h"

Go to the source code of this file.

Data Structures

struct  actions
 list of actions registered More...
struct  all_events
struct  ast_manager_user
 user descriptor, as read from the config file. More...
struct  eventqent
struct  fast_originate_helper
 helper function for originate More...
struct  manager_hooks
 list of hooks registered More...
struct  mansession
struct  mansession_session
struct  permalias
struct  sessions
struct  users
 list of users found in the config file More...
struct  variable_count

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
 initial allocated size for the astman_append_buf
#define HSMC_FORMAT   " %-15.15s %-15.15s %-55.55s\n"
#define HSMCONN_FORMAT1   " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n"
#define HSMCONN_FORMAT2   " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n"
#define MANAGER_EVENT_BUF_INITSIZE   256
#define MAX_BLACKLIST_CMD_LEN   2
 Descriptor for a manager session, either on the AMI socket or over HTTP.
#define MSG_MOREDATA   ((char *)astman_send_response)
 send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.
#define NEW_EVENT(m)   (AST_LIST_NEXT(m->session->last_ev, eq_next))
#define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
#define TEST_STRING   "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ <input type=\"submit\"></form>"

Enumerations

enum  error_type {
  UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT,
  FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT,
  FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND
}
enum  output_format { FORMAT_RAW, FORMAT_HTML, FORMAT_XML }

Functions

static void __init_astman_append_buf (void)
 thread local buffer for astman_append
static int __init_manager (int reload)
static void __init_manager_event_buf (void)
static void __init_userevent_buf (void)
int __manager_event (int category, const char *event, const char *file, int line, const char *func, const char *fmt,...)
 manager_event: Send AMI event to client
static int action_challenge (struct mansession *s, const struct message *m)
static int action_command (struct mansession *s, const struct message *m)
 Manager command "command" - execute CLI command.
static int action_coresettings (struct mansession *s, const struct message *m)
 Show PBX core settings information.
static int action_coreshowchannels (struct mansession *s, const struct message *m)
 Manager command "CoreShowChannels" - List currently defined channels and some information about them.
static int action_corestatus (struct mansession *s, const struct message *m)
 Show PBX core status information.
static int action_createconfig (struct mansession *s, const struct message *m)
static int action_events (struct mansession *s, const struct message *m)
static int action_extensionstate (struct mansession *s, const struct message *m)
static int action_getconfig (struct mansession *s, const struct message *m)
static int action_getconfigjson (struct mansession *s, const struct message *m)
static int action_getvar (struct mansession *s, const struct message *m)
static int action_hangup (struct mansession *s, const struct message *m)
static int action_listcategories (struct mansession *s, const struct message *m)
static int action_listcommands (struct mansession *s, const struct message *m)
static int action_login (struct mansession *s, const struct message *m)
static int action_logoff (struct mansession *s, const struct message *m)
static int action_mailboxcount (struct mansession *s, const struct message *m)
static int action_mailboxstatus (struct mansession *s, const struct message *m)
static int action_originate (struct mansession *s, const struct message *m)
static int action_ping (struct mansession *s, const struct message *m)
static int action_redirect (struct mansession *s, const struct message *m)
 action_redirect: The redirect manager command
static int action_reload (struct mansession *s, const struct message *m)
 Send a reload event.
static int action_sendtext (struct mansession *s, const struct message *m)
static int action_setvar (struct mansession *s, const struct message *m)
static int action_status (struct mansession *s, const struct message *m)
 Manager "status" command to show channels.
static int action_timeout (struct mansession *s, const struct message *m)
static int action_updateconfig (struct mansession *s, const struct message *m)
static int action_userevent (struct mansession *s, const struct message *m)
static int action_waitevent (struct mansession *s, const struct message *m)
static int append_event (const char *str, int category)
static int ast_instring (const char *bigstr, const char *smallstr, const char delim)
int ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description)
 Register a manager command with the manager interface.
void ast_manager_register_hook (struct manager_custom_hook *hook)
 Add a custom hook to be called when an event is fired.
static int ast_manager_register_struct (struct manager_action *act)
int ast_manager_unregister (char *action)
 Unregister a registered manager command.
void ast_manager_unregister_hook (struct manager_custom_hook *hook)
 Delete a custom hook to be called when an event is fired.
void astman_append (struct mansession *s, const char *fmt,...)
const char * astman_get_header (const struct message *m, char *var)
 Get header from mananger transaction.
ast_variableastman_get_variables (const struct message *m)
 Get a linked list of the Variable: headers.
int astman_is_authed (uint32_t ident)
 Determinie if a manager session ident is authenticated.
void astman_send_ack (struct mansession *s, const struct message *m, char *msg)
 Send ack in manager transaction.
void astman_send_error (struct mansession *s, const struct message *m, char *error)
 Send error in manager transaction.
void astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag)
 Send ack in manager list transaction.
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
 Send response in manager transaction.
static void astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
static void astman_start_ack (struct mansession *s, const struct message *m)
int astman_verify_session_readpermissions (uint32_t ident, int perm)
 Verify a session's read permissions against a permission mask.
int astman_verify_session_writepermissions (uint32_t ident, int perm)
 Verify a session's write permissions against a permission mask.
static int authenticate (struct mansession *s, const struct message *m)
static char * authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options.
static int check_blacklist (const char *cmd)
int check_manager_enabled ()
 Check if AMI is enabled.
static int check_manager_session_inuse (const char *name)
int check_webmanager_enabled ()
 Check if AMI/HTTP is enabled.
static int compress_char (char c)
static void destroy_session (struct mansession_session *session)
static int do_message (struct mansession *s)
static void * fast_originate (void *data)
static struct mansession_sessionfind_session (uint32_t ident, int incinuse)
static void free_session (struct mansession_session *session)
static struct ast_strgeneric_http_callback (enum output_format format, struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
static int get_input (struct mansession *s, char *output)
static struct ast_manager_userget_manager_by_name_locked (const char *name)
static int get_perm (const char *instr)
static struct eventqentgrab_last (void)
static char * handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager reload.
static char * handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list commands.
static char * handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list connected.
static char * handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list eventq.
static enum error_type handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
int init_manager (void)
 Called by Asterisk initialization.
static void json_escape (char *out, const char *in)
static int manager_displayconnects (struct mansession_session *session)
 Get displayconnects config option.
static struct ast_strmanager_http_callback (struct ast_tcptls_session_instance *ser, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
static int manager_modulecheck (struct mansession *s, const struct message *m)
static int manager_moduleload (struct mansession *s, const struct message *m)
static int manager_state_cb (char *context, char *exten, int state, void *data)
static struct ast_strmxml_http_callback (struct ast_tcptls_session_instance *ser, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
static int process_events (struct mansession *s)
static int process_message (struct mansession *s, const struct message *m)
static void purge_events (void)
static void purge_old_stuff (void *data)
 cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most
static void purge_sessions (int n_max)
 remove at most n_max stale session from the list.
static struct ast_strrawman_http_callback (struct ast_tcptls_session_instance *ser, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
static void ref_event (struct eventqent *e)
int reload_manager (void)
 Called by Asterisk module functions and the CLI command.
static int send_string (struct mansession *s, char *string)
static void * session_do (void *data)
 The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).
static int set_eventmask (struct mansession *s, const char *eventmask)
 Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.
static int strings_to_mask (const char *string)
static struct eventqentunref_event (struct eventqent *e)
static int variable_count_cmp_fn (void *obj, void *vstr, int flags)
static int variable_count_hash_fn (const void *vvc, const int flags)
static void xml_copy_escape (struct ast_str **out, const char *src, int mode)
static void xml_translate (struct ast_str **out, char *in, struct ast_variable *vars, enum output_format format)
 Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'.

Variables

static int allowmultiplelogin = 1
static struct server_args ami_desc
ast_tls_config ami_tls_cfg
static struct server_args amis_desc
static struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_astman_append_buf , .custom_init = NULL , }
static int block_sockets
static struct ast_cli_entry cli_manager []
struct {
   char *   words [AST_MAX_CMD_LEN]
command_blacklist []
static char * contenttype []
static int displayconnects = 1
static int httptimeout = 60
static int manager_debug
static int manager_enabled = 0
static struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_manager_event_buf , .custom_init = NULL , }
ast_http_uri manageruri
ast_http_uri managerxmluri
static char mandescr_command []
static char mandescr_coresettings []
static char mandescr_coreshowchannels []
static char mandescr_corestatus []
static char mandescr_createconfig []
static char mandescr_events []
static char mandescr_extensionstate []
static char mandescr_getconfig []
static char mandescr_getconfigjson []
static char mandescr_getvar []
static char mandescr_hangup []
static char mandescr_listcategories []
static char mandescr_listcommands []
static char mandescr_logoff []
static char mandescr_mailboxcount []
static char mandescr_mailboxstatus []
 Help text for manager command mailboxstatus.
static char mandescr_modulecheck []
static char mandescr_moduleload []
static char mandescr_originate []
static char mandescr_ping []
 Manager PING.
static char mandescr_redirect []
static char mandescr_reload []
static char mandescr_sendtext []
static char mandescr_setvar []
static char mandescr_timeout []
static char mandescr_updateconfig []
static char mandescr_userevent []
static char mandescr_waitevent []
 Manager WAITEVENT.
static int num_sessions
static struct permalias perms []
ast_http_uri rawmanuri
static int registered = 0
static int timestampevents
static struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_userevent_buf , .custom_init = NULL , }
static int webmanager_enabled = 0
static int webregged = 0


Detailed Description

The Asterisk Management Interface - AMI.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
OpenSSL http://www.openssl.org - for AMI/SSL
At the moment this file contains a number of functions, namely:

manager.conf

Definition in file manager.c.


Define Documentation

#define HSMC_FORMAT   " %-15.15s %-15.15s %-55.55s\n"

Referenced by handle_showmancmds().

#define HSMCONN_FORMAT1   " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n"

Referenced by handle_showmanconn().

#define HSMCONN_FORMAT2   " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n"

Referenced by handle_showmanconn().

#define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"

#define TEST_STRING   "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ <input type=\"submit\"></form>"


Enumeration Type Documentation

enum output_format

END Doxygen group

Enumerator:
FORMAT_RAW 
FORMAT_HTML 
FORMAT_XML 

Definition at line 3246 of file manager.c.

03246                    {
03247    FORMAT_RAW,
03248    FORMAT_HTML,
03249    FORMAT_XML,
03250 };


Function Documentation

static int __init_manager ( int  reload  )  [static]

Definition at line 3798 of file manager.c.

References action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_listcommands(), action_login(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), ahp, ami_desc, ami_tls_cfg, amis_desc, append_event(), AST_CERTFILE, ast_cli_register_multiple(), ast_config_load, ast_extension_state_add(), ast_free, ast_gethostbyname(), ast_log(), ast_manager_register, ast_manager_register2(), ast_strdup, ast_true(), ast_variable_browse(), ast_tls_config::certfile, ast_tls_config::cipher, cli_manager, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MANAGER_PORT, ast_tls_config::enabled, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_ORIGINATE, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, hp, inet_aton(), LOG_NOTICE, LOG_WARNING, manager_modulecheck(), manager_moduleload(), manager_state_cb(), mandescr_createconfig, mandescr_getconfig, mandescr_getconfigjson, mandescr_listcategories, mandescr_ping, mandescr_updateconfig, mandescr_waitevent, server_args::sin, and var.

Referenced by init_manager(), and reload_manager().

03799 {
03800    struct ast_config *ucfg = NULL, *cfg = NULL;
03801    const char *val;
03802    char *cat = NULL;
03803    int newhttptimeout = 60;
03804    int have_sslbindaddr = 0;
03805    struct hostent *hp;
03806    struct ast_hostent ahp;
03807    struct ast_manager_user *user = NULL;
03808    struct ast_variable *var;
03809    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
03810 
03811    manager_enabled = 0;
03812 
03813    if (!registered) {
03814       /* Register default actions */
03815       ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
03816       ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
03817       ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
03818       ast_manager_register2("Login", 0, action_login, "Login Manager", NULL);
03819       ast_manager_register2("Challenge", 0, action_challenge, "Generate Challenge for MD5 Auth", NULL);
03820       ast_manager_register2("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
03821       ast_manager_register("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status, "Lists channel status" );
03822       ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
03823       ast_manager_register2("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar, "Gets a Channel Variable", mandescr_getvar );
03824       ast_manager_register2("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
03825       ast_manager_register2("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson, "Retrieve configuration (JSON format)", mandescr_getconfigjson);
03826       ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
03827       ast_manager_register2("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig, "Creates an empty file in the configuration directory", mandescr_createconfig);
03828       ast_manager_register2("ListCategories", EVENT_FLAG_CONFIG, action_listcategories, "List categories in configuration file", mandescr_listcategories);
03829       ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
03830       ast_manager_register2("Originate", EVENT_FLAG_ORIGINATE, action_originate, "Originate Call", mandescr_originate);
03831       ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
03832       ast_manager_register2("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
03833       ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
03834       ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
03835       ast_manager_register2("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
03836       ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
03837       ast_manager_register2("SendText", EVENT_FLAG_CALL, action_sendtext, "Send text message to channel", mandescr_sendtext);
03838       ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
03839       ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
03840       ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings);
03841       ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus, "Show PBX core status variables", mandescr_corestatus);
03842       ast_manager_register2("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload, "Send a reload event", mandescr_reload);
03843       ast_manager_register2("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels, "List currently active channels", mandescr_coreshowchannels);
03844       ast_manager_register2("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload, "Module management", mandescr_moduleload);
03845       ast_manager_register2("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck, "Check if module is loaded", mandescr_modulecheck);
03846 
03847       ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
03848       ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
03849       registered = 1;
03850       /* Append placeholder event so master_eventq never runs dry */
03851       append_event("Event: Placeholder\r\n\r\n", 0);
03852    }
03853    if ((cfg = ast_config_load("manager.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
03854       return 0;
03855 
03856    displayconnects = 1;
03857    if (!cfg) {
03858       ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf. Asterisk management interface (AMI) disabled.\n");
03859       return 0;
03860    }
03861 
03862    /* default values */
03863    memset(&ami_desc.sin, 0, sizeof(struct sockaddr_in));
03864    memset(&amis_desc.sin, 0, sizeof(amis_desc.sin));
03865    amis_desc.sin.sin_port = htons(5039);
03866    ami_desc.sin.sin_port = htons(DEFAULT_MANAGER_PORT);
03867 
03868    ami_tls_cfg.enabled = 0;
03869    if (ami_tls_cfg.certfile)
03870       ast_free(ami_tls_cfg.certfile);
03871    ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
03872    if (ami_tls_cfg.cipher)
03873       ast_free(ami_tls_cfg.cipher);
03874    ami_tls_cfg.cipher = ast_strdup("");
03875 
03876    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
03877       val = var->value;
03878       if (!strcasecmp(var->name, "sslenable"))
03879          ami_tls_cfg.enabled = ast_true(val);
03880       else if (!strcasecmp(var->name, "sslbindport"))
03881          amis_desc.sin.sin_port = htons(atoi(val));
03882       else if (!strcasecmp(var->name, "sslbindaddr")) {
03883          if ((hp = ast_gethostbyname(val, &ahp))) {
03884             memcpy(&amis_desc.sin.sin_addr, hp->h_addr, sizeof(amis_desc.sin.sin_addr));
03885             have_sslbindaddr = 1;
03886          } else {
03887             ast_log(LOG_WARNING, "Invalid bind address '%s'\n", val);
03888          }
03889       } else if (!strcasecmp(var->name, "sslcert")) {
03890          ast_free(ami_tls_cfg.certfile);
03891          ami_tls_cfg.certfile = ast_strdup(val);
03892       } else if (!strcasecmp(var->name, "sslcipher")) {
03893          ast_free(ami_tls_cfg.cipher);
03894          ami_tls_cfg.cipher = ast_strdup(val);
03895       } else if (!strcasecmp(var->name, "enabled")) {
03896          manager_enabled = ast_true(val);
03897       } else if (!strcasecmp(var->name, "block-sockets")) {
03898          block_sockets = ast_true(val);
03899       } else if (!strcasecmp(var->name, "webenabled")) {
03900          webmanager_enabled = ast_true(val);
03901       } else if (!strcasecmp(var->name, "port")) {
03902          ami_desc.sin.sin_port = htons(atoi(val));
03903       } else if (!strcasecmp(var->name, "bindaddr")) {
03904          if (!inet_aton(val, &ami_desc.sin.sin_addr)) {
03905             ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
03906             memset(&ami_desc.sin.sin_addr, 0, sizeof(ami_desc.sin.sin_addr));
03907          }
03908       } else if (!strcasecmp(var->name, "allowmultiplelogin")) { 
03909          allowmultiplelogin = ast_true(val);
03910       } else if (!strcasecmp(var->name, "displayconnects")) {
03911          displayconnects = ast_true(val);
03912       } else if (!strcasecmp(var->name, "timestampevents")) {
03913          timestampevents = ast_true(val);
03914       } else if (!strcasecmp(var->name, "debug")) {
03915          manager_debug = ast_true(val);
03916       } else if (!strcasecmp(var->name, "httptimeout")) {
03917          newhttptimeout = atoi(val);
03918       } else {
03919          ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
03920             var->name, val);
03921       }  
03922    }
03923 
03924    if (manager_enabled)
03925       ami_desc.sin.sin_family = AF_INET;
03926    if (!have_sslbindaddr)
03927       amis_desc.sin.sin_addr = ami_desc.sin.sin_addr;
03928    if (ami_tls_cfg.enabled)
03929       amis_desc.sin.sin_family = AF_INET;
03930 
03931    
03932    AST_RWLIST_WRLOCK(&users);
03933 
03934    /* First, get users from users.conf */
03935    ucfg = ast_config_load("users.conf", config_flags);
03936    if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED)) {
03937       const char *hasmanager;
03938       int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager"));
03939 
03940       while ((cat = ast_category_browse(ucfg, cat))) {
03941          if (!strcasecmp(cat, "general"))
03942             continue;
03943          
03944          hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager");
03945          if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) {
03946             const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret");
03947             const char *user_read = ast_variable_retrieve(ucfg, cat, "read");
03948             const char *user_write = ast_variable_retrieve(ucfg, cat, "write");
03949             const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects");
03950             const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout");
03951             
03952             /* Look for an existing entry,
03953              * if none found - create one and add it to the list
03954              */
03955             if (!(user = get_manager_by_name_locked(cat))) {
03956                if (!(user = ast_calloc(1, sizeof(*user))))
03957                   break;
03958 
03959                /* Copy name over */
03960                ast_copy_string(user->username, cat, sizeof(user->username));
03961                /* Insert into list */
03962                AST_LIST_INSERT_TAIL(&users, user, list);
03963                user->ha = NULL;
03964                user->keep = 1;
03965                user->readperm = -1;
03966                user->writeperm = -1;
03967                /* Default displayconnect from [general] */
03968                user->displayconnects = displayconnects;
03969                user->writetimeout = 100;
03970             }
03971 
03972             if (!user_secret)
03973                user_secret = ast_variable_retrieve(ucfg, "general", "secret");
03974             if (!user_read)
03975                user_read = ast_variable_retrieve(ucfg, "general", "read");
03976             if (!user_write)
03977                user_write = ast_variable_retrieve(ucfg, "general", "write");
03978             if (!user_displayconnects)
03979                user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects");
03980             if (!user_writetimeout)
03981                user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout");
03982 
03983             if (!ast_strlen_zero(user_secret)) {
03984                if (user->secret)
03985                   ast_free(user->secret);
03986                user->secret = ast_strdup(user_secret);
03987             }
03988 
03989             if (user_read)
03990                user->readperm = get_perm(user_read);
03991             if (user_write)
03992                user->writeperm = get_perm(user_write);
03993             if (user_displayconnects)
03994                user->displayconnects = ast_true(user_displayconnects);
03995 
03996             if (user_writetimeout) {
03997                int val = atoi(user_writetimeout);
03998                if (val < 100)
03999                   ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at users.conf line %d\n", var->value, var->lineno);
04000                else
04001                   user->writetimeout = val;
04002             }
04003          }
04004       }
04005       ast_config_destroy(ucfg);
04006    }
04007 
04008    /* cat is NULL here in any case */
04009 
04010    while ((cat = ast_category_browse(cfg, cat))) {
04011       struct ast_ha *oldha;
04012 
04013       if (!strcasecmp(cat, "general"))
04014          continue;
04015 
04016       /* Look for an existing entry, if none found - create one and add it to the list */
04017       if (!(user = get_manager_by_name_locked(cat))) {
04018          if (!(user = ast_calloc(1, sizeof(*user))))
04019             break;
04020          /* Copy name over */
04021          ast_copy_string(user->username, cat, sizeof(user->username));
04022 
04023          user->ha = NULL;
04024          user->readperm = 0;
04025          user->writeperm = 0;
04026          /* Default displayconnect from [general] */
04027          user->displayconnects = displayconnects;
04028          user->writetimeout = 100;
04029 
04030          /* Insert into list */
04031          AST_RWLIST_INSERT_TAIL(&users, user, list);
04032       }
04033 
04034       /* Make sure we keep this user and don't destroy it during cleanup */
04035       user->keep = 1;
04036       oldha = user->ha;
04037       user->ha = NULL;
04038 
04039       var = ast_variable_browse(cfg, cat);
04040       for (; var; var = var->next) {
04041          if (!strcasecmp(var->name, "secret")) {
04042             if (user->secret)
04043                ast_free(user->secret);
04044             user->secret = ast_strdup(var->value);
04045          } else if (!strcasecmp(var->name, "deny") ||
04046                    !strcasecmp(var->name, "permit")) {
04047             user->ha = ast_append_ha(var->name, var->value, user->ha, NULL);
04048          }  else if (!strcasecmp(var->name, "read") ) {
04049             user->readperm = get_perm(var->value);
04050          }  else if (!strcasecmp(var->name, "write") ) {
04051             user->writeperm = get_perm(var->value);
04052          }  else if (!strcasecmp(var->name, "displayconnects") ) {
04053             user->displayconnects = ast_true(var->value);
04054          } else if (!strcasecmp(var->name, "writetimeout")) {
04055             int val = atoi(var->value);
04056             if (val < 100)
04057                ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno);
04058             else
04059                user->writetimeout = val;
04060          } else
04061             ast_debug(1, "%s is an unknown option.\n", var->name);
04062       }
04063       ast_free_ha(oldha);
04064    }
04065    ast_config_destroy(cfg);
04066 
04067    /* Perform cleanup - essentially prune out old users that no longer exist */
04068    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
04069       if (user->keep) { /* valid record. clear flag for the next round */
04070          user->keep = 0;
04071          continue;
04072       }
04073       /* We do not need to keep this user so take them out of the list */
04074       AST_RWLIST_REMOVE_CURRENT(list);
04075       /* Free their memory now */
04076       if (user->secret)
04077          ast_free(user->secret);
04078       ast_free_ha(user->ha);
04079       ast_free(user);
04080    }
04081    AST_RWLIST_TRAVERSE_SAFE_END;
04082 
04083    AST_RWLIST_UNLOCK(&users);
04084 
04085    if (webmanager_enabled && manager_enabled) {
04086       if (!webregged) {
04087          ast_http_uri_link(&rawmanuri);
04088          ast_http_uri_link(&manageruri);
04089          ast_http_uri_link(&managerxmluri);
04090          webregged = 1;
04091       }
04092    } else {
04093       if (webregged) {
04094          ast_http_uri_unlink(&rawmanuri);
04095          ast_http_uri_unlink(&manageruri);
04096          ast_http_uri_unlink(&managerxmluri);
04097          webregged = 0;
04098       }
04099    }
04100 
04101    if (newhttptimeout > 0)
04102       httptimeout = newhttptimeout;
04103 
04104    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Manager\r\nStatus: %s\r\nMessage: Manager reload Requested\r\n", manager_enabled ? "Enabled" : "Disabled");
04105 
04106    ast_tcptls_server_start(&ami_desc);
04107    if (ast_ssl_setup(amis_desc.tls_cfg))
04108       ast_tcptls_server_start(&amis_desc);
04109    return 0;
04110 }

int astman_is_authed ( uint32_t  ident  ) 

Determinie if a manager session ident is authenticated.

Definition at line 3284 of file manager.c.

References mansession_session::__lock, ast_mutex_unlock(), mansession_session::authenticated, and find_session().

Referenced by static_callback().

03285 {
03286    int authed;
03287    struct mansession_session *session;
03288 
03289    if (!(session = find_session(ident, 0)))
03290       return 0;
03291 
03292    authed = (session->authenticated != 0);
03293 
03294    ast_mutex_unlock(&session->__lock);
03295 
03296    return authed;
03297 }

int astman_verify_session_readpermissions ( uint32_t  ident,
int  perm 
)

Verify a session's read permissions against a permission mask.

Parameters:
ident session identity
perm permission mask to verify
Return values:
1 if the session has the permission mask capabilities
0 otherwise

Definition at line 3299 of file manager.c.

References mansession_session::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::managerid, and mansession_session::readperm.

03300 {
03301    int result = 0;
03302    struct mansession_session *session;
03303 
03304    AST_LIST_LOCK(&sessions);
03305    AST_LIST_TRAVERSE(&sessions, session, list) {
03306       ast_mutex_lock(&session->__lock);
03307       if ((session->managerid == ident) && (session->readperm & perm)) {
03308          result = 1;
03309          ast_mutex_unlock(&session->__lock);
03310          break;
03311       }
03312       ast_mutex_unlock(&session->__lock);
03313    }
03314    AST_LIST_UNLOCK(&sessions);
03315    return result;
03316 }

int astman_verify_session_writepermissions ( uint32_t  ident,
int  perm 
)

Verify a session's write permissions against a permission mask.

Parameters:
ident session identity
perm permission mask to verify
Return values:
1 if the session has the permission mask capabilities, otherwise 0
0 otherwise

Definition at line 3318 of file manager.c.

References mansession_session::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::managerid, and mansession_session::writeperm.

03319 {
03320    int result = 0;
03321    struct mansession_session *session;
03322 
03323    AST_LIST_LOCK(&sessions);
03324    AST_LIST_TRAVERSE(&sessions, session, list) {
03325       ast_mutex_lock(&session->__lock);
03326       if ((session->managerid == ident) && (session->writeperm & perm)) {
03327          result = 1;
03328          ast_mutex_unlock(&session->__lock);
03329          break;
03330       }
03331       ast_mutex_unlock(&session->__lock);
03332    }
03333    AST_LIST_UNLOCK(&sessions);
03334    return result;
03335 }

static int compress_char ( char  c  )  [static]

Definition at line 3403 of file manager.c.

Referenced by member_hash_fn(), and variable_count_hash_fn().

03404 {
03405    c &= 0x7f;
03406    if (c < 32)
03407       return 0;
03408    else if (c >= 'a' && c <= 'z')
03409       return c - 64;
03410    else if (c > 'z')
03411       return '_';
03412    else
03413       return c - 32;
03414 }

static struct mansession_session* find_session ( uint32_t  ident,
int  incinuse 
) [static]

locate an http session in the list. The search key (ident) is the value of the mansession_id cookie (0 is not valid and means a session on the AMI socket).

Definition at line 3263 of file manager.c.

References mansession_session::__lock, ast_atomic_fetchadd_int(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::inuse, mansession_session::managerid, and mansession_session::needdestroy.

Referenced by astman_is_authed().

03264 {
03265    struct mansession_session *session;
03266 
03267    if (ident == 0)
03268       return NULL;
03269 
03270    AST_LIST_LOCK(&sessions);
03271    AST_LIST_TRAVERSE(&sessions, session, list) {
03272       ast_mutex_lock(&session->__lock);
03273       if (session->managerid == ident && !session->needdestroy) {
03274          ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
03275          break;
03276       }
03277       ast_mutex_unlock(&session->__lock);
03278    }
03279    AST_LIST_UNLOCK(&sessions);
03280 
03281    return session;
03282 }

static struct ast_str* generic_http_callback ( enum output_format  format,
struct sockaddr_in *  requestor,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static]

Definition at line 3567 of file manager.c.

References ast_variable::name, ast_variable::next, s, and ast_variable::value.

Referenced by manager_http_callback(), mxml_http_callback(), and rawman_http_callback().

03571 {
03572    struct mansession s = {.session = NULL, };
03573    struct mansession_session *session = NULL;
03574    uint32_t ident = 0;
03575    int blastaway = 0;
03576    struct ast_variable *v;
03577    char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
03578    struct ast_str *out = NULL;
03579    struct message m = { 0 };
03580    unsigned int x;
03581    size_t hdrlen;
03582 
03583    for (v = params; v; v = v->next) {
03584       if (!strcasecmp(v->name, "mansession_id")) {
03585          sscanf(v->value, "%x", &ident);
03586          break;
03587       }
03588    }
03589 
03590    if (!(session = find_session(ident, 1))) {
03591       /* Create new session.
03592        * While it is not in the list we don't need any locking
03593        */
03594       if (!(session = ast_calloc(1, sizeof(*session)))) {
03595          *status = 500;
03596          goto generic_callback_out;
03597       }
03598       session->sin = *requestor;
03599       session->fd = -1;
03600       session->waiting_thread = AST_PTHREADT_NULL;
03601       session->send_events = 0;
03602       ast_mutex_init(&session->__lock);
03603       ast_mutex_lock(&session->__lock);
03604       session->inuse = 1;
03605       /*!\note There is approximately a 1 in 1.8E19 chance that the following
03606        * calculation will produce 0, which is an invalid ID, but due to the
03607        * properties of the rand() function (and the constantcy of s), that
03608        * won't happen twice in a row.
03609        */
03610       while ((session->managerid = ast_random() ^ (unsigned long) session) == 0);
03611       session->last_ev = grab_last();
03612       AST_LIST_LOCK(&sessions);
03613       AST_LIST_INSERT_HEAD(&sessions, session, list);
03614       ast_atomic_fetchadd_int(&num_sessions, 1);
03615       AST_LIST_UNLOCK(&sessions);
03616    }
03617 
03618    s.session = session;
03619 
03620    ast_mutex_unlock(&session->__lock);
03621 
03622    if (!(out = ast_str_create(1024))) {
03623       *status = 500;
03624       goto generic_callback_out;
03625    }
03626 
03627    s.fd = mkstemp(template);  /* create a temporary file for command output */
03628    unlink(template);
03629    s.f = fdopen(s.fd, "w+");
03630 
03631    for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
03632       hdrlen = strlen(v->name) + strlen(v->value) + 3;
03633       m.headers[m.hdrcount] = alloca(hdrlen);
03634       snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
03635       m.hdrcount = x + 1;
03636    }
03637 
03638    if (process_message(&s, &m)) {
03639       if (session->authenticated) {
03640             if (manager_displayconnects(session))
03641             ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
03642          ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
03643       } else {
03644             if (displayconnects)
03645             ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
03646          ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr));
03647       }
03648       session->needdestroy = 1;
03649    }
03650 
03651    ast_str_append(&out, 0,
03652              "Content-type: text/%s\r\n"
03653              "Cache-Control: no-cache;\r\n"
03654              "Set-Cookie: mansession_id=\"%08x\"; Version=\"1\"; Max-Age=%d\r\n"
03655              "\r\n",
03656          contenttype[format],
03657          session->managerid, httptimeout);
03658 
03659    if (format == FORMAT_XML) {
03660       ast_str_append(&out, 0, "<ajax-response>\n");
03661    } else if (format == FORMAT_HTML) {
03662 
03663 #define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
03664 #define TEST_STRING \
03665    "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \
03666    user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \
03667    <input type=\"submit\"></form>"
03668 
03669       ast_str_append(&out, 0, "<title>Asterisk&trade; Manager Interface</title>");
03670       ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
03671       ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>");
03672       ast_str_append(&out, 0, ROW_FMT, TEST_STRING);
03673    }
03674 
03675    if (s.f != NULL) {   /* have temporary output */
03676       char *buf;
03677       size_t l = ftell(s.f);
03678       
03679       if (l) {
03680          if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s.fd, 0))) {
03681             ast_log(LOG_WARNING, "mmap failed.  Manager output was not processed\n");
03682          } else {
03683             if (format == FORMAT_XML || format == FORMAT_HTML)
03684                xml_translate(&out, buf, params, format);
03685             else
03686                ast_str_append(&out, 0, "%s", buf);
03687             munmap(buf, l);
03688          }
03689       } else if (format == FORMAT_XML || format == FORMAT_HTML) {
03690          xml_translate(&out, "", params, format);
03691       }
03692       fclose(s.f);
03693       s.f = NULL;
03694       s.fd = -1;
03695    }
03696 
03697    if (format == FORMAT_XML) {
03698       ast_str_append(&out, 0, "</ajax-response>\n");
03699    } else if (format == FORMAT_HTML)
03700       ast_str_append(&out, 0, "</table></body>\r\n");
03701 
03702    ast_mutex_lock(&session->__lock);
03703    /* Reset HTTP timeout.  If we're not authenticated, keep it extremely short */
03704    session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5);
03705 
03706    if (session->needdestroy) {
03707       if (session->inuse == 1) {
03708          ast_debug(1, "Need destroy, doing it now!\n");
03709          blastaway = 1;
03710       } else {
03711          ast_debug(1, "Need destroy, but can't do it yet!\n");
03712          if (session->waiting_thread != AST_PTHREADT_NULL)
03713             pthread_kill(session->waiting_thread, SIGURG);
03714          session->inuse--;
03715       }
03716    } else
03717       session->inuse--;
03718    ast_mutex_unlock(&session->__lock);
03719 
03720    if (blastaway)
03721       destroy_session(session);
03722 generic_callback_out:
03723    if (*status != 200)
03724       return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n");
03725    return out;
03726 }

int init_manager ( void   ) 

Called by Asterisk initialization.

Definition at line 4112 of file manager.c.

References __init_manager().

Referenced by main().

04113 {
04114    return __init_manager(0);
04115 }

static struct ast_str* manager_http_callback ( struct ast_tcptls_session_instance ser,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static]

Definition at line 3728 of file manager.c.

References FORMAT_HTML, generic_http_callback(), and ast_tcptls_session_instance::requestor.

03729 {
03730    return generic_http_callback(FORMAT_HTML, &ser->requestor, uri, params, status, title, contentlength);
03731 }

static struct ast_str* mxml_http_callback ( struct ast_tcptls_session_instance ser,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static]

Definition at line 3733 of file manager.c.

References FORMAT_XML, generic_http_callback(), and ast_tcptls_session_instance::requestor.

03734 {
03735    return generic_http_callback(FORMAT_XML, &ser->requestor, uri, params, status, title, contentlength);
03736 }

static void purge_old_stuff ( void *  data  )  [static]

cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most

Definition at line 3770 of file manager.c.

References purge_events(), and purge_sessions().

03771 {
03772    purge_sessions(1);
03773    purge_events();
03774 }

static struct ast_str* rawman_http_callback ( struct ast_tcptls_session_instance ser,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static]

Definition at line 3738 of file manager.c.

References FORMAT_RAW, generic_http_callback(), and ast_tcptls_session_instance::requestor.

03739 {
03740    return generic_http_callback(FORMAT_RAW, &ser->requestor, uri, params, status, title, contentlength);
03741 }

int reload_manager ( void   ) 

Called by Asterisk module functions and the CLI command.

Definition at line 4117 of file manager.c.

References __init_manager().

Referenced by handle_manager_reload().

04118 {
04119    return __init_manager(1);
04120 }

static int variable_count_cmp_fn ( void *  obj,
void *  vstr,
int  flags 
) [static]

Definition at line 3428 of file manager.c.

References CMP_MATCH, str, and variable_count::varname.

Referenced by xml_translate().

03429 {
03430    /* Due to the simplicity of struct variable_count, it makes no difference
03431     * if you pass in objects or strings, the same operation applies. This is
03432     * due to the fact that the hash occurs on the first element, which means
03433     * the address of both the struct and the string are exactly the same. */
03434    struct variable_count *vc = obj;
03435    char *str = vstr;
03436    return !strcmp(vc->varname, str) ? CMP_MATCH : 0;
03437 }

static int variable_count_hash_fn ( const void *  vvc,
const int  flags 
) [static]

Definition at line 3416 of file manager.c.

References compress_char(), and variable_count::varname.

Referenced by xml_translate().

03417 {
03418    const struct variable_count *vc = vvc;
03419    int res = 0, i;
03420    for (i = 0; i < 5; i++) {
03421       if (vc->varname[i] == '\0')
03422          break;
03423       res += compress_char(vc->varname[i]) << (i * 6);
03424    }
03425    return res;
03426 }

static void xml_copy_escape ( struct ast_str **  out,
const char *  src,
int  mode 
) [static]

Definition at line 3342 of file manager.c.

References ast_str_append(), and buf.

Referenced by xml_translate().

03343 {
03344    /* store in a local buffer to avoid calling ast_str_append too often */
03345    char buf[256];
03346    char *dst = buf;
03347    int space = sizeof(buf);
03348    /* repeat until done and nothing to flush */
03349    for ( ; *src || dst != buf ; src++) {
03350       if (*src == '\0' || space < 10) {   /* flush */
03351          *dst++ = '\0';
03352          ast_str_append(out, 0, "%s", buf);
03353          dst = buf;
03354          space = sizeof(buf);
03355          if (*src == '\0')
03356             break;
03357       }
03358          
03359       if ( (mode & 2) && !isalnum(*src)) {
03360          *dst++ = '_';
03361          space--;
03362          continue;
03363       }
03364       switch (*src) {
03365       case '<':
03366          strcpy(dst, "&lt;");
03367          dst += 4;
03368          space -= 4;
03369          break;
03370       case '>':
03371          strcpy(dst, "&gt;");
03372          dst += 4;
03373          space -= 4;
03374          break;
03375       case '\"':
03376          strcpy(dst, "&quot;");
03377          dst += 6;
03378          space -= 6;
03379          break;
03380       case '\'':
03381          strcpy(dst, "&apos;");
03382          dst += 6;
03383          space -= 6;
03384          break;
03385       case '&':
03386          strcpy(dst, "&amp;");
03387          dst += 5;
03388          space -= 5;
03389          break;
03390 
03391       default:
03392          *dst++ = mode ? tolower(*src) : *src;
03393          space--;
03394       }
03395    }
03396 }

static void xml_translate ( struct ast_str **  out,
char *  in,
struct ast_variable vars,
enum output_format  format 
) [static]

Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'.

At the moment the output format is the following (but it may change depending on future requirements so don't count too much on it when writing applications):

General: the unformatted text is used as a value of XML output: to be completed

 *   Each section is within <response type="object" id="xxx">
 *   where xxx is taken from ajaxdest variable or defaults to unknown
 *   Each row is reported as an attribute Name="value" of an XML
 *   entity named from the variable ajaxobjtype, default to "generic"
 * 

HTML output: each Name-value pair is output as a single row of a two-column table. Sections (blank lines in the input) are separated by a


Definition at line 3467 of file manager.c.

References ao2_alloc(), ao2_container_alloc(), ao2_find(), ao2_link(), ao2_ref(), ast_debug, ast_skip_blanks(), ast_str_append(), ast_strlen_zero(), ast_trim_blanks(), variable_count::count, FORMAT_XML, ast_variable::name, ast_variable::next, strsep(), ast_variable::value, var, variable_count_cmp_fn(), variable_count_hash_fn(), and xml_copy_escape().

03468 {
03469    struct ast_variable *v;
03470    const char *dest = NULL;
03471    char *var, *val;
03472    const char *objtype = NULL;
03473    int in_data = 0;  /* parsing data */
03474    int inobj = 0;
03475    int xml = (format == FORMAT_XML);
03476    struct variable_count *vc = NULL;
03477    struct ao2_container *vco = NULL;
03478 
03479    for (v = vars; v; v = v->next) {
03480       if (!dest && !strcasecmp(v->name, "ajaxdest"))
03481          dest = v->value;
03482       else if (!objtype && !strcasecmp(v->name, "ajaxobjtype"))
03483          objtype = v->value;
03484    }
03485    if (!dest)
03486       dest = "unknown";
03487    if (!objtype)
03488       objtype = "generic";
03489 
03490    /* we want to stop when we find an empty line */
03491    while (in && *in) {
03492       val = strsep(&in, "\r\n"); /* mark start and end of line */
03493       if (in && *in == '\n')     /* remove trailing \n if any */
03494          in++;
03495       ast_trim_blanks(val);
03496       ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val);
03497       if (ast_strlen_zero(val)) {
03498          if (in_data) { /* close data */
03499             ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
03500             in_data = 0;
03501          }
03502          if (inobj) {
03503             ast_str_append(out, 0, xml ? " /></response>\n" :
03504                "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
03505             inobj = 0;
03506             ao2_ref(vco, -1);
03507             vco = NULL;
03508          }
03509          continue;
03510       }
03511 
03512       /* we expect Name: value lines */
03513       if (in_data) {
03514          var = NULL;
03515       } else {
03516          var = strsep(&val, ":");
03517          if (val) {  /* found the field name */
03518             val = ast_skip_blanks(val);
03519             ast_trim_blanks(var);
03520          } else {    /* field name not found, move to opaque mode */
03521             val = var;
03522             var = "Opaque-data";
03523          }
03524       }
03525 
03526       if (!inobj) {
03527          if (xml)
03528             ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
03529          else
03530             ast_str_append(out, 0, "<body>\n");
03531          vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
03532          inobj = 1;
03533       }
03534 
03535       if (!in_data) {   /* build appropriate line start */
03536          ast_str_append(out, 0, xml ? " " : "<tr><td>");
03537          if ((vc = ao2_find(vco, var, 0)))
03538             vc->count++;
03539          else {
03540             /* Create a new entry for this one */
03541             vc = ao2_alloc(sizeof(*vc), NULL);
03542             vc->varname = var;
03543             vc->count = 1;
03544             ao2_link(vco, vc);
03545          }
03546          xml_copy_escape(out, var, xml ? 1 | 2 : 0);
03547          if (vc->count > 1)
03548             ast_str_append(out, 0, "-%d", vc->count);
03549          ao2_ref(vc, -1);
03550          ast_str_append(out, 0, xml ? "='" : "</td><td>");
03551          if (!strcmp(var, "Opaque-data"))
03552             in_data = 1;
03553       }
03554       xml_copy_escape(out, val, 0); /* data field */
03555       if (!in_data)
03556          ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
03557       else
03558          ast_str_append(out, 0, xml ? "\n" : "<br>\n");
03559    }
03560    if (inobj) {
03561       ast_str_append(out, 0, xml ? " /></response>\n" :
03562          "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
03563       ao2_ref(vco, -1);
03564    }
03565 }


Variable Documentation

struct server_args ami_desc [static]

Definition at line 3777 of file manager.c.

Referenced by __init_manager().

struct ast_tls_config ami_tls_cfg

Definition at line 3776 of file manager.c.

Referenced by __init_manager().

struct server_args amis_desc [static]

Definition at line 3788 of file manager.c.

Referenced by __init_manager().

char* contenttype[] [static]

Initial value:

 {
   [FORMAT_RAW] = "plain",
   [FORMAT_HTML] = "html",
   [FORMAT_XML] =  "xml",
}

Definition at line 3252 of file manager.c.

struct ast_http_uri manageruri

Definition at line 3750 of file manager.c.

struct ast_http_uri managerxmluri

Definition at line 3757 of file manager.c.

struct ast_http_uri rawmanuri

Definition at line 3743 of file manager.c.

int registered = 0 [static]

Definition at line 3764 of file manager.c.

int webregged = 0 [static]

Definition at line 3765 of file manager.c.

char* words[AST_MAX_CMD_LEN]

Definition at line 144 of file manager.c.

Referenced by check_blacklist().


Generated on Thu Jul 9 13:41:24 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7