diff --git a/exec/ircbots/ham/ham.js b/exec/ircbots/ham/ham.js
index 844fe9f93cedb300fc8fcb0ca3018ac345451c9a..bb911ef307fad39dddf582aec0fe51018dac4d92 100644
--- a/exec/ircbots/ham/ham.js
+++ b/exec/ircbots/ham/ham.js
@@ -108,7 +108,7 @@ Bot_Commands["CALLSIGN"].command = function (target,onick,ouh,srv,lvl,cmd) {
 
 		if(m && m.length) {
 			var response=new HTTPRequest().Get('http://wireless2.fcc.gov/UlsApp/UlsSearch/'+m[m.length-1]);
-			m=response.match(/In the case of City, state and zip[^-]*?-->([\x00-\xff]*?)<\/td>/);
+			m=response.match(/In the case of City, state and zip[^-]*?-->([\s\S]*?)<\/td>/);
 			if(m) {
 				var info=callsign+':';
 				m[1]=m[1].replace(/<[^>]*>/g,'');
@@ -116,7 +116,7 @@ Bot_Commands["CALLSIGN"].command = function (target,onick,ouh,srv,lvl,cmd) {
 				m[1]=m[1].replace(/\s+/g,' ');
 				info += m[1];
 
-				m=response.match(/>Type<\/td>[\x00-\xff]*?>([^<&]*)[<&]/);
+				m=response.match(/>Type<\/td>[\s\S]*?>([^<&]*)[<&]/);
 				if(m) {
 					m[1]=m[1].replace(/<[^>]*>/g,'');
 					m[1]=m[1].replace(/[\r\n]/g,' ');
@@ -132,7 +132,7 @@ Bot_Commands["CALLSIGN"].command = function (target,onick,ouh,srv,lvl,cmd) {
 					info += ' -  Class: '+m[1];
 				}
 
-				m=response.match(/>Status<\/td>[\x00-\xff]*?>([^<&]*)[<&]/);
+				m=response.match(/>Status<\/td>[\s\S]*?>([^<&]*)[<&]/);
 				if(m) {
 					m[1]=m[1].replace(/<[^>]*>/g,'');
 					m[1]=m[1].replace(/[\r\n]/g,' ');
@@ -140,27 +140,34 @@ Bot_Commands["CALLSIGN"].command = function (target,onick,ouh,srv,lvl,cmd) {
 					info += ' ('+m[1]+')';
 				}
 				srv.o(target,info);
+				return true;
 			}
 			else {
-				srv.o(target, "Unable to parse US callsign info!");
+				return false;
 			}
 		}
 		else {
-			srv.o(target, "Unable to match US callsign!");
+			return false;
 		}
 	}
 
 	function CanadaCallsign(callsign, srv, target) {
-		var result=new HTTPRequest().Post('http://www.callsign.ca/ind.php','indicatif='+callsign);
-		var m=result.match(/<H5>\s*([\x00-\xff]*?)<\/H5/);
+		var result=new HTTPRequest().Post('http://apc-cap.ic.gc.ca/pls/apc_anon/query_amat_cs$callsign.actionquery','P_CALLSIGN='+callsign+'&P_SURNAME=&P_CITY=&P_PROV_STATE_CD=&P_POSTAL_ZIP_CODE=&Z_ACTION=QUERY&Z_CHK=0');
+		var re=new RegExp("<a href=\"(query_amat_cs\\$callsign\\.QueryViewByKey\\?P_CALLSIGN="+callsign.toUpperCase()+"&amp;Z_CHK=[0-9]+)\">"+callsign.toUpperCase()+"</a>");
+		var m=result.match(re);
 		if(m!=null) {
-			m[1]=m[1].replace(/<[^>]*>/g,'');
-			m[1]=m[1].replace(/[\r\n]/g,' ');
-			m[1]=m[1].replace(/\s+/g,' ');
-			srv.o(target, m[1]);
+			result=new HTTPRequest().Get('http://apc-cap.ic.gc.ca/pls/apc_anon/'+m[1].replace(/&amp;/g, '&'));
+			m=result.match(/Call Sign:[\s\S]*?\<td>([^<]+)<[\s\S]*?Amateur Name:[\s\S]*?\<td>([^<]+)<[\s\S]*?Address:[\s\S]*?\<td>([^<]+)<[\s\S]*?City:[\s\S]*?\<td>([^<]+)<[\s\S]*?Province:[\s\S]*?\<td>([^<]+)<[\s\S]*?Postal Code:[\s\S]*?\<td>([^<]+)<[\s\S]*?Qualifications:[\s\S]*?\<td>([^<]+)</);
+			if(m!=null) {
+				srv.o(target, (m[1]+": "+m[2]+", "+m[3]+", "+m[4]+", "+m[5]+" "+m[6]+". "+m[7]).replace(/&nbsp;/g,''));
+				return true;
+			}
+			else {
+				return false;
+			}
 		}
 		else {
-			srv.o(target, "Unable to match Canadian callsign!");
+			return false;
 		}
 	}
 
@@ -169,7 +176,7 @@ Bot_Commands["CALLSIGN"].command = function (target,onick,ouh,srv,lvl,cmd) {
 		var config = new File(system.ctrl_dir + js.global.config_filename);
 		if(!config.open('r')) {
 			log("Unable to open config!");
-			exit(1);
+			return false;
 		}
 
 		req.SetupGet('http://hamcall.net/call?callsign='+callsign);
@@ -179,45 +186,71 @@ Bot_Commands["CALLSIGN"].command = function (target,onick,ouh,srv,lvl,cmd) {
 
 		config.close();
 
-		var m=req.body.match(/Tell them you found it on HamCall.net, the world's largest callsign database!.*?<BR>([\x00-\xff]*?)(<font size|<\/td>)/);
+		var m=req.body.match(/Tell them you found it on HamCall.net, the world's largest callsign database!.*?<BR>([\s\S]*?)(<font size|<\/td>)/);
 		if(m) {
 			m[1]=m[1].replace(/<[^>]*>/g,' ');
 			m[1]=m[1].replace(/[\r\n]/g,' ');
 			m[1]=m[1].replace(/\s+/g,' ');
 			m[1] += ' (Found on HamCall.net)';
 			srv.o(target, m[1]);
+			return true;
 		}
 		else {
-			srv.o(target, "Unable to lookup on HamCall.net");
+			return false;
 		}
 	}
 
 	function USSpecialEvent(callsign,src,target) {
 		var today=strftime("%m%%2F%d%%2F%Y", time());
 		var result=new HTTPRequest().Post('http://www.arrl.org/special-event-stations', '_method=POST&data%5BSearch%5D%5Bcall_sign%5D='+callsign+'&data%5BSearch%5D%5Bkeywords%5D=&data%5BLocation%5D%5Bzip%5D=&data%5BLocation%5D%5Barea%5D=&data%5BLocation%5D%5Bcity%5D=&data%5BLocation%5D%5Bstate%5D=&data%5BLocation%5D%5Bdivision_id%5D=&data%5BLocation%5D%5Bsection_id%5D=&data%5BLocation%5D%5Bcountry%5D=&data%5BDate%5D%5Bstart%5D='+today+'&data%5BDate%5D%5Bend%5D=&=Search');
-		var m=result.match(/<h3>\s*([\x00-\xff]*?)<\/p/);
+		var m=result.match(/<h3>\s*([\s\S]*?)<\/p/);
 		if(m!=null) {
 			m[1]=m[1].replace(/<[^>]*>/g,'');
 			m[1]=m[1].replace(/[\r\n]/g,' ');
 			m[1]=m[1].replace(/\s+/g,' ');
 			srv.o(target, m[1]);
+			return true;
 		}
 		else {
-			srv.o(target, "Unable to match US special event callsign!");
+			return false;
 		}
 	}
 
-	if(callsign.search(/(C[F-K]|C[Y-Z]|V[A-GOXY]|X[J-O])/)==0) {
-		CanadaCallsign(callsign, srv, target);
+	var matched=false;
+	if(!matched && callsign.search(/(C[F-K]|C[Y-Z]|V[A-GOXY]|X[J-O])/)==0) {
+		try {
+			matched=CanadaCallsign(callsign, srv, target);
+		}
+		catch(e) {
+			srv.o(target, "Failed to look up Canadian Callsign: "+e);
+		}
 	}
-	else if(callsign.search(/^\s*(K|N|W)[0-9].\s*$/)==0) {
-		USSpecialEvent(callsign,srv,target);
+	if(!matched && callsign.search(/^\s*(K|N|W)[0-9].\s*$/)==0) {
+		try {
+			matched=USSpecialEvent(callsign,srv,target);
+		}
+		catch(e) {
+			srv.o(target, "Failed to look up Canadian Callsign: "+e);
+		}
+	}
+	if(!matched && callsign.search(/(A[A-L]|K|N|W)/)==0) {
+		try {
+			matched=USCallsign(callsign,srv,target);
+		}
+		catch(e) {
+			srv.o(target, "Failed to look up Canadian Callsign: "+e);
+		}
 	}
-	else if(callsign.search(/(A[A-L]|K|N|W)/)==0) {
-		USCallsign(callsign,srv,target);
+	if(!matched) {
+		try {
+			matched=HamcallCallsign(callsign, srv, target);
+		}
+		catch(e) {
+			srv.o(target, "Failed to look up Canadian Callsign: "+e);
+		}
 	}
-	else {
-		HamcallCallsign(callsign, srv, target);
+	if(!matched) {
+		srv.o(target, "Unable to match callsign in any databases.");
 	}
 
 	return true;