[asterisk-commits] branch oej/aum - r7302 in /team/oej/aum: include/asterisk/aum.h res/res_aum.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Sat Dec 3 11:40:29 CST 2005


Author: oej
Date: Sat Dec  3 11:40:26 2005
New Revision: 7302

URL: http://svn.digium.com/view/asterisk?rev=7302&view=rev
Log:
The resource file and include file, more info in doxygen :-) This is work in progress.

Added:
    team/oej/aum/include/asterisk/aum.h
    team/oej/aum/res/res_aum.c

Added: team/oej/aum/include/asterisk/aum.h
URL: http://svn.digium.com/view/asterisk/team/oej/aum/include/asterisk/aum.h?rev=7302&view=auto
==============================================================================
--- team/oej/aum/include/asterisk/aum.h (added)
+++ team/oej/aum/include/asterisk/aum.h Sat Dec  3 11:40:26 2005
@@ -1,0 +1,411 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Asterisk User Management interface
+ *
+ * Copyright (C) 2005, Edvina AB, Sollentuna, Sweden
+ *
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!\note This is just skeletons, that I'm trying to put flesh and	
+	clothes on... Mail input to oej at edvina.net
+*/
+
+/*!\file
+ * \brief Asterisk User Managment - AUM - API
+ * \arg Implemented in res_aum.c
+ * \par See also
+ *  	\arg AUM_desc
+ */
+
+#ifndef _ASTERISK_AUM_H
+#define _ASTERISK_AUM_H
+
+/*--------------------------- AUM STRING HANDLING -------------------------------- */
+/*! Character set definition for some strings */
+enum aum_string_charset {
+	AUM_CHAR_UNKNOWN = 0,
+	AUM_CHAR_ASCII,			/*!< 7 bit ASCII */
+	AUM_CHAR_ISO8859_1,		/*!< ISO 8859-1, 8 bits */
+	AUM_CHAR_ISO8859_2,		/*!< ISO 8859-2, 8 bits */
+	AUM_CHAR_ISO8859_3,		/*!< ISO 8859-3, 8 bits */
+	AUM_CHAR_UTF8,			/*!< Unicode ISO 9660, UTF 8 encoding */
+};
+
+struct aum_string_convert {
+	enum aum_string_charset	charset;	/*!< Character set */
+	const char *label;			/*!< Label used in strings in config files */
+};
+
+/*! String object for international strings. 
+	\note Use the aum_string functions to assign values, get strings in alternative 
+	character sets and free the chain of strings 
+	OEJ: This is a simple linked list. Wonder if the AST_LIST is needed here?
+*/
+struct aum_string_struct {
+	char 		*string;	/*!< Allocated string, needs to be free()d after use */
+	size_t		size;		/*!< Allocated size, if allocated (Won't free unless we have size */
+	enum aum_string_charset charset;	/*!< Character set for this string */
+	struct aum_string *next;	/*!< Pointers to alternative encodings of the same string */
+};
+
+typedef struct aum_string_struct aum_string;
+
+/*! \brief Address types for address objects in AUM */
+enum aum_address_type {
+	AUM_ADDR_EMAIL 	= (1 << 0),	/*!< E-mail - string like "username at domain.se" */
+	AUM_ADDR_XMPP	= (1 << 1),	/*!< XMPP uri */
+	AUM_ADDR_SIP	= (1 << 2),	/*!< SIP uri */
+	AUM_ADDR_MSN	= (1 << 3),	/*!< MSN user identifier "username at hotmail.com" */
+	AUM_ADDR_AOL	= (1 << 4),	/*!< AOL/ICQ user ID */
+	AUM_ADDR_TEL	= (1 << 5),	/*!< E.164 phone number (TEL-uri format, local allowed (depends on your configuration) */
+	AUM_ADDR_CELL_TEL = (1 << 6),	/*!< Cell phone E.164 phone number (TEL-uri format, local allowed (depends on your configuration) */
+	AUM_ADDR_IAX2	= (1 << 7),	/*!< IAX2 callable uri, like "guest at myasterisk.com/12345"	*/
+	AUM_ADDR_FWD	= (1 << 8),	/*!< Free World Dialup User ID */
+	AUM_ADDR_IAXTEL	= (1 << 9),	/*!< IAXtel Dialup User ID */
+	AUM_ADDR_FAX	= (1 << 10),	/*!< Preferred fax number (E.164 Tel URI) */
+	AUM_ADDR_WEB	= (1 << 11),	/*!< HOMEPAGE */
+	AUM_ADDR_NONE	= (1 << 30),	/*!< Return value */
+};
+
+/*! \brief Things you can configure in AUM */
+enum aum_config_objects {
+	AUM_CONFOBJ_GENERAL	= (1 << 0),	/*!< General configuration options */
+	AUM_CONFOBJ_USER	= (1 << 1),	/*!< User configuration */ 
+	AUM_CONFOBJ_GROUP	= (1 << 2),	/*!< Group configuration */
+};
+
+/*! \brief AUM configuration options */
+enum aum_config_options {
+	AUM_CNF_NONE,			/*!< Unknown configuration directive */
+	AUM_CNF_NOT_VALID_FOR_OBJECT,	/*!< Not valid for this object */
+	AUM_CNF_NOT_FOUND,		/*!< No match found */
+	AUM_CNF_ADDR_EMAIL,		/*!< Email address */
+	AUM_CNF_ADDR_XMPP,		/*!< XMPP/Jabber address */
+	AUM_CNF_ADDR_SIP,		/*!< SIP AOR: SIP uri to reach this user */
+	AUM_CNF_ADDR_IAX2,		/*!< IAX2 URI */
+	AUM_CNF_ADDR_AOL,		/*!< AOL IM */
+	AUM_CNF_ADDR_MSN,		/*!< MSN Contat for IM */
+	AUM_CNF_ADDR_TEL,		/*!< Telephone numer in E.164 format */
+	AUM_CNF_ADDR_CELL_TEL,		/*!< Cell phone number */
+	AUM_CNF_ADDR_FAX,		/*!< Fax number (PSTN) */
+	AUM_CNF_ADDR_FWD,		/*!< Free World Dialup account */
+	AUM_CNF_ADDR_IAXTEL,		/*!< IAXtel account ID */
+	AUM_CNF_ADDR_WEB,		/*!< Home page */
+	AUM_CNF_VMAILBOX,		/*!< Voicemail mailbox exten at context */
+	AUM_CNF_GROUP,			/*!< Group membership */
+	AUM_CNF_CALLBACKEXT,		/*!< Default extension */
+	AUM_CNF_DISACONTEXT,		/*!< DISA context for disa() access */
+	AUM_CNF_SIPDOMAIN,		/*!< SIP DOMAIN this user belongs to (virtual PBX) */
+	AUM_CNF_SUBSCRIBECONTEXT,	/*!< SIP subscription context */
+	AUM_CNF_DEFEXTEN,		/*!< Default extension */
+	AUM_CNF_DEFCONTEXT,		/*!< Default context */
+	AUM_CNF_CID,			/*!< Caller ID */
+	AUM_CNF_CALLERPRES,		/*!< Caller ID presentation when making calls */
+	AUM_CNF_ACCOUNTCODE,		/*!< Account code for this user */
+	AUM_CNF_MANAGERACCESS,		/*!< Manager access something */
+	AUM_CNF_SECRET,			/*!< Secret (password) */
+	AUM_CNF_PIN,			/*!< Pin code for authorization by DTMF */
+	AUM_CNF_IAX2KEY,		/*!< Name of IAX key */
+	AUM_CNF_MUSICCLASS,		/*!< Default music class when this user puts someone on hold */
+	AUM_CNF_LDAPDN,			/*!< LDAP handle for this user */
+	AUM_CNF_FIRSTNAME,		/*!< First name */
+	AUM_CNF_LASTNAME,		/*!< Last name*/
+	AUM_CNF_TITLE,			/*!< Title */
+	AUM_CNF_SOUNDNAME,		/*!< Sound file */
+	AUM_CNF_CHANVAR,		/*!< Channel variables */
+	AUM_CNF_PERMIT,			/*!< ACL permit */
+	AUM_CNF_DENY,			/*!< ACL deny */
+	AUM_CNF_NUMID,			/*!< Numerical ID for this user */
+	AUM_CNF_TIMEZONE,		/*!< Timezone, mostly used for voice mail */
+	AUM_CNF_GROUPVAR,		/*!< */
+	AUM_CNF_TYPE,			/*!< Type of config - group, user */
+	AUM_CNF_GROUPDESC,		/*!< Group description */
+	AUM_CNF_DEBUG,			/*!< AUM debug option */
+};
+
+/*! \brief AUM configuration definition structure */
+struct aum_config_struct {
+	enum aum_config_options option;
+	char 			*label;
+	enum aum_config_objects valid;
+};
+
+/*! \brief AUM Address object */
+struct aum_address {
+ 	enum aum_address_type type;		/*!< Address type */
+	enum aum_string_charset charset;		/*!< character set */
+	char address[180];			/*!< The actual address */
+	int active;
+	AST_LIST_ENTRY(aum_address) list;	/*!< List mechanics */
+};
+
+/*! \brief AUM Address configuration helper */
+struct aum_address_config_struct {
+	enum aum_address_type	type;
+	char 			*label;
+	char 			*display;
+	enum aum_config_options configoption;
+};
+
+/*! \brief Context types for AUM user objects */
+enum aum_context_type {
+	AUM_CONTEXT_NONE = 0,	/*!< No Context (Return value for functions) */
+	AUM_CONTEXT_DEF_CB,	/*!< Default callback context for reaching this user */
+	AUM_CONTEXT_DEF_INCOMING,	/*!< Default incoming context for this user */
+	AUM_CONTEXT_VOICEMAIL,	/*!< Default voicemail context */
+	AUM_CONTEXT_DISA,	/*!< Default DISA context */
+	AUM_CONTEXT_SIPSUBSCRIBE,	/*!< Default context for SIP subscriptions */
+};
+
+/*! \brief Explanations of contexts */
+struct aum_context_table {
+	enum aum_context_type	type;
+	const char *desc;
+};
+
+/*! \brief Presence states for AUM user objects */
+enum aum_presence_state {	/* This follows XMPP roughly */
+	AUM_PRES_NOT_AVAILABLE,	/*!< No presence available */
+	AUM_PRES_AVAILABLE,	/*!< Reachable, on line */
+	AUM_PRES_MEETING,	/*!< Meeting */
+	AUM_PRES_ONCALL,	/*!< On call */
+	AUM_PRES_DND,		/*!< Do not disturb */
+	AUM_PRES_EXT_AWAY,	/*!< Extended away */
+};
+
+/*! \brief Presence providers */
+enum aum_presence_prov {
+	AUM_PRESPROV_XMPP,	/*!< Jabber/XMPP */	
+	AUM_PRESPROV_MSN,	/*!< MSN Messenger */
+	AUM_PRESPROV_SIMPLE,	/*!< SIP Simple */
+	AUM_PRESPROV_AMI,	/*!< AMI - Asterisk manager interface */
+	AUM_PRESPROV_DIALPLAN,	/*!< Dialplan functions */
+};
+
+/*! \brief Presence structures for AUM presence objects */
+struct aum_presence {
+	enum aum_presence_state	state;		/*!< State of this user */
+	enum aum_presence_prov provider;	/*!< Provider of presence */
+	AST_LIST_ENTRY(aum_presence) list;	/*!< List mechanics */
+};
+
+/*! \brief Context structure 
+	\note Until further notice, Asterisk contexts are ASCII
+*/
+struct aum_context {
+	enum aum_context_type type;		/*!< Context type */
+	char context[AST_MAX_CONTEXT];		/*!< Context name */
+	AST_LIST_ENTRY(aum_context) list;	/*!< List mechanics */
+};
+
+
+/*! \brief Group memberships */
+struct aum_group_member {
+	int priority;				/*!< Not defined yet... */
+	union {
+		struct aum_group *group;	/*!< For users, pointer to groups */
+		struct aum_user *user;		/*!< For groups, pointer to users */
+	};
+	AST_LIST_ENTRY(aum_group_member) list;	/*!< List mechanics */
+};
+
+
+/*! \brief Declaration of grouplist structure for inclusion in objects */
+AST_LIST_HEAD(aum_user_grouplist, aum_group_member);
+AST_LIST_HEAD(aum_user_addrlist, aum_address);
+AST_LIST_HEAD(aum_user_contextlist, aum_context);
+AST_LIST_HEAD(aum_presencelist, aum_presence);
+
+/*! \brief Main AUM user object
+	\par This is the main AUM object
+	- contains linked list of addresses
+	- contains linked list of contexts of addresses
+	- contains linked list of group memberships
+*/
+struct aum_user {
+	ASTOBJ_COMPONENTS(struct aum_user);	/*!< Generic pointers - name being one */
+	char mailbox[AST_MAX_EXTENSION];	/*!< Default mailbox */
+	char default_exten[AST_MAX_EXTENSION];	/*!< Default extension for this user (for callbacks) */
+	char cid_num[256];		/*!< Default caller ID num (E.164 type) */
+	char cid_name[256];		/*!< Default caller ID name */
+	char accountcode[AST_MAX_ACCOUNT_CODE];	/*!< Default Account code */
+	char sip_username[256];		/*!< SIP user name (utf8) */
+	char musicclass[MAX_MUSICCLASS];	/*!< Default musicclass for this user */
+	char first_name[80];		/*!< First name (ISO 8859-1) */
+	char last_name[80];		/*!< Last name (ISO 8859-1) */
+	char title[20];			/*!< Title */
+	char language[MAX_LANGUAGE];	/*!< Default language */
+	struct aum_presencelist	presence;	/*! Presence states */
+	char zonetag[80];		/*!< Time zone */
+	char numuserid[80];		/*!< Numeric user ID for this user */
+	char pincode[80];		/*!< Numeric pincode for this user */
+	char secret[80];		/*!< Secret for this user */
+	char ldapdn[180];		/*!< LDAP DN */
+	char registrar[20];		/*!< Who added this object? */
+	struct ast_variable *chanvars;	/*!< Default channel variables */
+	struct aum_user_contextlist contexts;	/*!< Linked list of contexts this user use */
+	struct aum_user_grouplist groups;	/*!< Linked list of groups we are members to */
+	struct aum_user_addrlist address;	/*!< Linked list of addresses of various types */
+	struct ast_ha	*acl;		/*!< Access control list for user */
+					/*!< The highest priority is used as primary group for setting default values */
+	int managerperm;		/*!< If sat, this user can log in to manager with these permissions */
+	int calling_pres;		/*!< Default Caller ID presentation */
+};
+
+/*! \brief the AUM group definition */
+struct aum_group {
+	ASTOBJ_COMPONENTS(struct aum_group);
+	char sipdomain[120];			/*!< Should be AST_MAX_DOMAIN something */
+	char incoming_did[AST_MAX_EXTENSION];	/*!< Main DID for this group */
+	char language[MAX_LANGUAGE];		/*!< Default language for group */
+	char musicclass[MAX_MUSICCLASS];	/*!< Default musicclass for this group */
+	int managerperm;			/*!< This group's permissions in manager */
+	struct aum_user_contextlist contexts;	/*!< Linked list of contexts this group use */
+	struct ast_variable *chanvars;
+	char *description;			/*!< Description */
+	struct aum_user_grouplist members;
+};
+
+/*--------------------------- GLOBAL FUNCTIONS ----------------------*/
+
+/*! \brief Find AUM user 
+	\param userid Unique user ID for this user 
+	\return NULL if not found, otherwise pointer to structure 
+*/
+struct aum_user *find_aum_user(char *userid);
+
+/*! \brief Find an address for an AUM user 
+	\param user	AUM user object pointer
+	\param type	AUM address type (enum)
+	\param start	AUM Address pointer for where to start the search in the linked list. NULL if from beginning
+	\return		Pointer to AUM address object if found, otherwise NULL 
+*/
+struct aum_address *find_address_for_user(struct aum_user *user, enum aum_address_type type, struct aum_address *start);
+
+/*! \brief Find address object for specified address
+	\param user	AUM user object pointer
+	\param type	AUM address type (enum aum_address_type)
+	\param address	Address
+	\return 	Pointer to AUM address object if found, otherwise NULL
+*/
+struct aum_address *find_user_aum_address(struct aum_user *user, enum aum_address_type type, char *address);
+
+/*! \brief Find user by any AUM address type address (xmpp, sip, email, iax2 etc)
+	\param type	AUM address type (enum)
+	\param address	Address as a text string
+*/
+struct aum_user *find_user_by_address(enum aum_address_type type, char *address);
+
+/*! \brief Find AUM user by e-mail
+	\param email Email address for this user
+	\return NULL if not found, otherwise pointer to structure 
+*/
+struct aum_user *find_aum_user_email(char *email);
+
+/*! \brief Find AUM user by numeric user id
+	\param numuid Searched numeric user ID
+	\return NULL if not found, otherwise pointer to structure
+*/
+struct aum_user *find_aum_user_by_numuserid(char *numuserid);
+
+/*! \brief Find AUM user group by group name 
+	\param Group name in text
+	\result struct aum_group pointer to group
+*/
+struct aum_group *find_group_by_name(char *groupname);
+
+/*! \brief Find out if user belongs to group 
+	\param user AUM user object
+	\param group Group name
+*/
+int aum_group_test(struct aum_user *user, char *groupname);
+
+/*! \brief Find out if user belongs to group by group object
+	\param user AUM user object
+	\param group Group name
+*/
+int aum_group_test_full(struct aum_user *user, struct aum_group *group);
+
+/*! \brief Find e-mail address for AUM user
+	\param user AUM user id
+	\return E-mail address with highest priority, NULL if not found
+*/
+char *aum_find_email(char *userid);
+
+/*! \brief Find e-mail address for AUM user by AUM struct pointer
+	\param user AUM struct pointer
+	\return E-mail address with highest priority, NULL if not found
+*/
+char *aum_find_email_full(struct aum_user *user);
+
+/*! \brief Find jabber/XMPP address for AUM user
+	\param user AUM user id
+	\return Jabber/XMPP uri with highest priority, NULL if not found
+*/
+char *aum_find_xmpp(char *userid);
+
+/*! \brief Find jabber/XMPP address for AUM user by AUM struct pointer
+	\param user AUM struct pointer
+	\return Jabber/XMPP uri with highest priority, NULL if not found
+*/
+char *aum_find_xmpp_full(struct aum_user *user);
+
+/*! \brief Find any address of given type 
+	\param user AUM struct pointer
+	\param type AUM address type
+	\return Character string with highest priority, NULL if not found
+*/
+char *aum_find_address(struct aum_user *user, enum aum_address_type type);
+
+/*! \brief Find a context for a user
+	\param user AUM struct pointer
+	\param type AUM context type (enum)
+	\return character string pointer if context found, NULL if not found
+*/
+char *aum_find_user_context(struct aum_user *user, enum aum_context_type type);
+
+/*--------- AUM String handling functions ----------------------*/
+/*! \brief Allocate AUM string - remember to deallocate
+	\param string	Input character string
+	\param charset	aum_string_charset enum
+	\return 	aum_string object
+*/
+aum_string *aum_string_alloc(char *string, enum aum_string_charset charset);
+
+/*! \brief Convert string, allocate new aum_string object and link it at end of list
+	\param string	Input aum_string
+	\param charset	aum_string_charset enum
+	\return 	aum_string object
+*/
+aum_string *aum_string_add_charset_variant(aum_string *string, enum aum_string_charset charset);
+
+/*! \brief Get string in specific character set. If not found, convert to that charset and return string
+	\param string	Input aum_string
+	\param charset	aum_string_charset enum
+	\return 	character string (char *)
+*/
+char *aum_string_output(aum_string *string, enum aum_string_charset charset);
+
+/*! \brief Parse character set in front of string, create string
+	\param string	string optionally with charset in front of string, separated with |
+	\param defaultcharset	Default character set, if not specified
+	\return 	aum_string object, allocated by this function
+	
+*/
+aum_string *aum_string_add(char *string, enum aum_string_charset defaultcharset);
+
+/*! \brief Destroy all strings beginning with this one */
+void aum_string_destroy(aum_string *string);
+
+#endif /* _ASTERISK_MD5_H */

Added: team/oej/aum/res/res_aum.c
URL: http://svn.digium.com/view/asterisk/team/oej/aum/res/res_aum.c?rev=7302&view=auto
==============================================================================
--- team/oej/aum/res/res_aum.c (added)
+++ team/oej/aum/res/res_aum.c Sat Dec  3 11:40:26 2005
@@ -1,0 +1,1478 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * 
+ * Asterisk User Management Resource
+ *
+ * Copyright (C) 2005, Edvina AB, Sollentuna, Sweden.
+ *
+ * Olle E. Johansson <oej at edvina.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief AUM - Asterisk User Management
+ *
+ * \author Olle E. Johansson <oej at edvina.net>
+ *
+ * \arg For information about aum, see \ref AUM_desc
+ *
+ */
+ 
+#include <pthread.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/signal.h>
+#include <netinet/in.h>
+#include <iconv.h>	/* String conversion routines */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.19 $")
+
+#include "asterisk/lock.h"
+#include "asterisk/file.h"
+#include "asterisk/logger.h"
+#include "asterisk/config.h"
+#include "asterisk/channel.h"
+#include "asterisk/astobj.h"
+#include "asterisk/pbx.h"
+#include "asterisk/options.h"
+#include "asterisk/module.h"
+#include "asterisk/app.h"
+#include "asterisk/cli.h"
+#include "asterisk/manager.h"
+#include "asterisk/utils.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/aum.h"
+
+/*! AUM user lock */
+AST_MUTEX_DEFINE_STATIC(aum_userlock);
+/*! AUM group lock */
+AST_MUTEX_DEFINE_STATIC(aum_grouplock);
+
+STANDARD_LOCAL_USER;
+
+LOCAL_USER_DECL;
+
+/*! \page AUM_desc Asterisk User Managment - AUM - module 
+	\par What is AUM?
+	The AUM module implements common user management. A user
+	can have one or several voicemail accounts, phones, IM accounts
+	and other properties. A common user module mamkes it easier
+	to manage passwords, e-mail addresses and properties that belong
+	to the person who manages a device.
+
+	\par
+	In AUM-enabled Asterisk modules (channels, applications, functions)
+	you can refer to the AUMid and thus fetch configuration data from
+	the AUM module for common properties.
+
+	\par Currently these modules support AUM:
+		- none 
+	\par Modules that may benefit from implementing AUM
+		- all channel drivers
+		- app_disa.c
+		- app_voicemail.c
+		- app_meetme.c
+		- manager.c
+		- The Asterisk CLI
+		- Parking
+
+	\par The AUM User object
+	The AUM user object consist of one general structure and
+	linked lists for addresses, contexts and groups.
+	When installed, the user inherit properties from the groups.
+	\arg \ref aum_user The user object
+	\arg \ref aum_group The group object
+
+	\par
+	The user has a presence state that can be checked with
+	a dial plan function. Presence can be changed from a SIP phone
+	with publish or linked to an IM account (if there's code support
+	for it).
+
+	\par The AUM Address Object
+	The address object consists of a type and a text string.
+	The type can be a phone number, SIP uri, IAX number or 
+	cell phone number.
+
+	\par The AUM group object
+	Group objects are "master" objects that the User inherits
+	properties from.
+
+	There are dial plan functions to check if a user belongs
+	to a user group or not.
+	
+	\par The AUM context object
+	...
+	\par The AUM string object
+	The AUM string object is an encapsulation of a normal C character string,
+	terminated with a zero character. It is a linked list of strings 
+	where each string is clearly marked with character set.
+	If a different character set is asked for, the string handling functions
+	will convert and add a new string in a linked list from the first one.
+
+	- String objects are created with aum_string_alloc()
+	- String objects are destroyed with aum_string_destroy()
+
+	\par Ideas for AUM presence
+	
+	Basically, we need to have a few classical PBX presence indicators
+	with major status and substatus
+	- Away
+		- Meeting
+		- Sick
+		- Travelling
+	- Meeting
+	- Busy
+	- Not reachable (system error, network error)
+	- Custom 
+		- Custom
+	- Agent specific statuses
+
+	For each user, a chain of events need to maintained, current and
+	future events. The handling of past events is up to another system.
+	
+	- For each user, we need to keep track of next planned change.
+	- For planned event changes, check whether the time is mandatory
+	  (should be executed) or a suggestion (don't time out, just keep
+	  current status while waiting for status change).
+	  Example:
+		- Meeting is planned to 13:00, but ran over to 14:15
+		- I am busy to 10:45, open my phone after that.
+	
+	- We need to store events somewhere (event silo) between reloads
+	- Events can come in trough dial plan or manager
+	- Current user status can be changed through dialplan functions,
+	  manager or IM channels/gateways (Jabber, SIP, other)
+	- We need to synch status levels with other IM (SIMPLE/Jabber/XMPP)
+
+	\par Things to do
+	- Implement all core AUM api functions from aum.h
+		- Revise the list
+	- Implement needed function in config engine (if needed)
+	- Implement manager functions for AUM
+		- Read presence
+		- Change presence
+	- Implement dial plan functions
+		- belong_to_group
+		- check_presence
+		- get_email_address
+		- get_sip_address
+	- Implement AUM in channel drivers
+		- Implement in chan_sip.c
+		- Implement in chan_iax2.c
+	- Implement AUM in applications
+		- Implement AUM in app_disa.c
+		- Implement AUM in app_voicemail.c
+	- Implement AUM functions
+		- Callback to register devices with AUM - $AUMUSERPHONE()
+	- Check if we can merge AUM with 
+		- mogorman's jabber patch
+		- file's SIP messaging patch
+	- Can we use aum_groups as callgroups/pickupgroups?
+	- Internationalization issues
+		- Learn how to use utf-8 in source code and convert between different
+	  	strings (firstname, lastname, sip uri etc)
+		- Figure out what character set is used in config and relatime
+	- Continue with other projects
+	- \b Remember: It's only software
+*/
+
+/*------------------------------- Declarations of static functions ---------*/
+enum modulereloadreason {	/* Should be in module.h or something */
+        MODULE__LOAD,
+        MODULE__RELOAD,
+        MODULE_CLI_RELOAD,
+        MODULE_MANAGER_RELOAD,
+};
+
+static void *aum_allocate(size_t size);
+static void aum_free(void *obj);
+static void aum_destroy_user(struct aum_user *user);
+static void aum_destroy_group(struct aum_group *group);
+static struct aum_user *aum_build_user(char *username, struct ast_variable *x, int realtime);
+static struct aum_group *aum_build_group(char *groupname, struct ast_variable *x, int realtime);
+const char *modulereloadreason2txt(enum modulereloadreason reason);
+static const char *aum_addrtype2txt(enum aum_address_type type);
+static enum aum_address_type get_addr_type_from_config_option(enum aum_config_options option);
+static const char *context_type2str(enum aum_context_type type);
+
+
+/*! ----------------------------------------
+\brief AUM General Configuration 
+*/
+/*! \brief Configuration file name */
+char *aum_config_file = "aum.conf";
+
+/*! \brief AUM debugging */
+int aum_debug = 0;
+
+/* Counters */
+int aum_static_users= 0;		/*!< Number of in-memory users */
+int aum_real_users= 0;			/*!< Number of active realtime users */
+int aum_real_groups = 0;		/*!< Number of active realtime groups */
+int aum_static_groups = 0;		/*!< Number of in-memory groups */
+int aum_real_groups_enabled = 0;	/*!< TRUE If realtime groups are enabled */
+int aum_real_users_enabled = 0;		/*!< TRUE if realtime users are enabled */
+
+long aum_memory_used = 0;		/*!< Used memory for the AUM module */
+
+iconv_t	ichandler_utf8_to_iso88591;	/*!< libiconv handler from utf8 to iso8859-1 */
+iconv_t	ichandler_iso88591_to_utf8;	/*!< libiconv handler from iso8859- to utf8 */
+
+/*! \brief the Group list */
+static struct s_aum_grouplist {
+	ASTOBJ_CONTAINER_COMPONENTS(struct aum_group);
+} aum_grouplist;
+
+/*! \brief the User list */
+static struct s_aum_userlist {
+	ASTOBJ_CONTAINER_COMPONENTS(struct aum_user);
+} aum_userlist;
+
+/*! brief Different config options for address formats */
+static struct aum_address_config_struct aum_address_config[] = {
+	{AUM_ADDR_EMAIL, 	"email", 	"E-mail",	AUM_CNF_ADDR_EMAIL},
+	{AUM_ADDR_EMAIL, 	"mailto", 	"E-mail",	AUM_CNF_ADDR_EMAIL},
+	{AUM_ADDR_XMPP,		"xmpp", 	"XMPP/Jabber",	AUM_CNF_ADDR_XMPP},
+	{AUM_ADDR_XMPP,		"jabber", 	"XMPP/Jabber",	AUM_CNF_ADDR_XMPP},	/*! Alias for xmpp */
+	{AUM_ADDR_SIP,		"sip", 		"SIP",		AUM_CNF_ADDR_SIP},	
+	{AUM_ADDR_MSN,		"msn", 		"MSN",		AUM_CNF_ADDR_MSN},
+	{AUM_ADDR_AOL,		"aol", 		"AOL",		AUM_CNF_ADDR_AOL},
+	{AUM_ADDR_TEL,		"tel", 		"Tel",		AUM_CNF_ADDR_TEL},
+	{AUM_ADDR_TEL,		"phone", 	"Tel",		AUM_CNF_ADDR_TEL},
+	{AUM_ADDR_TEL,		"e164", 	"Tel",		AUM_CNF_ADDR_TEL},
+	{AUM_ADDR_CELL_TEL,	"cell", 	"Cell",		AUM_CNF_ADDR_CELL_TEL},
+	{AUM_ADDR_CELL_TEL,	"mobile", 	"Cell",		AUM_CNF_ADDR_CELL_TEL},
+	{AUM_ADDR_IAX2,		"iax", 		"IAX2",		AUM_CNF_ADDR_IAX2},
+	{AUM_ADDR_IAX2,		"iax2", 	"IAX2",		AUM_CNF_ADDR_IAX2},
+	{AUM_ADDR_FWD,		"fwd", 		"FWD",		AUM_CNF_ADDR_FWD},
+	{AUM_ADDR_IAXTEL,	"iaxtel", 	"IAXtel",	AUM_CNF_ADDR_IAXTEL},
+	{AUM_ADDR_FAX,		"fax", 		"Fax",		AUM_CNF_ADDR_FAX},
+	{AUM_ADDR_WEB,		"homepage", 	"Web",		AUM_CNF_ADDR_WEB},
+	{AUM_ADDR_WEB,		"url", 		"Web",		AUM_CNF_ADDR_WEB},
+	{AUM_ADDR_WEB,		"http", 	"Web",		AUM_CNF_ADDR_WEB},
+};
+
+static struct aum_context_table aum_context_text[] = {
+	{AUM_CONTEXT_NONE,		"None" },
+	{AUM_CONTEXT_DEF_CB,		"Callback" },
+	{AUM_CONTEXT_DEF_INCOMING,	"Incoming" },
+	{AUM_CONTEXT_VOICEMAIL,		"Voicemail" },
+	{AUM_CONTEXT_DISA,		"Disa" },
+	{AUM_CONTEXT_SIPSUBSCRIBE,	"SIPsubscribe" },
+};
+
+
+const char *modulereloadreason2txt(enum modulereloadreason reason)
+{
+        switch (reason) {
+        case MODULE__LOAD:       return "LOAD (Channel module load)";
+                                        break;
+        case MODULE__RELOAD:     return "RELOAD (Channel module reload)";
+                                        break;
+        case MODULE_CLI_RELOAD:        return "CLIRELOAD (Channel module reload by CLI command)";
+                                        break;
+        default:        return "MANAGERRELOAD (Channel module reload by manager)";
+                                        break;
+        };
+};
+
+/*! \brief Convert address type to display string */
+static const char *aum_addrtype2txt(enum aum_address_type type) {
+	int x;
+	for (x = 0; x < (sizeof(aum_address_config) / sizeof(struct aum_address_config_struct)); x++) {
+		if (aum_address_config[x].type == type)
+			return aum_address_config[x].display;
+	}
+	return "";
+}
+
+/*----------------------------- CLI COMMANDS ----------------------*/
+
+/*! \brief CLI command description */
+static char cli_aum_show_stats_usage[] = 
+"Usage: aum show stats\n"
+"	Displays some AUM statistics.\n";
+
+/*! \brief CLI command "aum show stats" */
+static int cli_aum_show_stats(int fd, int argc, char *argv[])
+{
+
+	if (argc != 3)
+		return RESULT_SHOWUSAGE;
+	ast_cli(fd, "AUM Statistics\n");
+	ast_cli(fd, "--------------\n\n");
+	ast_cli(fd, "  Allocated memory:      %-10.10ld\n", aum_memory_used);
+	ast_cli(fd, "  Users - static:        %-10.10d\n", aum_static_users);
+	ast_cli(fd, "  Groups - static:       %-10.10d\n", aum_static_groups);
+	if (aum_real_users_enabled)
+		ast_cli(fd, "  Users - realtime:      %-10.10d\n", aum_real_users);
+	if (aum_real_groups_enabled)
+		ast_cli(fd, "  Groups - realtime:     %-10.10d\n", aum_real_groups);
+	ast_cli(fd, "\n\n");
+	
+	return RESULT_SUCCESS;
+}
+
+/*! \brief CLI command description */
+static char cli_aum_show_users_usage[] = 
+"Usage: aum show users\n"
+"	Lists all configured AUM users.\n"
+"	For details on a specific user, use \"aum show user <name>\"\n";
+
+/*! \brief CLI command "aum show users" */
+static int cli_aum_show_users(int fd, int argc, char *argv[])
+{
+	int numusers = 0;
+
+	if (argc != 3)
+		return RESULT_SHOWUSAGE;
+	int numgroups = 0;
+
+	if (argc != 3)
+		return RESULT_SHOWUSAGE;
+	
+	ASTOBJ_CONTAINER_TRAVERSE(&aum_userlist, 1, {
+		ASTOBJ_RDLOCK(iterator);
+		ast_cli(fd, " %-20.20s \n", iterator->name);
+		numusers ++;
+		ASTOBJ_UNLOCK(iterator);
+	} );
+	ast_cli(fd, "-- Number of users: %d\n", numusers);
+	
+	return RESULT_SUCCESS;
+}
+
+/*! \brief CLI command description */
+static char cli_aum_show_user_usage[] = 
+"Usage: aum show user <user>\n"
+"	Lists details about one AUM user.\n"
+"	For a list of all static users, use \"aum show users\"\n";
+
+/*! \brief CLI command "aum show user" */
+static int cli_aum_show_user(int fd, int argc, char *argv[])
+{
+	struct aum_group_member *member;
+	struct aum_address *addr;
+	struct aum_context *context;
+	struct aum_user *user;
+
+	if (argc != 4)
+		return RESULT_SHOWUSAGE;
+	ast_log(LOG_DEBUG, "Trying to find user %s to show... \n", argv[3]);
+
+	user = find_aum_user(argv[3]);
+	if (!user) {
+		ast_cli(fd, "- AUM user %s not found\n", argv[3]);
+		return RESULT_SUCCESS;
+	}
+	ast_cli(fd, "* Userid:        %s\n", user->name);
+	
+	AST_LIST_TRAVERSE(&user->groups, member, list) {
+		ast_cli(fd, " Member of : %s\n", member->group->name);
+	};
+
+	AST_LIST_TRAVERSE(&user->address, addr, list) {
+		ast_cli(fd, " Address   : %s - %s\n", aum_addrtype2txt(addr->type), addr->address);
+	};
+
+	AST_LIST_TRAVERSE(&user->contexts, context, list) {
+		ast_cli(fd, " %s Context : %s\n", context_type2str(context->type), context->context);
+	};
+	
+	return RESULT_SUCCESS;
+}
+
+/*! \brief CLI command description */
+static char cli_aum_show_groups_usage[] = 
+"Usage: aum show groups\n"
+"	Lists all configured AUM groups.\n"
+"	For details on a specific group, use \"aum show group <name>\"\n";
+
+
+/*! \brief CLI command "aum show groups" */
+static int cli_aum_show_groups(int fd, int argc, char *argv[])
+{
+	int numgroups = 0;
+
+	if (argc != 3)
+		return RESULT_SHOWUSAGE;
+	
+	ASTOBJ_CONTAINER_TRAVERSE(&aum_grouplist, 1, {
+		ASTOBJ_RDLOCK(iterator);
+		ast_cli(fd, " %-20.20s %55s\n", iterator->name, (iterator->description ? iterator->description : "") );
+		numgroups ++;
+		ASTOBJ_UNLOCK(iterator);
+	} );
+
+	ast_cli(fd, "-- %d AUM groups\n\n", numgroups);
+
+	return RESULT_SUCCESS;
+}
+
+
+
+/*! \brief CLI entries for the AUM module */
+static struct ast_cli_entry my_clis[] = {
+	{ { "aum", "show", "groups", NULL }, cli_aum_show_groups, "List AUM groups", cli_aum_show_groups_usage },
+	{ { "aum", "show", "users", NULL }, cli_aum_show_users, "List AUM users", cli_aum_show_users_usage },
+	{ { "aum", "show", "user", NULL }, cli_aum_show_user, "List details of AUM user", cli_aum_show_user_usage },
+	{ { "aum", "show", "stats", NULL }, cli_aum_show_stats, "Display AUM statistics", cli_aum_show_stats_usage },
+};
+
+/*----------------------------- DIALPLAN FUNCTIONS ---------------------*/
+static char *func_aumuser_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
+{
+	struct aum_user *user;
+	char *s, *args[2];
+	char *username, *param;
+	int error = 0;
+	char *res = NULL;
+
+	buf[0] = '\0';	/* Reset buffer */
+
+	if (!data) {
+		error = 1;
+	} else {
+		s = ast_strdupa((char *) data);
+		if (!s) {
+			error = 1;
+		} else {
+			ast_app_separate_args(s, '|', args, 2);
+			username = args[0];
+			param = args[1];
+			if (!param)
+				error = 1;
+		}
+	}
+
+	if (error) {
+		ast_log(LOG_ERROR, "This function requires two parameters.\n");
+		return (char*) NULL;
+	}
+	user = find_aum_user(username);
+	if (!user) {
+		ast_log(LOG_ERROR, "AUM user ID %s not found.\n", username);
+		return (char*) NULL;
+	}
+	if (!strcasecmp(param, "email")) {
+		res = aum_find_email_full(user);
+	} else if (!strcasecmp(param, "xmpp")) {
+		res = aum_find_address(user, AUM_ADDR_XMPP);
+	} else if (!strcasecmp(param, "sip")) {
+		res = aum_find_address(user, AUM_ADDR_SIP);
+	} else if (!strcasecmp(param, "tel")) {
+		res = aum_find_address(user, AUM_ADDR_TEL);
+	} else if (!strcasecmp(param, "iax2")) {
+		res = aum_find_address(user, AUM_ADDR_IAX2);
+	} else if (!strcasecmp(param, "fwd")) {
+		res = aum_find_address(user, AUM_ADDR_FWD);
+	} else if (!strcasecmp(param, "numuserid")) {
+		res = user->numuserid;
+	} else if (!strcasecmp(param, "pincode")) {
+		res = user->pincode;
+	} else if (!strcasecmp(param, "firstname")) {
+		res = user->first_name;
+	} else if (!strcasecmp(param, "lastname")) {
+		res = user->first_name;
+	} else if (!strcasecmp(param, "title")) {
+		res = user->title;
+	} else if (!strcasecmp(param, "musicclass")) {
+		res = user->musicclass;
+	} else if (!strcasecmp(param, "language")) {
+		res = user->language;
+	} else if (!strcasecmp(param, "accountcode")) {
+		res = user->accountcode;
+	} else if (!strcasecmp(param, "cidnum")) {
+		 res = user->cid_num;
+	} else if (!strcasecmp(param, "cidname")) {
+		 res = user->cid_name;
+	} else if (!strcasecmp(param, "name")) {
+		 snprintf(buf, sizeof(buf), "%s %s", user->first_name, user->last_name);
+	} else if (!strcasecmp(param, "vmbox")) {
+		 snprintf(buf, sizeof(buf), "%s@%s", user->mailbox, aum_find_user_context(user, AUM_CONTEXT_VOICEMAIL));
+	} else {
+		ast_log(LOG_ERROR, "Unknown parameter: %s\n", param);
+		return (char*) NULL;
+	}
+
+	if (res)
+		ast_copy_string(buf, res, len);
+	return buf;
+}
+
+/*! Dial plan function AUM-USER */
+struct ast_custom_function aum_user_function = {
+	.name = "AUM-USER",
+	.synopsis = "Gets AUM User information",
+	.syntax = "AUM-USER(<userid>,<param>)",
+	.read = func_aumuser_read,
+	.desc = "Valid parameters are:\n"
+	"- name			First and last name\n"
+	"- firstname		First name\n"
+	"- lastname		Last name\n"
+	"- email		Email address\n"
+	"- xmpp			XMPP/Jabber address\n"
+	"- sip			SIP address\n"
+	"- tel			Telephone number\n"
+	"- iax2			IAX2 address\n"
+	"- fwd			FWD number\n"
+	"- numuserid		Numeric User ID\n"
+	"- pincode		User's Pincode\n"
+	"- musicclass		Default music class (MOH)\n"
+	"- accountcode		Account code\n"
+	"- vmbox		Voicemail box for user (mbox at vmcontext)\n"
+	"- cidnum		Caller ID number\n"
+	"- cidname		Caller ID name\n"
+	"\n",
+};
+
+/*-------------------------AUM_STRING SUPPORT--------------------------*/
+static struct aum_string_convert aum_string_labels[] = {
+	{ AUM_CHAR_ASCII,	"ASCII"	},
+	{ AUM_CHAR_ISO8859_1,	"ISO8859-1"	},
+	{ AUM_CHAR_ISO8859_2,	"ISO8859-2"	},
+	{ AUM_CHAR_ISO8859_3,	"ISO8859-3"	},
+	{ AUM_CHAR_UTF8,	"UTF8"	},
+};
+
+aum_string *aum_string_alloc(char *string, enum aum_string_charset charset)
+{
+	aum_string *temp = NULL;
+	if (!string || charset == AUM_CHAR_UNKNOWN)
+		return temp;	/* Null */
+
+	temp = (aum_string *) aum_allocate(sizeof(aum_string));
+	temp->charset = charset;
+	temp->string = strdup(string);
+	temp->size = sizeof(temp->string);
+	aum_memory_used += (long) temp->size;
+
+	return temp;	
+}
+
+void aum_string_destroy(aum_string *string)
+{
+	aum_free(string->string);
+	aum_free(string);
+}
+
+aum_string *aum_string_add_charset_variant(aum_string *string, enum aum_string_charset charset)
+{
+	aum_string *temp = string;
+	aum_string *new = (aum_string *) NULL;
+	char buf[BUFSIZ];
+	size_t newsize = 0, insize, outsize;
+	enum aum_string_charset fromcharset;
+	char *inbuf;
+
+	while (temp && temp->charset != charset)
+		temp = (aum_string *) temp->next;
+
+	if (temp)	/* We got a string already */
+		return temp;
+	
+	fromcharset = string->charset;
+	insize = sizeof(string->string);
+	outsize = sizeof(buf);
+	inbuf = string->string;
+	if (fromcharset == AUM_CHAR_UTF8) {
+		switch (charset) {
+			case AUM_CHAR_ISO8859_1:
+				newsize = iconv(ichandler_utf8_to_iso88591, &inbuf, &insize, &buf, &outsize);
+				break;
+			case AUM_CHAR_ASCII:
+				ast_log(LOG_DEBUG, "Don't know how to convert from utf to ascii yet...\n");
+				break;
+			default:
+				ast_log(LOG_DEBUG, "Don't know how to convert from utf to unknown charset yet...\n");
+				break;
+		}
+	} else if (fromcharset == AUM_CHAR_ISO8859_1) {
+		switch (charset) {
+			case AUM_CHAR_UTF8:
+				newsize = iconv(ichandler_iso88591_to_utf8, &inbuf, &insize, &buf, &outsize);
+				break;
+			case AUM_CHAR_ASCII:
+				ast_log(LOG_DEBUG, "Don't know how to convert from ISO8859-1 to ascii yet...\n");
+				break;
+			default:
+				ast_log(LOG_DEBUG, "Don't know how to convert from utf to unknown charset yet...\n");
+				break;
+		}
+	}
+	if (newsize == (size_t) -1)	/* Could not convert */
+		/* If errno == EILSEQ	Illegal multibyte sequence */
+		/* If errno == EINVAL	Invalid multibyte sequence */
+		/* If errno == E2BIG	Output buffer too small */
+		return temp;		/* ??? */
+
+	new = aum_string_alloc(buf, charset);	/* Allocate object */
+
+	/* Link it in */
+	temp = string->next;
+	string->next = new;
+	new->next = temp;
+
+	return new;
+	
+}
+
+//iconv_t	ichandler_utf8_to_iso88591;	/*!< libiconv handler from utf8 to iso8859-1 */
+//iconv_t	ichandler_iso88591_to_utf8;	/*!< libiconv handler from iso8859- to utf8 */
+// char *aum_string_output(aum_string *string, enum aum_string_charset charset);
+// aum_string *aum_string_add(char *string, enum aum_string_charset defaultcharset);
+
+/*------------------------- CONFIGURATION ------------------------------*/
+static struct aum_config_struct aum_config[] = {
+	{ AUM_CNF_ADDR_EMAIL,	"email" 	,AUM_CONFOBJ_USER },
+	{ AUM_CNF_ADDR_XMPP,	"xmpp" 		,AUM_CONFOBJ_USER },
+	{ AUM_CNF_ADDR_XMPP,	"jabber" 	,AUM_CONFOBJ_USER },
+	{ AUM_CNF_ADDR_SIP,	"sip" 		,AUM_CONFOBJ_USER },
+	{ AUM_CNF_ADDR_IAX2,	"iax" 		,AUM_CONFOBJ_USER },
+	{ AUM_CNF_ADDR_AOL,	"aol" 		,AUM_CONFOBJ_USER },
+	{ AUM_CNF_ADDR_MSN,	"msn" 		,AUM_CONFOBJ_USER },
+	{ AUM_CNF_ADDR_TEL,	"tel" 		,AUM_CONFOBJ_USER },
+	{ AUM_CNF_ADDR_CELL_TEL,"cell" 		,AUM_CONFOBJ_USER },
+	{ AUM_CNF_ADDR_FAX,	"fax" 		,AUM_CONFOBJ_USER },
+	{ AUM_CNF_PIN,		"pin" 		,AUM_CONFOBJ_USER },
+	{ AUM_CNF_VMAILBOX,	"mailbox" 	,AUM_CONFOBJ_USER },
+	{ AUM_CNF_GROUP,	"group" 	,AUM_CONFOBJ_USER },
+	{ AUM_CNF_CALLBACKEXT,	"extension" 	,AUM_CONFOBJ_USER },	/*!< Default extension */
+	{ AUM_CNF_DEFCONTEXT,	"context" 	,AUM_CONFOBJ_USER & AUM_CONFOBJ_GROUP },
+	{ AUM_CNF_SUBSCRIBECONTEXT,	"subscribecontext" 	,AUM_CONFOBJ_USER & AUM_CONFOBJ_GROUP },
+	{ AUM_CNF_DISACONTEXT,	"disacontext" 	,AUM_CONFOBJ_USER & AUM_CONFOBJ_GROUP },

[... 817 lines stripped ...]


More information about the asterisk-commits mailing list