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
}
}