소스 검색

Add gateways and sip profiles to the xml handler.

Mark Crane 12 년 전
부모
커밋
b97f65c28a
1개의 변경된 파일763개의 추가작업 그리고 352개의 파일을 삭제
  1. 763 352
      includes/install/scripts/xml_handler.lua

+ 763 - 352
includes/install/scripts/xml_handler.lua

@@ -24,11 +24,56 @@
 --	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 --	POSSIBILITY OF SUCH DAMAGE.
 
+--to do list
+	--adding gateways
+		--to an array
+		--then add to the sip profiles
+	--system variables
+		--replace ${var} and $${var}.
+
+--set defaults
+	expire = {}
+	expire["directory"] = "90";
+	expire["dialplan"] = "300";
+	expire["sofia.conf"] = "3600";
+
 --set the debug level
 	debug["params"] = false;
 	debug["sql"] = false;
 	debug["xml_request"] = false;
 	debug["xml_string"] = false;
+	debug["cache"] = false;
+
+--include the lua script
+	scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
+	include = assert(loadfile(scripts_dir .. "/resources/config.lua"));
+	include();
+
+--connect to the database
+	--ODBC - data source name
+		if (dsn_name) then
+			dbh = freeswitch.Dbh(dsn_name,dsn_username,dsn_password);
+		end
+	--FreeSWITCH core db handler
+		if (db_type == "sqlite") then
+			dbh = freeswitch.Dbh("core:"..db_path.."/"..db_name);
+		end
+
+--add the trim function
+	function trim(s)
+		return s:gsub("^%s+", ""):gsub("%s+$", "")
+	end
+
+--if the params class and methods do not exist then add them to prevent errors
+	if (not params) then
+		params = {}
+		function params:getHeader(name)
+			self.name = name
+		end
+		function params:serialize(name)
+			self.name = name
+		end
+	end
 
 --show param debug info
 	if (debug["params"]) then
@@ -46,20 +91,8 @@
 	local destination_number = params:getHeader("Caller-Destination-Number");
 	local caller_id_number = params:getHeader("Caller-Caller-ID-Number");
 
---include the lua script
-	scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
-	include = assert(loadfile(scripts_dir .. "/resources/config.lua"));
-	include();
-
---connect to the database
-	--ODBC - data source name
-		if (dsn_name) then
-			dbh = freeswitch.Dbh(dsn_name,dsn_username,dsn_password);
-		end
-	--FreeSWITCH core db handler
-		if (db_type == "sqlite") then
-			dbh = freeswitch.Dbh("core:"..db_path.."/"..db_name);
-		end
+--prepare the api object
+	api = freeswitch.API();
 
 --get the domain_uuid
 	if (domain_name ~= nil) then
@@ -72,17 +105,355 @@
 			domain_uuid = rows["domain_uuid"];
 		end);
 	end
-
---handle gateways
-	if (purpose == "gateways" and profile) then
-		--freeswitch.consoleLog("notice", "[xml_handler] Gateways: " .. profile .." profile\n"); --purpose
+	if (domain_uuid == nil) then
+		domain_uuid = "00000000-0000-0000-0000-000000000000";
 	end
 
+--handle the configuration
+	if (XML_REQUEST["section"] == "configuration") then
+		--sofia.conf - profiles and gateways
+			if (XML_REQUEST["key_value"] == "sofia.conf") then
+
+				--get the cache
+				if (trim(api:execute("module_exists", "mod_memcache")) == "true") then
+					XML_STRING = trim(api:execute("memcache", "get sofia.conf"));
+				else
+					XML_STRING = "-ERR NOT FOUND";
+				end
+
+				if (XML_STRING == "-ERR NOT FOUND") then
+
+					--get the variables
+						vars = trim(api:execute("global_getvar", ""));
+
+					--start the xml array
+						local xml = {}
+						table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
+						table.insert(xml, [[<document type="freeswitch/xml">]]);
+						table.insert(xml, [[	<section name="configuration">]]);
+						table.insert(xml, [[		<configuration name="sofia.conf" description="sofia Endpoint">]]);
+						table.insert(xml, [[			<global_settings>]]);
+						table.insert(xml, [[				<param name="log-level" value="0"/>]]);
+						--table.insert(xml, [[				<param name="auto-restart" value="false"/>]]);
+						table.insert(xml, [[				<param name="debug-presence" value="0"/>]]);
+						--table.insert(xml, [[				<param name="capture-server" value="udp:homer.domain.com:5060"/>]]);
+						table.insert(xml, [[			</global_settings>]]);
+						table.insert(xml, [[			<profiles>]]);
+
+					--set defaults
+						previous_sip_profile_name = "";
+						profile_tag_status = "closed";
+
+					--run the query
+						sql = "select p.sip_profile_name, p.sip_profile_description, s.sip_profile_setting_name, s.sip_profile_setting_value ";
+						sql = sql .. "from v_sip_profiles as p, v_sip_profile_settings as s ";
+						sql = sql .. "where p.sip_profile_uuid = s.sip_profile_uuid ";
+						sql = sql .. "and s.sip_profile_setting_enabled = 'true' ";
+						sql = sql .. "order by p.sip_profile_name asc ";
+						if (debug["sql"]) then
+							freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
+						end
+						x = 0;
+						dbh:query(sql, function(row)
+							--set as variables
+								sip_profile_name = row.sip_profile_name;
+								--sip_profile_description = row.sip_profile_description;
+								sip_profile_setting_name = row.sip_profile_setting_name;
+								sip_profile_setting_value = row.sip_profile_setting_value;
+
+							--open xml tag
+								if (sip_profile_name ~= previous_sip_profile_name) then
+									if (x > 1) then
+										table.insert(xml, [[					</settings>]]);
+										table.insert(xml, [[				</profile>]]);
+									end
+									table.insert(xml, [[				<profile name="]]..sip_profile_name..[[">]]);
+									table.insert(xml, [[					<aliases>]]);
+									table.insert(xml, [[					</aliases>]]);
+									table.insert(xml, [[					<gateways>]]);
+									--table.insert(xml, [[						<X-PRE-PROCESS cmd="include" data="]]..sip_profile_name..[[/*.xml"/>]]);
+
+									--get the gateways
+										if (domain_count > 1) then
+											sql = "select * from v_gateways as g, v_domains as d ";
+											sql = sql .. "where g.profile = '"..sip_profile_name.."' ";
+											sql = sql .. "and g.enabled = 'true' ";
+											sql = sql .. "and g.domain_uuid = d.domain_uuid ";
+										else
+											sql = "select * from v_gateways ";
+											sql = sql .. "where profile = '"..sip_profile_name.."' and enabled = 'true' ";
+										end
+										if (debug["sql"]) then
+											freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
+										end
+										x = 0;
+										dbh:query(sql, function(field)
+											--set as variables
+											gateway = field.gateway;
+											gateway = gateway:gsub(" ", "_");
+
+											if (domain_count > 1) then
+												table.insert(xml, [[						<gateway name="]] .. field.domain_name .."-".. gateway .. [[">]]);
+											else
+												table.insert(xml, [[						<gateway name="]] .. gateway .. [[">]]);
+											end
+
+											if (string.len(field.username) > 0) then
+												table.insert(xml, [[							<param name="username" value="]] .. field.username .. [["/>]]);
+											else
+												table.insert(xml, [[							<param name="username" value="register:false"/>]]);
+											end
+											if (string.len(field.distinct_to) > 0) then
+												table.insert(xml, [[							<param name="distinct-to" value="]] .. field.distinct_to .. [["/>]]);
+											end
+											if (string.len(field.auth_username) > 0) then
+												table.insert(xml, [[							<param name="auth-username" value="]] .. field.auth_username .. [["/>]]);
+											end
+											if (string.len(field.password) > 0) then
+												table.insert(xml, [[							<param name="password" value="]] .. field.password .. [["/>]]);
+											else
+												table.insert(xml, [[							<param name="password" value="register:false"/>]]);
+											end
+											if (string.len(field.realm) > 0) then
+												table.insert(xml, [[							<param name="realm" value="]] .. field.realm .. [["/>]]);
+											end
+											if (string.len(field.from_user) > 0) then
+												table.insert(xml, [[							<param name="from-user" value="]] .. field.from_user .. [["/>]]);
+											end
+											if (string.len(field.from_domain) > 0) then
+												table.insert(xml, [[							<param name="from-domain" value="]] .. field.from_domain .. [["/>]]);
+											end
+											if (string.len(field.proxy) > 0) then
+												table.insert(xml, [[							<param name="proxy" value="]] .. field.proxy .. [["/>]]);
+											end
+											if (string.len(field.register_proxy) > 0) then
+												table.insert(xml, [[							<param name="register-proxy" value="]] .. field.register_proxy .. [["/>]]);
+											end
+											if (string.len(field.outbound_proxy) > 0) then
+												table.insert(xml, [[							<param name="outbound-proxy" value="]] .. field.outbound_proxy .. [["/>]]);
+											end
+											if (string.len(field.expire_seconds) > 0) then
+												table.insert(xml, [[							<param name="expire-seconds" value="]] .. field.expire_seconds .. [["/>]]);
+											end
+											if (string.len(field.register) > 0) then
+												table.insert(xml, [[							<param name="register" value="]] .. field.register .. [["/>]]);
+											end
+
+											if (field.register_transport) then
+												if (field.register_transport == "udp") then
+													table.insert(xml, [[							<param name="register-transport" value="udp"/>]]);
+												elseif (field.register_transport ==  "tcp") then
+													table.insert(xml, [[							<param name="register-transport" value="tcp"/>]]);
+												elseif (field.register_transport == "tls") then
+													table.insert(xml, [[							<param name="register-transport" value="tls"/>]]);
+													table.insert(xml, [[							<param name="contact-params" value="transport=tls"/>]]);
+												else
+													table.insert(xml, [[							<param name="register-transport" value="udp"/>]]);
+												end
+											end
+
+											if (string.len(field.retry_seconds) > 0) then
+												table.insert(xml, [[							<param name="retry-seconds" value="]] .. field.retry_seconds .. [["/>]]);
+											end
+											if (string.len(field.extension) > 0) then
+												table.insert(xml, [[							<param name="extension" value="]] .. field.extension .. [["/>]]);
+											end
+											if (string.len(field.ping) > 0) then
+												table.insert(xml, [[							<param name="ping" value="]] .. field.ping .. [["/>]]);
+											end
+											if (string.len(field.context) > 0) then
+												table.insert(xml, [[							<param name="context" value="]] .. field.context .. [["/>]]);
+											end
+											if (string.len(field.caller_id_in_from) > 0) then
+												table.insert(xml, [[							<param name="caller-id-in-from" value="]] .. field.caller_id_in_from .. [["/>]]);
+											end
+											if (string.len(field.supress_cng) > 0) then
+												table.insert(xml, [[							<param name="supress-cng" value="]] .. field.supress_cng .. [["/>]]);
+											end
+											if (string.len(field.sip_cid_type) > 0) then
+												table.insert(xml, [[							<param name="sip_cid_type" value="]] .. field.sip_cid_type .. [["/>]]);
+											end
+											if (string.len(field.extension_in_contact) > 0) then
+												table.insert(xml, [[							<param name="extension-in-contact" value="]] .. field.extension_in_contact .. [["/>]]);
+											end
+											table.insert(xml, [[						</gateway>]]);
+										end)
+
+									table.insert(xml, [[					</gateways>]]);
+									table.insert(xml, [[					<domains>]]);
+									table.insert(xml, [[						<domain name="all" alias="false" parse="true"/>]]);
+									table.insert(xml, [[					</domains>]]);
+									table.insert(xml, [[					<settings>]]);
+									profile_tag_status = "open";
+								end
+
+							--loop through the var array
+								for line in (vars.."\n"):gmatch"(.-)\n" do
+									if (line) then
+										--name = string.sub( line, 0, pos-1);
+										--value = string.sub( line, pos+1);
+										pos = string.find(line, "=", 0, true);
+										sip_profile_setting_value = sip_profile_setting_value:gsub("%$%${"..string.sub( line, 0, pos-1).."}", string.sub( line, pos+1));
+									end
+								end
+
+							--remove $ and replace with ""
+								--if (sip_profile_setting_value) then
+								--	sip_profile_setting_value = sip_profile_setting_value:gsub("%$", "");
+								--end
+
+							--set the parameters
+								if (sip_profile_setting_name) then
+									table.insert(xml, [[						<param name="]]..sip_profile_setting_name..[[" value="]]..sip_profile_setting_value..[["/>]]);
+								end
+
+							--set the previous value
+								previous_sip_profile_name = sip_profile_name;
+
+							--increment the value of x
+								x = x + 1;
+						end)
+
+					--close the extension tag if it was left open
+						if (profile_tag_status == "open") then
+							table.insert(xml, [[					</settings>]]);
+							table.insert(xml, [[				</profile>]]);
+							profile_tag_status = "close";
+						end
+						table.insert(xml, [[			</profiles>]]);
+						table.insert(xml, [[		</configuration>]]);
+						table.insert(xml, [[	</section>]]);
+						table.insert(xml, [[</document>]]);
+						XML_STRING = table.concat(xml, "\n");
+						if (debug["xml_string"]) then
+							freeswitch.consoleLog("notice", "[xml_handler] XML_STRING: " .. XML_STRING .. "\n");
+						end
+
+					--set the cache
+						result = trim(api:execute("memcache", "set sofia.conf '"..XML_STRING:gsub("'", "&#39;").."' "..expire["sofia.conf"]));
+
+					--send the xml to the console
+						if (debug["xml_string"]) then
+							local file = assert(io.open("/tmp/sofia.conf.xml", "w"));
+							file:write(XML_STRING);
+							file:close();
+						end
+
+					--send to the console
+						if (debug["cache"]) then
+							freeswitch.consoleLog("notice", "[xml_handler] sofia.conf source: database\n");
+						end
+				else
+					--send to the console
+						if (debug["cache"]) then
+							freeswitch.consoleLog("notice", "[xml_handler] sofia.conf source: memcache\n");
+						end
+				end --if XML_STRING
+			end --sofia.conf
+
+		--conference.conf - conference controls, and conference profiles
+			if (XML_REQUEST["key_value"] == "conference.conf") then
+
+				--start the xml array
+					local xml = {}
+					table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
+					table.insert(xml, [[<document type="freeswitch/xml">]]);
+					table.insert(xml, [[	<section name="configuration">]]);
+					table.insert(xml, [[		<configuration name="conference.conf" description="Audio Conference">]]);
+					table.insert(xml, [[			<caller-controls>]]);
+					table.insert(xml, [[				<group name="default">]]);
+					table.insert(xml, [[					<control action="mute" digits=""/>]]);
+					table.insert(xml, [[					<control action="deaf mute" digits=""/>]]);
+					table.insert(xml, [[					<control action="energy up" digits="9"/>]]);
+					table.insert(xml, [[					<control action="energy equ" digits="8"/>]]);
+					table.insert(xml, [[					<control action="energy dn" digits="7"/>]]);
+					table.insert(xml, [[					<control action="vol talk up" digits="3"/>]]);
+					table.insert(xml, [[					<control action="vol talk zero" digits="2"/>]]);
+					table.insert(xml, [[					<control action="vol talk dn" digits="1"/>]]);
+					table.insert(xml, [[					<control action="vol listen up" digits="6"/>]]);
+					table.insert(xml, [[					<control action="vol listen zero" digits="5"/>]]);
+					table.insert(xml, [[					<control action="vol listen dn" digits="4"/>]]);
+					table.insert(xml, [[					<control action="hangup" digits=""/>]]);
+					table.insert(xml, [[				</group>]]);
+					table.insert(xml, [[				<group name="moderator">]]);
+					table.insert(xml, [[					<control action="mute" digits="#"/>]]);
+					table.insert(xml, [[					<control action="deaf mute" digits=""/>]]);
+					table.insert(xml, [[					<control action="energy up" digits="9"/>]]);
+					table.insert(xml, [[					<control action="energy equ" digits="8"/>]]);
+					table.insert(xml, [[					<control action="energy dn" digits="7"/>]]);
+					table.insert(xml, [[					<control action="vol talk up" digits="3"/>]]);
+					table.insert(xml, [[					<control action="vol talk zero" digits="2"/>]]);
+					table.insert(xml, [[					<control action="vol talk dn" digits="1"/>]]);
+					table.insert(xml, [[					<control action="vol listen up" digits="6"/>]]);
+					table.insert(xml, [[					<control action="vol listen zero" digits="5"/>]]);
+					table.insert(xml, [[					<control action="vol listen dn" digits="4"/>]]);
+					table.insert(xml, [[					<control action="hangup" digits=""/>]]);
+					table.insert(xml, [[				</group>]]);
+					table.insert(xml, [[			</caller-controls>]]);
+					table.insert(xml, "");
+					table.insert(xml, [[			<profile name="default">]]);
+					table.insert(xml, [[				<param name="cdr-log-dir" value="auto"/>]]);
+					table.insert(xml, [[				<param name="conference-flags" value="wait-mod" />]]);
+					table.insert(xml, [[				<param name="domain" value="$${domain}"/>]]);
+					table.insert(xml, [[				<param name="rate" value="16000"/>]]);
+					table.insert(xml, [[				<param name="interval" value="20"/>]]);
+					table.insert(xml, [[				<param name="energy-level" value="15"/>]]);
+					table.insert(xml, [[				<param name="auto-gain-level" value="50"/>]]);
+					table.insert(xml, [[				<param name="caller-controls" value="default"/>]]);
+					table.insert(xml, [[				<param name="moderator-controls" value="default"/>]]);
+					table.insert(xml, [[				<param name="muted-sound" value="conference/conf-muted.wav"/>]]);
+					table.insert(xml, [[				<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>]]);
+					table.insert(xml, [[				<param name="alone-sound" value="conference/conf-alone.wav"/>]]);
+					table.insert(xml, [[				<param name="moh-sound" value="$${hold_music}"/>]]);
+					table.insert(xml, [[				<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>]]);
+					table.insert(xml, [[				<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>]]);
+					table.insert(xml, [[				<param name="kicked-sound" value="conference/conf-kicked.wav"/>]]);
+					table.insert(xml, [[				<param name="locked-sound" value="conference/conf-locked.wav"/>]]);
+					table.insert(xml, [[				<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>]]);
+					table.insert(xml, [[				<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>]]);
+					table.insert(xml, [[				<param name="pin-sound" value="conference/conf-pin.wav"/>]]);
+					table.insert(xml, [[				<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>]]);
+					table.insert(xml, [[				<param name="caller-id-name" value="$${outbound_caller_name}"/>]]);
+					table.insert(xml, [[				<param name="caller-id-number" value="$${outbound_caller_id}"/>]]);
+					table.insert(xml, [[				<param name="comfort-noise" value="true"/>]]);
+					table.insert(xml, [[				<param name="auto-record" value="/tmp/test.wav"/>]]);
+					table.insert(xml, [[			</profile>]]);
+
+				--set the xml array and then concatenate the array to a string
+					table.insert(xml, [[		</configuration>]]);
+					table.insert(xml, [[	</section>]]);
+					table.insert(xml, [[</document>]]);
+					XML_STRING = table.concat(xml, "\n");
+
+				--send the xml to the console
+					if (debug["xml_string"]) then
+						local file = assert(io.open("/tmp/conference.conf.xml", "w"));
+						file:write(XML_STRING);
+						file:close();
+					end
+			end --conference.conf
+	end --section configuration
+
 --handle the directory
 	if (XML_REQUEST["section"] == "directory" and key and user and domain_name) then
 
-		--prevent processing for invalid user
+		--set the default
 			continue = true;
+
+		--get the cache
+			if (trim(api:execute("module_exists", "mod_memcache")) == "true") then
+				XML_STRING = trim(api:execute("memcache", "get " .. user .. "@" .. domain_name));
+				if (XML_STRING == "-ERR NOT FOUND") then
+					continue = true;
+				else
+					continue = false;
+				end
+			else
+				XML_STRING = "";
+				continue = true;
+			end
+
+		--prevent processing for invalid user
 			if (user == "*97") then
 				continue = false;
 			end
@@ -159,162 +530,179 @@
 			end
 
 		--outbound hot desking - get the extension variables
-			sql = "SELECT * FROM v_extensions WHERE dial_domain = '" .. domain_name .. "' and dial_user = '" .. user .. "' and enabled = 'true' ";
-			if (debug["sql"]) then
-				freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
+			if (continue) then
+				sql = "SELECT * FROM v_extensions WHERE dial_domain = '" .. domain_name .. "' and dial_user = '" .. user .. "' and enabled = 'true' ";
+				if (debug["sql"]) then
+					freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
+				end
+				dbh:query(sql, function(row)
+					--variables
+					extension_uuid = row.extension_uuid;
+					domain_uuid = row.domain_uuid;
+					extension = row.extension;
+					sip_from_user = row.extension;
+					call_group = row.call_group;
+					hold_music = row.hold_music;
+					toll_allow = row.toll_allow;
+					accountcode = row.accountcode;
+					user_context = row.user_context;
+					effective_caller_id_name = row.effective_caller_id_name;
+					effective_caller_id_number = row.effective_caller_id_number;
+					outbound_caller_id_name = row.outbound_caller_id_name;
+					outbound_caller_id_number = row.outbound_caller_id_number;
+					emergency_caller_id_number = row.emergency_caller_id_number;
+					directory_full_name = row.directory_full_name;
+					directory_visible = row.directory_visible;
+					directory_exten_visible = row.directory_exten_visible;
+					limit_max = row.limit_max;
+					limit_destination = row.limit_destination;
+					sip_force_contact = row.sip_force_contact;
+					sip_force_expires = row.sip_force_expires;
+					nibble_account = row.nibble_account;
+					sip_bypass_media = row.sip_bypass_media;
+				end);
 			end
-			dbh:query(sql, function(row)
-				--variables
-				extension_uuid = row.extension_uuid;
-				domain_uuid = row.domain_uuid;
-				sip_from_user = row.extension;
-				call_group = row.call_group;
-				hold_music = row.hold_music;
-				toll_allow = row.toll_allow;
-				accountcode = row.accountcode;
-				user_context = row.user_context;
-				effective_caller_id_name = row.effective_caller_id_name;
-				effective_caller_id_number = row.effective_caller_id_number;
-				outbound_caller_id_name = row.outbound_caller_id_name;
-				outbound_caller_id_number = row.outbound_caller_id_number;
-				emergency_caller_id_number = row.emergency_caller_id_number;
-				directory_full_name = row.directory_full_name;
-				directory_visible = row.directory_visible;
-				directory_exten_visible = row.directory_exten_visible;
-				limit_max = row.limit_max;
-				limit_destination = row.limit_destination;
-				sip_force_contact = row.sip_force_contact;
-				sip_force_expires = row.sip_force_expires;
-				nibble_account = row.nibble_account;
-				sip_bypass_media = row.sip_bypass_media;
-			end);
 
 		--set the xml array and then concatenate the array to a string
-			if (password) then
-				local xml = {}
-				table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
-				table.insert(xml, [[<document type="freeswitch/xml">]]);
-				table.insert(xml, [[	<section name="directory">]]);
-				table.insert(xml, [[		<domain name="]] .. domain_name .. [[">]]);
-				if (number_alias) then
-					if (cidr) then
-						table.insert(xml, [[			<user id="]] .. extension .. [["]] .. cidr .. number_alias .. [[>]]);
+			if (continue and password) then
+				--build the xml
+					local xml = {}
+					table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
+					table.insert(xml, [[<document type="freeswitch/xml">]]);
+					table.insert(xml, [[	<section name="directory">]]);
+					table.insert(xml, [[		<domain name="]] .. domain_name .. [[">]]);
+					if (number_alias) then
+						if (cidr) then
+							table.insert(xml, [[			<user id="]] .. extension .. [["]] .. cidr .. number_alias .. [[>]]);
+						else
+							table.insert(xml, [[			<user id="]] .. extension .. [["]] .. number_alias .. [[>]]);
+						end
 					else
-						table.insert(xml, [[			<user id="]] .. extension .. [["]] .. number_alias .. [[>]]);
+						if (cidr) then
+							table.insert(xml, [[			<user id="]] .. extension .. [["]] .. cidr .. [[>]]);
+						else
+							table.insert(xml, [[			<user id="]] .. extension .. [[">]]);
+						end
 					end
-				else
-					if (cidr) then
-						table.insert(xml, [[			<user id="]] .. extension .. [["]] .. cidr .. [[>]]);
+					table.insert(xml, [[			<params>]]);
+					table.insert(xml, [[				<param name="password" value="]] .. password .. [["/>]]);
+					table.insert(xml, [[				<param name="vm-enabled" value="]] .. vm_enabled .. [["/>]]);
+					if (string.len(vm_mailto) > 0) then
+						table.insert(xml, [[				<param name="vm-password" value="]] .. vm_password  .. [["/>]]);
+						table.insert(xml, [[				<param name="vm-email-all-messages" value="]] .. vm_enabled  ..[["/>]]);
+						table.insert(xml, [[				<param name="vm-attach-file" value="]] .. vm_attach_file .. [["/>]]);
+						table.insert(xml, [[				<param name="vm-keep-local-after-email" value="]] .. vm_keep_local_after_email .. [["/>]]);
+						table.insert(xml, [[				<param name="vm-mailto" value="]] .. vm_mailto .. [["/>]]);
+					end
+					if (string.len(mwi_account) > 0) then
+						table.insert(xml, [[				<param name="MWI-Account" value="]] .. mwi_account .. [["/>]]);
+					end
+					if (string.len(auth_acl) > 0) then
+						table.insert(xml, [[				<param name="auth-acl" value="]] .. auth_acl .. [["/>]]);
+					end
+					table.insert(xml, [[				<param name="dial-string" value="]] .. dial_string .. [["/>]]);
+					table.insert(xml, [[			</params>]]);
+					table.insert(xml, [[			<variables>]]);
+					table.insert(xml, [[				<variable name="domain_uuid" value="]] .. domain_uuid .. [["/>]]);
+					if (user_context ~= "default" and user_context ~= "public" and user_context ~= "features") then
+						table.insert(xml, [[				<variable name="domain_name" value="]] .. user_context .. [["/>]]);
+					end
+					table.insert(xml, [[				<variable name="caller_id_name" value="]] .. sip_from_user .. [["/>]]);
+					table.insert(xml, [[				<variable name="caller_id_number" value="]] .. sip_from_user .. [["/>]]);
+					if (string.len(call_group) > 0) then
+						table.insert(xml, [[				<variable name="call_group" value="]] .. call_group .. [["/>]]);
+					end
+					if (string.len(hold_music) > 0) then
+						table.insert(xml, [[				<variable name="hold_music" value="]] .. hold_music .. [["/>]]);
+					end
+					if (string.len(toll_allow) > 0) then
+						table.insert(xml, [[				<variable name="toll_allow" value="]] .. toll_allow .. [["/>]]);
+					end
+					if (string.len(accountcode) > 0) then
+						table.insert(xml, [[				<variable name="accountcode" value="]] .. accountcode .. [["/>]]);
+					end
+					table.insert(xml, [[				<variable name="user_context" value="]] .. user_context .. [["/>]]);
+					if (string.len(effective_caller_id_name) > 0) then
+						table.insert(xml, [[				<variable name="effective_caller_id_name" value="]] .. effective_caller_id_name.. [["/>]]);
+					end
+					if (string.len(effective_caller_id_number) > 0) then
+						table.insert(xml, [[				<variable name="effective_caller_id_number" value="]] .. effective_caller_id_number.. [["/>]]);
+					end
+					if (string.len(outbound_caller_id_name) > 0) then
+						table.insert(xml, [[				<variable name="outbound_caller_id_name" value="]] .. outbound_caller_id_name .. [["/>]]);
+					end
+					if (string.len(outbound_caller_id_number) > 0) then
+						table.insert(xml, [[				<variable name="outbound_caller_id_number" value="]] .. outbound_caller_id_number .. [["/>]]);
+					end
+					if (string.len(emergency_caller_id_number) > 0) then
+						table.insert(xml, [[				<variable name="emergency_caller_id_number" value="]] .. emergency_caller_id_number .. [["/>]]);
+					end
+					if (string.len(directory_full_name) > 0) then
+						table.insert(xml, [[				<variable name="directory_full_name" value="]] .. directory_full_name .. [["/>]]);
+					end
+					if (string.len(directory_visible) > 0) then
+						table.insert(xml, [[				<variable name="directory-visible" value="]] .. directory_visible .. [["/>]]);
+					end
+					if (string.len(directory_exten_visible) > 0) then
+						table.insert(xml, [[				<variable name="directory-exten-visible" value="]] .. directory_exten_visible .. [["/>]]);
+					end
+					if (string.len(limit_max) > 0) then
+						table.insert(xml, [[				<variable name="limit_max" value="]] .. limit_max .. [["/>]]);
 					else
-						table.insert(xml, [[			<user id="]] .. extension .. [[">]]);
+						table.insert(xml, [[				<variable name="limit_max" value="5"/>]]);
 					end
-				end
-				table.insert(xml, [[			<params>]]);
-				table.insert(xml, [[				<param name="password" value="]] .. password .. [["/>]]);
-				table.insert(xml, [[				<param name="vm-enabled" value="]] .. vm_enabled .. [["/>]]);
-				if (string.len(vm_mailto) > 0) then
-					table.insert(xml, [[				<param name="vm-password" value="]] .. vm_password  .. [["/>]]);
-					table.insert(xml, [[				<param name="vm-email-all-messages" value="]] .. vm_enabled  ..[["/>]]);
-					table.insert(xml, [[				<param name="vm-attach-file" value="]] .. vm_attach_file .. [["/>]]);
-					table.insert(xml, [[				<param name="vm-keep-local-after-email" value="]] .. vm_keep_local_after_email .. [["/>]]);
-					table.insert(xml, [[				<param name="vm-mailto" value="]] .. vm_mailto .. [["/>]]);
-				end
-				if (string.len(mwi_account) > 0) then
-					table.insert(xml, [[				<param name="MWI-Account" value="]] .. mwi_account .. [["/>]]);
-				end
-				if (string.len(auth_acl) > 0) then
-					table.insert(xml, [[				<param name="auth-acl" value="]] .. auth_acl .. [["/>]]);
-				end
-				table.insert(xml, [[				<param name="dial-string" value="]] .. dial_string .. [["/>]]);
-				table.insert(xml, [[			</params>]]);
-				table.insert(xml, [[			<variables>]]);
-				table.insert(xml, [[				<variable name="domain_uuid" value="]] .. domain_uuid .. [["/>]]);
-				if (user_context ~= "default" and user_context ~= "public" and user_context ~= "features") then
-					table.insert(xml, [[				<variable name="domain_name" value="]] .. user_context .. [["/>]]);
-				end
-				table.insert(xml, [[				<variable name="caller_id_name" value="]] .. sip_from_user .. [["/>]]);
-				table.insert(xml, [[				<variable name="caller_id_number" value="]] .. sip_from_user .. [["/>]]);
-				if (string.len(call_group) > 0) then
-					table.insert(xml, [[				<variable name="call_group" value="]] .. call_group .. [["/>]]);
-				end
-				if (string.len(hold_music) > 0) then
-					table.insert(xml, [[				<variable name="hold_music" value="]] .. hold_music .. [["/>]]);
-				end
-				if (string.len(toll_allow) > 0) then
-					table.insert(xml, [[				<variable name="toll_allow" value="]] .. toll_allow .. [["/>]]);
-				end
-				if (string.len(accountcode) > 0) then
-					table.insert(xml, [[				<variable name="accountcode" value="]] .. accountcode .. [["/>]]);
-				end
-				table.insert(xml, [[				<variable name="user_context" value="]] .. user_context .. [["/>]]);
-				if (string.len(effective_caller_id_name) > 0) then
-					table.insert(xml, [[				<variable name="effective_caller_id_name" value="]] .. effective_caller_id_name.. [["/>]]);
-				end
-				if (string.len(effective_caller_id_number) > 0) then
-					table.insert(xml, [[				<variable name="effective_caller_id_number" value="]] .. effective_caller_id_number.. [["/>]]);
-				end
-				if (string.len(outbound_caller_id_name) > 0) then
-					table.insert(xml, [[				<variable name="outbound_caller_id_name" value="]] .. outbound_caller_id_name .. [["/>]]);
-				end
-				if (string.len(outbound_caller_id_number) > 0) then
-					table.insert(xml, [[				<variable name="outbound_caller_id_number" value="]] .. outbound_caller_id_number .. [["/>]]);
-				end
-				if (string.len(emergency_caller_id_number) > 0) then
-					table.insert(xml, [[				<variable name="emergency_caller_id_number" value="]] .. emergency_caller_id_number .. [["/>]]);
-				end
-				if (string.len(directory_full_name) > 0) then
-					table.insert(xml, [[				<variable name="directory_full_name" value="]] .. directory_full_name .. [["/>]]);
-				end
-				if (string.len(directory_visible) > 0) then
-					table.insert(xml, [[				<variable name="directory-visible" value="]] .. directory_visible .. [["/>]]);
-				end
-				if (string.len(directory_exten_visible) > 0) then
-					table.insert(xml, [[				<variable name="directory-exten-visible" value="]] .. directory_exten_visible .. [["/>]]);
-				end
-				if (string.len(limit_max) > 0) then
-					table.insert(xml, [[				<variable name="limit_max" value="]] .. limit_max .. [["/>]]);
-				else
-					table.insert(xml, [[				<variable name="limit_max" value="5"/>]]);
-				end
-				if (string.len(limit_destination) > 0) then
-					table.insert(xml, [[				<variable name="limit_destination" value="]] .. limit_destination .. [["/>]]);
-				end
-				if (string.len(sip_force_contact) > 0) then
-					table.insert(xml, [[				<variable name="sip_force_contact" value="]] .. sip_force_contact .. [["/>]]);
-				end
-				if (string.len(sip_force_expires) > 0) then
-					table.insert(xml, [[				<variable name="sip-force-expires" value="]] .. sip_force_expires .. [["/>]]);
-				end
-				if (string.len(nibble_account) > 0) then
-					table.insert(xml, [[				<variable name="nibble_account" value="]] .. nibble_account .. [["/>]]);
-				end
-				if (sip_bypass_media == "bypass-media") then
-					table.insert(xml, [[				<variable name="bypass_media" value="true"/>]]);
-				end
-				if (sip_bypass_media == "bypass-media-after-bridge") then
-					table.insert(xml, [[				<variable name="bypass_media_after_bridge" value="true"/>]]);
-				end
-				if (sip_bypass_media == "proxy-media") then
-					table.insert(xml, [[				<variable name="proxy_media" value="true"/>]]);
-				end
-				table.insert(xml, [[				<variable name="record_stereo" value="true"/>]]);
-				table.insert(xml, [[				<variable name="transfer_fallback_extension" value="operator"/>]]);
-				table.insert(xml, [[				<variable name="export_vars" value="domain_name"/>]]);
-				table.insert(xml, [[			</variables>]]);
-				table.insert(xml, [[			</user>]]);
-				table.insert(xml, [[		</domain>]]);
-				table.insert(xml, [[	</section>]]);
-				table.insert(xml, [[</document>]]);
-				XML_STRING = table.concat(xml, "\n");
-			else
-				XML_STRING = "";
-			end
+					if (string.len(limit_destination) > 0) then
+						table.insert(xml, [[				<variable name="limit_destination" value="]] .. limit_destination .. [["/>]]);
+					end
+					if (string.len(sip_force_contact) > 0) then
+						table.insert(xml, [[				<variable name="sip_force_contact" value="]] .. sip_force_contact .. [["/>]]);
+					end
+					if (string.len(sip_force_expires) > 0) then
+						table.insert(xml, [[				<variable name="sip-force-expires" value="]] .. sip_force_expires .. [["/>]]);
+					end
+					if (string.len(nibble_account) > 0) then
+						table.insert(xml, [[				<variable name="nibble_account" value="]] .. nibble_account .. [["/>]]);
+					end
+					if (sip_bypass_media == "bypass-media") then
+						table.insert(xml, [[				<variable name="bypass_media" value="true"/>]]);
+					end
+					if (sip_bypass_media == "bypass-media-after-bridge") then
+						table.insert(xml, [[				<variable name="bypass_media_after_bridge" value="true"/>]]);
+					end
+					if (sip_bypass_media == "proxy-media") then
+						table.insert(xml, [[				<variable name="proxy_media" value="true"/>]]);
+					end
+					table.insert(xml, [[				<variable name="record_stereo" value="true"/>]]);
+					table.insert(xml, [[				<variable name="transfer_fallback_extension" value="operator"/>]]);
+					table.insert(xml, [[				<variable name="export_vars" value="domain_name"/>]]);
+					table.insert(xml, [[			</variables>]]);
+					table.insert(xml, [[			</user>]]);
+					table.insert(xml, [[		</domain>]]);
+					table.insert(xml, [[	</section>]]);
+					table.insert(xml, [[</document>]]);
+					XML_STRING = table.concat(xml, "\n");
 
-		--send the xml to the console
-			if (debug["xml_string"]) then
-				local file = assert(io.open("/tmp/directory.xml", "w"));
-				file:write(XML_STRING);
-				file:close();
+				--set the cache
+					result = trim(api:execute("memcache", "set " .. user .. "@" .. domain_name .. " '"..XML_STRING:gsub("'", "&#39;").."' "..expire["directory"]));
+
+				--send the xml to the console
+					if (debug["xml_string"]) then
+						local file = assert(io.open("/tmp/directory.xml", "w"));
+						file:write(XML_STRING);
+						file:close();
+					end
+
+				--send to the console
+					if (debug["cache"]) then
+						freeswitch.consoleLog("notice", "[xml_handler] directory: " .. user .. "@" .. domain_name .. " source: database\n");
+					end
+			else
+				--send to the console
+					if (debug["cache"]) then
+						if (XML_STRING) then
+							freeswitch.consoleLog("notice", "[xml_handler] directory: " .. user .. "@" .. domain_name .. " source: memcache \n");
+						end
+					end
 			end
 
 		--send the xml to the console
@@ -328,213 +716,236 @@
 		if (debug["params"]) then
 			freeswitch.consoleLog("notice", "[xml_handler] Params:\n" .. params:serialize() .. "\n");
 		end
-		--set the xml array and then concatenate the array to a string
-			local xml = {}
-			table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
-			table.insert(xml, [[<document type="freeswitch/xml">]]);
-			table.insert(xml, [[	<section name="dialplan" description="">]]);
-			table.insert(xml, [[		<context name="]] .. call_context .. [[">]]);
-
-		--set defaults
-			previous_dialplan_uuid = "";
-			previous_dialplan_detail_group = "";
-			previous_dialplan_detail_tag = "";
-			previous_dialplan_detail_type = "";
-			previous_dialplan_detail_data = "";
-			dialplan_tag_status = "closed";
-			condition_tag_status = "closed";
-
-		--get the dialplan and related details
-			sql = "select * from v_dialplans as d, v_dialplan_details as s ";
-			sql = sql .. "where d.dialplan_context = '" .. call_context .. "' ";
-			sql = sql .. "and d.dialplan_enabled = 'true' ";
-			sql = sql .. "and d.dialplan_uuid = s.dialplan_uuid ";
-			sql = sql .. "order by ";
-			sql = sql .. "d.dialplan_order asc, ";
-			sql = sql .. "d.dialplan_name asc, ";
-			sql = sql .. "s.dialplan_detail_group asc, ";
-			sql = sql .. "CASE s.dialplan_detail_tag ";
-			sql = sql .. "WHEN 'condition' THEN 1 ";
-			sql = sql .. "WHEN 'action' THEN 2 ";
-			sql = sql .. "WHEN 'anti-action' THEN 3 ";
-			sql = sql .. "ELSE 100 END, ";
-			sql = sql .. "s.dialplan_detail_order asc ";
-			if (debug["sql"]) then
-				freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
-			end
-			x = 0;
-			dbh:query(sql, function(row)
-				--get the dialplan
-					--domain_uuid = row.domain_uuid;
-					dialplan_uuid = row.dialplan_uuid;
-					--app_uuid = row.app_uuid;
-					--dialplan_context = row.dialplan_context;
-					dialplan_name = row.dialplan_name;
-					--dialplan_number = row.dialplan_number;
-					dialplan_continue = row.dialplan_continue;
-					--dialplan_order = row.dialplan_order;
-					--dialplan_enabled = row.dialplan_enabled;
-					--dialplan_description = row.dialplan_description;
-				--get the dialplan details
-					--dialplan_detail_uuid = row.dialplan_detail_uuid;
-					dialplan_detail_tag = row.dialplan_detail_tag;
-					dialplan_detail_type = row.dialplan_detail_type;
-					dialplan_detail_data = row.dialplan_detail_data;
-					dialplan_detail_break = row.dialplan_detail_break;
-					dialplan_detail_inline = row.dialplan_detail_inline;
-					dialplan_detail_group = row.dialplan_detail_group;
-					--dialplan_detail_order = row.dialplan_detail_order;
-
-				--remove $$ and replace with $
-					dialplan_detail_data = dialplan_detail_data:gsub("%$%$", "$");
-
-				--get the dialplan detail inline
-					detail_inline = "";
-					if (dialplan_detail_inline) then
-						if (string.len(dialplan_detail_inline) > 0) then
-							detail_inline = [[ inline="]] .. dialplan_detail_inline .. [["]];
-						end
-					end
 
-				--close the tags
-					if (condition_tag_status ~= "closed") then
-						if (previous_dialplan_uuid ~= dialplan_uuid) then
-							table.insert(xml, [[				</condition>]]);
-							table.insert(xml, [[			</extension>]]);
-							dialplan_tag_status = "closed";
-							condition_tag_status = "closed";
-						else
-							if (previous_dialplan_detail_group ~= dialplan_detail_group and previous_dialplan_detail_tag == "condition") then
-								table.insert(xml, [[			</condition>]]);
-								condition_tag_status = "closed";
+		--get the cache
+		if (trim(api:execute("module_exists", "mod_memcache")) == "true") then
+			XML_STRING = trim(api:execute("memcache", "get " .. call_context));
+		else
+			XML_STRING = "-ERR NOT FOUND";
+		end
+
+		if (XML_STRING == "-ERR NOT FOUND") then
+			--set the xml array and then concatenate the array to a string
+				local xml = {}
+				table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
+				table.insert(xml, [[<document type="freeswitch/xml">]]);
+				table.insert(xml, [[	<section name="dialplan" description="">]]);
+				table.insert(xml, [[		<context name="]] .. call_context .. [[">]]);
+
+			--set defaults
+				previous_dialplan_uuid = "";
+				previous_dialplan_detail_group = "";
+				previous_dialplan_detail_tag = "";
+				previous_dialplan_detail_type = "";
+				previous_dialplan_detail_data = "";
+				dialplan_tag_status = "closed";
+				condition_tag_status = "closed";
+
+			--get the dialplan and related details
+				sql = "select * from v_dialplans as d, v_dialplan_details as s ";
+				sql = sql .. "where d.dialplan_context = '" .. call_context .. "' ";
+				sql = sql .. "and d.dialplan_enabled = 'true' ";
+				sql = sql .. "and d.dialplan_uuid = s.dialplan_uuid ";
+				sql = sql .. "order by ";
+				sql = sql .. "d.dialplan_order asc, ";
+				sql = sql .. "d.dialplan_name asc, ";
+				sql = sql .. "s.dialplan_detail_group asc, ";
+				sql = sql .. "CASE s.dialplan_detail_tag ";
+				sql = sql .. "WHEN 'condition' THEN 1 ";
+				sql = sql .. "WHEN 'action' THEN 2 ";
+				sql = sql .. "WHEN 'anti-action' THEN 3 ";
+				sql = sql .. "ELSE 100 END, ";
+				sql = sql .. "s.dialplan_detail_order asc ";
+				if (debug["sql"]) then
+					freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
+				end
+				x = 0;
+				dbh:query(sql, function(row)
+					--get the dialplan
+						--domain_uuid = row.domain_uuid;
+						dialplan_uuid = row.dialplan_uuid;
+						--app_uuid = row.app_uuid;
+						--dialplan_context = row.dialplan_context;
+						dialplan_name = row.dialplan_name;
+						--dialplan_number = row.dialplan_number;
+						dialplan_continue = row.dialplan_continue;
+						--dialplan_order = row.dialplan_order;
+						--dialplan_enabled = row.dialplan_enabled;
+						--dialplan_description = row.dialplan_description;
+					--get the dialplan details
+						--dialplan_detail_uuid = row.dialplan_detail_uuid;
+						dialplan_detail_tag = row.dialplan_detail_tag;
+						dialplan_detail_type = row.dialplan_detail_type;
+						dialplan_detail_data = row.dialplan_detail_data;
+						dialplan_detail_break = row.dialplan_detail_break;
+						dialplan_detail_inline = row.dialplan_detail_inline;
+						dialplan_detail_group = row.dialplan_detail_group;
+						--dialplan_detail_order = row.dialplan_detail_order;
+
+					--remove $$ and replace with $
+						dialplan_detail_data = dialplan_detail_data:gsub("%$%$", "$");
+
+					--get the dialplan detail inline
+						detail_inline = "";
+						if (dialplan_detail_inline) then
+							if (string.len(dialplan_detail_inline) > 0) then
+								detail_inline = [[ inline="]] .. dialplan_detail_inline .. [["]];
 							end
 						end
-					end
 
-				--open the tags
-					if (dialplan_tag_status == "closed") then
-						table.insert(xml, [[			<extension name="]] .. dialplan_name .. [[" continue="]] .. dialplan_continue .. [[" uuid="]] .. dialplan_uuid .. [[">]]);
-						dialplan_tag_status = "open";
-					end
-					if (dialplan_detail_tag == "condition") then
-						--determine the type of condition
-							if (dialplan_detail_type == "hour") then
-								condition_type = 'time';
-							elseif (dialplan_detail_type == "minute") then 
-								condition_type = 'time';
-							elseif (dialplan_detail_type == "minute-of-day") then 
-								condition_type = 'time';
-							elseif (dialplan_detail_type == "mday") then 
-								condition_type = 'time';
-							elseif (dialplan_detail_type == "mweek") then 
-								condition_type = 'time';
-							elseif (dialplan_detail_type == "mon") then 
-								condition_type = 'time';
-							elseif (dialplan_detail_type == "yday") then 
-								condition_type = 'time';
-							elseif (dialplan_detail_type == "year") then 
-								condition_type = 'time';
-							elseif (dialplan_detail_type == "wday") then 
-								condition_type = 'time';
-							elseif (dialplan_detail_type == "week") then 
-								condition_type = 'time';
+					--close the tags
+						if (condition_tag_status ~= "closed") then
+							if (previous_dialplan_uuid ~= dialplan_uuid) then
+								table.insert(xml, [[				</condition>]]);
+								table.insert(xml, [[			</extension>]]);
+								dialplan_tag_status = "closed";
+								condition_tag_status = "closed";
 							else
-								condition_type = 'default';
+								if (previous_dialplan_detail_group ~= dialplan_detail_group and previous_dialplan_detail_tag == "condition") then
+									table.insert(xml, [[			</condition>]]);
+									condition_tag_status = "closed";
+								end
 							end
+						end
 
-						--get the condition break attribute
-							condition_break = "";
-							if (dialplan_detail_break) then
-								if (string.len(dialplan_detail_break) > 0) then
-									condition_break = [[ break="]] .. dialplan_detail_break .. [["]];
+					--open the tags
+						if (dialplan_tag_status == "closed") then
+							table.insert(xml, [[			<extension name="]] .. dialplan_name .. [[" continue="]] .. dialplan_continue .. [[" uuid="]] .. dialplan_uuid .. [[">]]);
+							dialplan_tag_status = "open";
+						end
+						if (dialplan_detail_tag == "condition") then
+							--determine the type of condition
+								if (dialplan_detail_type == "hour") then
+									condition_type = 'time';
+								elseif (dialplan_detail_type == "minute") then 
+									condition_type = 'time';
+								elseif (dialplan_detail_type == "minute-of-day") then 
+									condition_type = 'time';
+								elseif (dialplan_detail_type == "mday") then 
+									condition_type = 'time';
+								elseif (dialplan_detail_type == "mweek") then 
+									condition_type = 'time';
+								elseif (dialplan_detail_type == "mon") then 
+									condition_type = 'time';
+								elseif (dialplan_detail_type == "yday") then 
+									condition_type = 'time';
+								elseif (dialplan_detail_type == "year") then 
+									condition_type = 'time';
+								elseif (dialplan_detail_type == "wday") then 
+									condition_type = 'time';
+								elseif (dialplan_detail_type == "week") then 
+									condition_type = 'time';
+								else
+									condition_type = 'default';
 								end
-							end
 
-						if (condition_tag_status == "open") then
-							if (previous_dialplan_detail_tag == "condition") then
-								--add the condition self closing tag
-								if (condition) then
-									if (string.len(condition) > 0) then
-										table.insert(xml, condition .. [[/>]]);
+							--get the condition break attribute
+								condition_break = "";
+								if (dialplan_detail_break) then
+									if (string.len(dialplan_detail_break) > 0) then
+										condition_break = [[ break="]] .. dialplan_detail_break .. [["]];
 									end
 								end
+
+							if (condition_tag_status == "open") then
+								if (previous_dialplan_detail_tag == "condition") then
+									--add the condition self closing tag
+									if (condition) then
+										if (string.len(condition) > 0) then
+											table.insert(xml, condition .. [[/>]]);
+										end
+									end
+								end
+								if (previous_dialplan_detail_tag == "action" or previous_dialplan_detail_tag == "anti-action") then
+									table.insert(xml, [[				</condition>]]);
+									condition_tag_status = "closed";
+									condition_type = "";
+									condition_attribute = "";
+									condition_expression = "";
+								end
 							end
-							if (previous_dialplan_detail_tag == "action" or previous_dialplan_detail_tag == "anti-action") then
-								table.insert(xml, [[				</condition>]]);
-								condition_tag_status = "closed";
-								condition_type = "";
-								condition_attribute = "";
-								condition_expression = "";
-							end
-						end
 
-						--condition tag but leave off the ending
-						if (condition_type == "default") then
-							condition = [[				<condition field="]] .. dialplan_detail_type .. [[" expression="]] .. dialplan_detail_data .. [["]] .. condition_break;
-						elseif (condition_type == "time") then
-							if (condition_attribute) then
-								condition_attribute = condition_attribute .. dialplan_detail_type .. [[="]] .. dialplan_detail_data .. [[" ]];
+							--condition tag but leave off the ending
+							if (condition_type == "default") then
+								condition = [[				<condition field="]] .. dialplan_detail_type .. [[" expression="]] .. dialplan_detail_data .. [["]] .. condition_break;
+							elseif (condition_type == "time") then
+								if (condition_attribute) then
+									condition_attribute = condition_attribute .. dialplan_detail_type .. [[="]] .. dialplan_detail_data .. [[" ]];
+								else
+									condition_attribute = dialplan_detail_type .. [[="]] .. dialplan_detail_data .. [[" ]];
+								end
+								condition_expression = "";
+								condition = ""; --prevents a duplicate time condition
 							else
-								condition_attribute = dialplan_detail_type .. [[="]] .. dialplan_detail_data .. [[" ]];
+								condition = [[				<condition field="]] .. dialplan_detail_type .. [[" expression="]] .. dialplan_detail_data .. [["]] ..  condition_break;
 							end
-							condition_expression = "";
-							condition = ""; --prevents a duplicate time condition
-						else
-							condition = [[				<condition field="]] .. dialplan_detail_type .. [[" expression="]] .. dialplan_detail_data .. [["]] ..  condition_break;
+							condition_tag_status = "open";
 						end
-						condition_tag_status = "open";
-					end
-					if (dialplan_detail_tag == "action" or dialplan_detail_tag == "anti-action") then
-						if (previous_dialplan_detail_tag == "condition") then
-							--add the condition ending
-							if (condition_type == "time") then
-								condition = [[				<condition ]] .. condition_attribute .. condition_break;
-								condition_attribute = ""; --prevents the condition attribute from being used on every condition
-							else
-								if (previous_dialplan_detail_type) then
-									condition = [[				<condition field="]] .. previous_dialplan_detail_type .. [[" expression="]] .. previous_dialplan_detail_data .. [["]] .. condition_break;
+						if (dialplan_detail_tag == "action" or dialplan_detail_tag == "anti-action") then
+							if (previous_dialplan_detail_tag == "condition") then
+								--add the condition ending
+								if (condition_type == "time") then
+									condition = [[				<condition ]] .. condition_attribute .. condition_break;
+									condition_attribute = ""; --prevents the condition attribute from being used on every condition
+								else
+									if (previous_dialplan_detail_type) then
+										condition = [[				<condition field="]] .. previous_dialplan_detail_type .. [[" expression="]] .. previous_dialplan_detail_data .. [["]] .. condition_break;
+									end
 								end
+								table.insert(xml, condition .. [[>]]);
+								condition = ""; --prevents duplicate time conditions
 							end
-							table.insert(xml, condition .. [[>]]);
-							condition = ""; --prevents duplicate time conditions
 						end
-					end
-					if (dialplan_detail_tag == "action") then
-						table.insert(xml, [[					<action application="]] .. dialplan_detail_type .. [[" data="]] .. dialplan_detail_data .. [["]] .. detail_inline .. [[/>]]);
-					end
-					if (dialplan_detail_tag == "anti-action") then
-						table.insert(xml, [[					<anti-action application="]] .. dialplan_detail_type .. [[" data="]] .. dialplan_detail_data .. [["]] .. detail_inline .. [[/>]]);
-					end
+						if (dialplan_detail_tag == "action") then
+							table.insert(xml, [[					<action application="]] .. dialplan_detail_type .. [[" data="]] .. dialplan_detail_data .. [["]] .. detail_inline .. [[/>]]);
+						end
+						if (dialplan_detail_tag == "anti-action") then
+							table.insert(xml, [[					<anti-action application="]] .. dialplan_detail_type .. [[" data="]] .. dialplan_detail_data .. [["]] .. detail_inline .. [[/>]]);
+						end
 
-				--save the previous values
-					previous_dialplan_uuid = dialplan_uuid;
-					previous_dialplan_detail_group = dialplan_detail_group;
-					previous_dialplan_detail_tag = dialplan_detail_tag;
-					previous_dialplan_detail_type = dialplan_detail_type;
-					previous_dialplan_detail_data = dialplan_detail_data;
-
-				--increment the x
-					x = x + 1;
-			end);
-
-		--close the extension tag if it was left open
-			if (dialplan_tag_status == "open") then
-				table.insert(xml, [[				</condition>]]);
-				table.insert(xml, [[			</extension>]]);
-			end
+					--save the previous values
+						previous_dialplan_uuid = dialplan_uuid;
+						previous_dialplan_detail_group = dialplan_detail_group;
+						previous_dialplan_detail_tag = dialplan_detail_tag;
+						previous_dialplan_detail_type = dialplan_detail_type;
+						previous_dialplan_detail_data = dialplan_detail_data;
 
-		--set the xml array and then concatenate the array to a string
-			table.insert(xml, [[		</context>]]);
-			table.insert(xml, [[	</section>]]);
-			table.insert(xml, [[</document>]]);
-			XML_STRING = table.concat(xml, "\n");
+					--increment the x
+						x = x + 1;
+				end);
 
-		--send the xml to the console
-			if (debug["xml_string"]) then
-				local file = assert(io.open("/tmp/dialplan-" .. call_context .. ".xml", "w"));
-				file:write(XML_STRING);
-				file:close();
-			end
+			--close the extension tag if it was left open
+				if (dialplan_tag_status == "open") then
+					table.insert(xml, [[				</condition>]]);
+					table.insert(xml, [[			</extension>]]);
+				end
+
+			--set the xml array and then concatenate the array to a string
+				table.insert(xml, [[		</context>]]);
+				table.insert(xml, [[	</section>]]);
+				table.insert(xml, [[</document>]]);
+				XML_STRING = table.concat(xml, "\n");
+
+			--set the cache
+				result = trim(api:execute("memcache", "set " .. call_context .. " '"..XML_STRING:gsub("'", "&#39;").."' "..expire["dialplan"]));
+
+			--send the xml to the console
+				if (debug["xml_string"]) then
+					local file = assert(io.open("/tmp/dialplan-" .. call_context .. ".xml", "w"));
+					file:write(XML_STRING);
+					file:close();
+				end
+
+			--send to the console
+				if (debug["cache"]) then
+					freeswitch.consoleLog("notice", "[xml_handler] dialplan: "..call_context.." source: database\n");
+				end
+		else
+			--send to the console
+				if (debug["cache"]) then
+					freeswitch.consoleLog("notice", "[xml_handler] dialplan: "..call_context.." source: memcache\n");
+				end
+		end
 	end
 
 --send debug info to the console