asternet/Asterisk.2013/Asterisk.NET/FastAGI/AGIRequest.cs

578 lines
15 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
namespace AsterNET.FastAGI
{
/// <summary>
/// Default implementation of the AGIRequest interface.
/// </summary>
public class AGIRequest
{
#region Variables
#if LOGGER
private Logger logger = Logger.Instance();
#endif
private string rawCallerId;
private readonly Dictionary<string, string> request;
/// <summary> A map assigning the values of a parameter (an array of Strings) to the name of the parameter.</summary>
private Dictionary<string, List<string>> parameterMap;
private string parameters;
private string script;
private bool callerIdCreated;
#endregion
#region Constructor - AGIRequest(ICollection environment)
/// <summary>
/// Creates a new AGIRequest.
/// </summary>
/// <param name="environment">the first lines as received from Asterisk containing the environment.</param>
public AGIRequest(List<string> 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
/// <summary>
/// Returns the full URL of the request in the form agi://host[:port][/script].
/// </summary>
public string RequestURL
{
get { return request["request"]; }
}
#endregion
#region Channel
/// <summary>
/// Returns the name of the channel.
/// </summary>
/// <returns>the name of the channel.</returns>
public string Channel
{
get { return request["channel"]; }
}
#endregion
#region UniqueId
/// <summary>
/// Returns the unqiue id of the channel.
/// </summary>
/// <returns>the unqiue id of the channel.</returns>
public string UniqueId
{
get { return request["uniqueid"]; }
}
#endregion
#region Type
/// <summary>
/// Returns the type of the channel, for example "SIP".
/// </summary>
/// <returns>the type of the channel, for example "SIP".</returns>
public string Type
{
get { return request["type"]; }
}
#endregion
#region Language
/// <summary>
/// Returns the language, for example "en".
/// </summary>
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
/// <summary>
/// Returns the context in the dial plan from which the AGI script was called.
/// </summary>
public string Context
{
get { return request["context"]; }
}
#endregion
#region Extension
/// <summary>
/// Returns the extension in the dial plan from which the AGI script was called.
/// </summary>
public string Extension
{
get { return request["extension"]; }
}
#endregion
#region Priority
/// <summary>
/// Returns the priority in the dial plan from which the AGI script was called.
/// </summary>
public string Priority
{
get
{
if (request["priority"] != null)
{
return request["priority"];
}
return "";
}
}
#endregion
#region Enhanced
/// <summary>
/// Returns wheather this agi is passed audio (EAGI - Enhanced AGI).<br />
/// Enhanced AGI is currently not supported on FastAGI.<br />
/// true if this agi is passed audio, false otherwise.
/// </summary>
public bool Enhanced
{
get
{
if (request["enhanced"] != null && request["enhanced"] == "1.0")
return true;
return false;
}
}
#endregion
#region AccountCode
/// <summary>
/// Returns the account code set for the call.
/// </summary>
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()
/// <summary>
/// Returns the name of the script to execute.
/// </summary>
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<string> values;
values = ParameterValues(name);
if (values == null || values.Count == 0)
return null;
return values[0];
}
#endregion
#region ParameterValues(string name)
public List<string> ParameterValues(string name)
{
if (ParameterMap().Count == 0)
return null;
return parameterMap[name];
}
#endregion
#region ParameterMap()
public Dictionary<string, List<string>> 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)
/// <summary>
/// Builds a map containing variable names as key (with the "agi_" prefix stripped) and the corresponding values.<br />
/// Syntactically invalid and empty variables are skipped.
/// </summary>
/// <param name="lines">the environment to transform.</param>
/// <returns> a map with the variables set corresponding to the given environment.</returns>
private Dictionary<string, string> buildMap(List<string> lines)
{
int colonPosition;
string key;
string value;
var map = new Dictionary<string, string>(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)
/// <summary>
/// Parses the given parameter string and caches the result.
/// </summary>
/// <param name="s">the parameter string to parse</param>
/// <returns> a Map made up of parameter names their values</returns>
private Dictionary<string, List<string>> parseParameters(string parameters)
{
var result = new Dictionary<string, List<string>>();
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<string>());
result[name].Add(val);
}
return result;
}
#endregion
}
}