Skip to content
Snippets Groups Projects
callerid.c 36.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • {
    	return ast_is_valid_string(n, "0123456789*#+");
    }
    
    int ast_is_shrinkable_phonenumber(const char *exten)
    {
    	return ast_is_valid_string(exten, "0123456789*#+()-.");
    }
    
    
    int ast_callerid_parse(char *input_str, char **name, char **location)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	char *ls;
    	char *le;
    	char *name_start;
    	char *instr;
    	int quotes_stripped = 0;
    
    	/* Handle surrounding quotes */
    
    	input_str = ast_strip(input_str);
    	instr = ast_strip_quoted(input_str, "\"", "\"");
    	if (instr != input_str) {
    		quotes_stripped = 1;
    	}
    
    
    	/* Try "name" <location> format or name <location> format or with a missing > */
    	if ((ls = strrchr(instr, '<'))) {
    		if ((le = strrchr(ls, '>'))) {
    			*le = '\0';	/* location found, trim off the brackets */
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    
    		*ls = '\0';
    		*location = ls + 1;	/* and this is the result */
    
    		name_start = ast_strip_quoted(instr, "\"", "\"");
    
    	} else {	/* no valid brackets */
    		char tmp[256];
    
    		ast_copy_string(tmp, instr, sizeof(tmp));
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_shrink_phone_number(tmp);
    
    		if (!quotes_stripped && ast_isphonenumber(tmp)) {	/* Assume it's just a location */
    
    			name_start = NULL;
    
    			strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
    
    Mark Spencer's avatar
    Mark Spencer committed
    			*location = instr;
    
    		} else { /* Assume it's just a name. */
    
    Mark Spencer's avatar
    Mark Spencer committed
    			*location = NULL;
    
    			name_start = ast_strip_quoted(instr, "\"", "\"");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    
    	if (name_start) {
    		ast_unescape_quoted(name_start);
    	}
    	*name = name_start;
    
    static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, struct ast_format *codec)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    		number = NULL;
    	return callerid_generate(buf, number, name, 0, callwaiting, codec);
    
    int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	return __ast_callerid_generate(buf, name, number, 0, codec);
    
    int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
    
    {
    	return __ast_callerid_generate(buf, name, number, 1, codec);
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (!unknown)
    		unknown = "<unknown>";
    
    	if (name && num) {
    		char name_buf[128];
    
    		ast_escape_quoted(name, name_buf, sizeof(name_buf));
    		snprintf(buf, bufsiz, "\"%s\" <%s>", name_buf, num);
    	} else if (name) {
    
    		ast_copy_string(buf, name, bufsiz);
    
    	} else if (num) {
    
    		ast_copy_string(buf, num, bufsiz);
    
    		ast_copy_string(buf, unknown, bufsiz);
    
    int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	char *tmp;
    	char *l = NULL, *n = NULL;
    
    	tmp = ast_strdupa(buf);
    	ast_callerid_parse(tmp, &n, &l);
    	if (n)
    
    		ast_copy_string(name, n, namelen);
    
    	else
    		name[0] = '\0';
    
    	if (l) {
    		ast_shrink_phone_number(l);
    
    		ast_copy_string(num, l, numlen);
    
    	} else
    		num[0] = '\0';
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    	const char *name;
    	const char *description;
    
    /*! \brief Translation table for Caller ID Presentation settings */
    static const struct ast_value_translation pres_types[] = {
    /* *INDENT-OFF* */
    	{ AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED,        "allowed_not_screened",  "Presentation Allowed, Not Screened" },
    	{ AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN,     "allowed_passed_screen", "Presentation Allowed, Passed Screen" },
    	{ AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN,     "allowed_failed_screen", "Presentation Allowed, Failed Screen" },
    	{ AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER,                "allowed",               "Presentation Allowed, Network Number" },
    
    	{ AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED,     "prohib_not_screened",   "Presentation Prohibited, Not Screened" },
    	{ AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN,  "prohib_passed_screen",  "Presentation Prohibited, Passed Screen" },
    	{ AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN,  "prohib_failed_screen",  "Presentation Prohibited, Failed Screen" },
    	{ AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER,             "prohib",                "Presentation Prohibited, Network Number" },
    
    	{ AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER,            "unavailable",           "Number Unavailable" }, /* Default name to value conversion. */
    	{ AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED,    "unavailable",           "Number Unavailable" },
    	{ AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_FAILED_SCREEN, "unavailable",           "Number Unavailable" },
    	{ AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_PASSED_SCREEN, "unavailable",           "Number Unavailable" },
    /* *INDENT-ON* */
    };
    
    /*!
     * \brief Convert caller ID text code to value (used in config file parsing)
     * \param data text string from config file
     * \retval value AST_PRES_ from callerid.h
     * \retval -1 if not in table
     */
    
    int ast_parse_caller_presentation(const char *data)
    {
    
    	for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
    		if (!strcasecmp(pres_types[index].name, data)) {
    			return pres_types[index].value;
    		}
    
    /*!
     * \brief Convert caller ID pres value to explanatory string
     * \param data AST_PRES_ value from callerid.h
     * \return string for human presentation
     */
    
    const char *ast_describe_caller_presentation(int data)
    {
    
    	for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
    		if (pres_types[index].value == data) {
    			return pres_types[index].description;
    		}
    
    /*!
     * \brief Convert caller ID pres value to text code
     * \param data AST_PRES_ value from callerid.h
     * \return string for config file
     */
    
    const char *ast_named_caller_presentation(int data)
    {
    
    	for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
    		if (pres_types[index].value == data) {
    			return pres_types[index].name;
    		}
    
    
    /*! \brief Translation table for redirecting reason settings */
    static const struct ast_value_translation redirecting_reason_types[] = {
    /* *INDENT-OFF* */
    	{ AST_REDIRECTING_REASON_UNKNOWN,        "unknown",      "Unknown" },
    	{ AST_REDIRECTING_REASON_USER_BUSY,      "cfb",          "Call Forwarding Busy" },
    	{ AST_REDIRECTING_REASON_NO_ANSWER,      "cfnr",         "Call Forwarding No Reply" },
    	{ AST_REDIRECTING_REASON_UNAVAILABLE,    "unavailable",  "Callee is Unavailable" },
    	{ AST_REDIRECTING_REASON_UNCONDITIONAL,  "cfu",          "Call Forwarding Unconditional" },
    	{ AST_REDIRECTING_REASON_TIME_OF_DAY,    "time_of_day",  "Time of Day" },
    	{ AST_REDIRECTING_REASON_DO_NOT_DISTURB, "dnd",          "Do Not Disturb" },
    	{ AST_REDIRECTING_REASON_DEFLECTION,     "deflection",   "Call Deflection" },
    	{ AST_REDIRECTING_REASON_FOLLOW_ME,      "follow_me",    "Follow Me" },
    	{ AST_REDIRECTING_REASON_OUT_OF_ORDER,   "out_of_order", "Called DTE Out-Of-Order" },
    	{ AST_REDIRECTING_REASON_AWAY,           "away",         "Callee is Away" },
    	{ AST_REDIRECTING_REASON_CALL_FWD_DTE,   "cf_dte",       "Call Forwarding By The Called DTE" },
    
    	{ AST_REDIRECTING_REASON_SEND_TO_VM,     "send_to_vm",   "Call is being redirected to user's voicemail" },
    
    	/* Convenience SIP aliases.  Alias descriptions are not used. */
    	{ AST_REDIRECTING_REASON_USER_BUSY,      "user-busy" },
    	{ AST_REDIRECTING_REASON_NO_ANSWER,      "no-answer" },
    	{ AST_REDIRECTING_REASON_UNCONDITIONAL,  "unconditional" },
    	{ AST_REDIRECTING_REASON_TIME_OF_DAY,    "time-of-day" },
    	{ AST_REDIRECTING_REASON_DO_NOT_DISTURB, "do-not-disturb" },
    	{ AST_REDIRECTING_REASON_FOLLOW_ME,      "follow-me" },
    	{ AST_REDIRECTING_REASON_OUT_OF_ORDER,   "out-of-service" },
    
    /* *INDENT-ON* */
    };
    
    int ast_redirecting_reason_parse(const char *data)
    {
    	int index;
    
    	for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
    		if (!strcasecmp(redirecting_reason_types[index].name, data)) {
    			return redirecting_reason_types[index].value;
    		}
    	}
    
    	return -1;
    }
    
    const char *ast_redirecting_reason_describe(int data)
    {
    	int index;
    
    	for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
    		if (redirecting_reason_types[index].value == data) {
    
    			return redirecting_reason_types[index].description ?: "Redirecting reason alias-bug";
    
    const char *ast_redirecting_reason_name(const struct ast_party_redirecting_reason *data)
    
    	if (!ast_strlen_zero(data->str)) {
    		/* Use this string if it has been set. Otherwise, use the table. */
    		return data->str;
    	}
    
    
    	for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
    
    		if (redirecting_reason_types[index].value == data->code) {
    
    			return redirecting_reason_types[index].name;
    		}
    	}
    
    	return "not-known";
    }
    
    /*! \brief Translation table for connected line update source settings */
    static const struct ast_value_translation connected_line_source_types[] = {
    /* *INDENT-OFF* */
    	{ AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN,           "unknown",           "Unknown" },
    	{ AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER,            "answer",            "Normal Call Answering" },
    	{ AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION,         "diversion",         "Call Diversion (Deprecated, use REDIRECTING)" },
    	{ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,          "transfer_active",   "Call Transfer(Active)" },
    	{ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,          "transfer",          "Call Transfer(Active)" },/* Old name must come after new name. */
    	{ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, "transfer_alerting", "Call Transfer(Alerting)" }
    /* *INDENT-ON* */
    };
    
    int ast_connected_line_source_parse(const char *data)
    {
    	int index;
    
    	for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
    		if (!strcasecmp(connected_line_source_types[index].name, data)) {
    			return connected_line_source_types[index].value;
    		}
    	}
    
    	return -1;
    }
    
    const char *ast_connected_line_source_describe(int data)
    {
    	int index;
    
    	for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
    		if (connected_line_source_types[index].value == data) {
    			return connected_line_source_types[index].description;
    		}
    	}
    
    	return "not-known";
    }
    
    const char *ast_connected_line_source_name(int data)
    {
    	int index;
    
    	for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
    		if (connected_line_source_types[index].value == data) {
    			return connected_line_source_types[index].name;
    		}
    	}
    
    	return "not-known";
    }
    
    
    /*! \brief Translation table for ast_party_name char-set settings */
    static const struct ast_value_translation party_name_charset_tbl[] = {
    /* *INDENT-OFF* */
    	{ AST_PARTY_CHAR_SET_UNKNOWN,               "unknown",      "Unknown" },
    	{ AST_PARTY_CHAR_SET_ISO8859_1,             "iso8859-1",    "ISO8859-1" },
    	{ AST_PARTY_CHAR_SET_WITHDRAWN,             "withdrawn",    "Withdrawn" },
    	{ AST_PARTY_CHAR_SET_ISO8859_2,             "iso8859-2",    "ISO8859-2" },
    	{ AST_PARTY_CHAR_SET_ISO8859_3,             "iso8859-3",    "ISO8859-3" },
    	{ AST_PARTY_CHAR_SET_ISO8859_4,             "iso8859-4",    "ISO8859-4" },
    	{ AST_PARTY_CHAR_SET_ISO8859_5,             "iso8859-5",    "ISO8859-5" },
    	{ AST_PARTY_CHAR_SET_ISO8859_7,             "iso8859-7",    "ISO8859-7" },
    	{ AST_PARTY_CHAR_SET_ISO10646_BMPSTRING,    "bmp",          "ISO10646 Bmp String" },
    	{ AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING,  "utf8",         "ISO10646 UTF-8 String" },
    /* *INDENT-ON* */
    };
    
    int ast_party_name_charset_parse(const char *data)
    {
    	int index;
    
    	for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
    		if (!strcasecmp(party_name_charset_tbl[index].name, data)) {
    			return party_name_charset_tbl[index].value;
    		}
    	}
    
    	return -1;
    }
    
    const char *ast_party_name_charset_describe(int data)
    {
    	int index;
    
    	for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
    		if (party_name_charset_tbl[index].value == data) {
    			return party_name_charset_tbl[index].description;
    		}
    	}
    
    	return "not-known";
    }
    
    const char *ast_party_name_charset_str(int data)
    {
    	int index;
    
    	for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
    		if (party_name_charset_tbl[index].value == data) {
    			return party_name_charset_tbl[index].name;
    		}
    	}
    
    	return "not-known";
    }