using System; using System.Collections; using System.Collections.Generic; using System.Net; using System.Text.RegularExpressions; using System.Web; namespace AsterNET.FastAGI { /// /// Default implementation of the AGIRequest interface. /// public class AGIRequest { #region Variables #if LOGGER private Logger logger = Logger.Instance(); #endif private string rawCallerId; private readonly Dictionary request; /// A map assigning the values of a parameter (an array of Strings) to the name of the parameter. private Dictionary> parameterMap; private string parameters; private string script; private bool callerIdCreated; #endregion #region Constructor - AGIRequest(ICollection environment) /// /// Creates a new AGIRequest. /// /// the first lines as received from Asterisk containing the environment. public AGIRequest(List environment) { if (environment == null) throw new ArgumentException("Environment must not be null."); request = buildMap(environment); } #endregion #region Request public IDictionary Request { get { return request; } } #endregion #region RequestURL /// /// Returns the full URL of the request in the form agi://host[:port][/script]. /// public string RequestURL { get { return request["request"]; } } #endregion #region Channel /// /// Returns the name of the channel. /// /// the name of the channel. public string Channel { get { return request["channel"]; } } #endregion #region UniqueId /// /// Returns the unqiue id of the channel. /// /// the unqiue id of the channel. public string UniqueId { get { return request["uniqueid"]; } } #endregion #region Type /// /// Returns the type of the channel, for example "SIP". /// /// the type of the channel, for example "SIP". public string Type { get { return request["type"]; } } #endregion #region Language /// /// Returns the language, for example "en". /// public string Language { get { return request["language"]; } } #endregion #region CallerId public string CallerId { get { string callerIdName = request["calleridname"]; string callerId = request["callerid"]; if (callerIdName != null) { if (callerId == null || callerId.ToLower(Helper.CultureInfo) == "unknown") return null; return callerId; } return callerId10(); } } #endregion #region CallerIdName public string CallerIdName { get { string callerIdName = request["calleridname"]; if (callerIdName != null) { // Asterisk 1.2 if (callerIdName.ToLower(Helper.CultureInfo) == "unknown") return null; return callerIdName; } return callerIdName10(); } } #endregion #region Asterisk 1.0 CallerID and CallerIdName private string callerId10() { int lbPosition; int rbPosition; if (!callerIdCreated) { rawCallerId = request["callerid"]; callerIdCreated = true; } if (rawCallerId == null) { return null; } lbPosition = rawCallerId.IndexOf('<'); rbPosition = rawCallerId.IndexOf('>'); if (lbPosition < 0 || rbPosition < 0) { return rawCallerId; } return rawCallerId.Substring(lbPosition + 1, (rbPosition) - (lbPosition + 1)); } private string callerIdName10() { int lbPosition; string callerIdName; if (!callerIdCreated) { rawCallerId = request["callerid"]; callerIdCreated = true; } if (rawCallerId == null) return null; lbPosition = rawCallerId.IndexOf('<'); if (lbPosition < 0) return null; callerIdName = rawCallerId.Substring(0, (lbPosition) - (0)).Trim(); if (callerIdName.StartsWith("\"") && callerIdName.EndsWith("\"")) callerIdName = callerIdName.Substring(1, (callerIdName.Length - 1) - (1)); if (callerIdName.Length == 0) return null; return callerIdName; } #endregion #region Dnid public string Dnid { get { string dnid = request["dnid"]; if (dnid == null || dnid.ToLower(Helper.CultureInfo) == "unknown") return null; return dnid; } } #endregion #region Rdnis public string Rdnis { get { string rdnis = request["rdnis"]; if (rdnis == null || rdnis.ToLower(Helper.CultureInfo) == "unknown") return null; return rdnis; } } #endregion #region Context /// /// Returns the context in the dial plan from which the AGI script was called. /// public string Context { get { return request["context"]; } } #endregion #region Extension /// /// Returns the extension in the dial plan from which the AGI script was called. /// public string Extension { get { return request["extension"]; } } #endregion #region Priority /// /// Returns the priority in the dial plan from which the AGI script was called. /// public string Priority { get { if (request["priority"] != null) { return request["priority"]; } return ""; } } #endregion #region Enhanced /// /// Returns wheather this agi is passed audio (EAGI - Enhanced AGI).
/// Enhanced AGI is currently not supported on FastAGI.
/// true if this agi is passed audio, false otherwise. ///
public bool Enhanced { get { if (request["enhanced"] != null && request["enhanced"] == "1.0") return true; return false; } } #endregion #region AccountCode /// /// Returns the account code set for the call. /// public string AccountCode { get { return request["accountCode"]; } } #endregion #region LocalAddress public IPAddress LocalAddress { get; set; } #endregion #region LocalPort public int LocalPort { get; set; } #endregion #region RemoteAddress public IPAddress RemoteAddress { get; set; } #endregion #region RemotePort public int RemotePort { get; set; } #endregion #region Script() /// /// Returns the name of the script to execute. /// public string Script { get { if (script != null) return script; script = request["network_script"]; if (script != null) { Match scriptMatcher = Common.AGI_SCRIPT_PATTERN.Match(script); if (scriptMatcher.Success) { script = scriptMatcher.Groups[1].Value; parameters = scriptMatcher.Groups[2].Value; } } return script; } } #endregion #region CallingAni2 public int CallingAni2 { get { if (request["callingani2"] == null) return -1; try { return Int32.Parse(request["callingani2"]); } catch { } return -1; } } #endregion #region CallingPres public int CallingPres { get { if (request["callingpres"] == null) return -1; try { return Int32.Parse(request["callingpres"]); } catch { } return -1; } } #endregion #region CallingTns public int CallingTns { get { if (request["callingtns"] == null) return -1; try { return Int32.Parse(request["callingtns"]); } catch { } return -1; } } #endregion #region CallingTon public int CallingTon { get { if (request["callington"] == null) return -1; try { return Int32.Parse(request["callington"]); } catch { } return -1; } } #endregion #region Parameter(string name) public string Parameter(string name) { List values; values = ParameterValues(name); if (values == null || values.Count == 0) return null; return values[0]; } #endregion #region ParameterValues(string name) public List ParameterValues(string name) { if (ParameterMap().Count == 0) return null; return parameterMap[name]; } #endregion #region ParameterMap() public Dictionary> ParameterMap() { if (parameterMap == null) parameterMap = parseParameters(parameters); return parameterMap; } #endregion #region ToString() public override string ToString() { return Helper.ToString(this); } #endregion #region buildMap(ICollection lines) /// /// Builds a map containing variable names as key (with the "agi_" prefix stripped) and the corresponding values.
/// Syntactically invalid and empty variables are skipped. ///
/// the environment to transform. /// a map with the variables set corresponding to the given environment. private Dictionary buildMap(List lines) { int colonPosition; string key; string value; var map = new Dictionary(lines.Count); foreach (var line in lines) { colonPosition = line.IndexOf(':'); if (colonPosition < 0 || !line.StartsWith("agi_") || line.Length < colonPosition + 2) continue; key = line.Substring(4, colonPosition - 4).ToLower(Helper.CultureInfo); value = line.Substring(colonPosition + 2); if (value.Length != 0) map.Add(key, value); } return map; } #endregion #region parseParameters(string s) /// /// Parses the given parameter string and caches the result. /// /// the parameter string to parse /// a Map made up of parameter names their values private Dictionary> parseParameters(string parameters) { var result = new Dictionary>(); string name; string val; if (string.IsNullOrEmpty(parameters)) return result; string[] pars = parameters.Split('&'); if (pars.Length == 0) return result; foreach (var parameter in pars) { val = string.Empty; int i = parameter.IndexOf('='); if (i > 0) { name = HttpUtility.UrlDecode(parameter.Substring(0, i)); if (parameter.Length > i + 1) val = HttpUtility.UrlDecode(parameter.Substring(i + 1)); } else if (i < 0) name = HttpUtility.UrlDecode(parameter); else continue; if (!result.ContainsKey(name)) result.Add(name, new List()); result[name].Add(val); } return result; } #endregion } }