/*
 * Copyright (c) 2010-2019 Belledonne Communications SARL.
 *
 * This file is part of Liblinphone.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/* enum lookup code */

#ifndef _WIN32_WCE
#include <errno.h>
#endif

#include <string.h>

#include "enum.h"

#define DNS_ANSWER_MAX_SIZE 2048


static char *create_enum_domain(const char *number){
	long len=(long)strlen(number);
	char *domain=reinterpret_cast<char *>(ms_malloc((size_t)(len*2)+10));
	long i,j;

	for (i=0,j=len-1;j>=0;j--){
		domain[i]=number[j];
		i++;
		domain[i]='.';
		i++;
	}
	strcpy(&domain[i],"e164.arpa");
	ms_message("enum domain for %s is %s",number,domain);
	return domain;
}


static bool_t is_a_number(const char *str){
	char *p=(char *)str;
	bool_t res=FALSE;
	bool_t space_found=FALSE;
	for(;;p++){
		switch(p[0]){
			case '9':
			case '8':
			case '7':
			case '6':
			case '5':
			case '4':
			case '3':
			case '2':
			case '1':
			case '0':
				res=TRUE;
				if (space_found) return FALSE; /* avoid splited numbers */
				break;
			case '\0':
				return res;
				break;
			case ' ':
				space_found=TRUE;
				break;
			default:
				return FALSE;
		}
	}
	return FALSE;
}
//4970072278724
bool_t is_enum(const char *sipaddress, char **enum_domain){
	const char *p;
	p=strstr(sipaddress,"sip:");
	if (p==NULL) return FALSE; /* enum should look like sip:4369959250*/
	else p+=4;
	if (is_a_number(p)){
		if (enum_domain!=NULL){
			*enum_domain=create_enum_domain(p);
		}
		return TRUE;
	}
	return FALSE;
}



int enum_lookup(const char *enum_domain, enum_lookup_res_t **res){
	int err;
	//char dns_answer[DNS_ANSWER_MAX_SIZE];
	char *begin,*end;
	char *host_result, *command;
	int i;
	bool_t forkok;
	/*
	ns_msg handle;
	int count;

	memset(&handle,0,sizeof(handle));
	*res=NULL;
	ms_message("Resolving %s...",enum_domain);

	err=res_search(enum_domain,ns_c_in,ns_t_naptr,dns_answer,DNS_ANSWER_MAX_SIZE);
	if (err<0){
		ms_warning("Error resolving enum:",herror(h_errno));
		return -1;
	}
	ns_initparse(dns_answer,DNS_ANSWER_MAX_SIZE,&handle);
	count=ns_msg_count(handle,ns_s_an);

	for(i=0;i<count;i++){
		ns_rr rr;
		memset(&rr,0,sizeof(rr));
		ns_parserr(&handle,ns_s_an,i,&rr);
		ms_message("data=%s",ns_rr_rdata(rr));
	}
	*/
	command=ms_strdup_printf("host -t naptr %s",enum_domain);
	forkok=lp_spawn_command_line_sync(command,&host_result,&err);
	ms_free(command);
	if (forkok){
		if (err!=0){
			ms_warning("Host exited with %i error status.",err);
			return -1;
		}
	}else{
		ms_warning("Could not spawn the \'host\' command.");
		return -1;
	}
	ms_message("Answer received from dns (err=%i): %s",err,host_result);

	begin=strstr(host_result,"sip:");
	if (begin==0) {
		ms_warning("No sip address found in dns naptr answer.");
		return -1;
	}
	*res=reinterpret_cast<enum_lookup_res_t *>(ms_malloc0(sizeof(enum_lookup_res_t)));
	err=0;
	for(i=0;i<MAX_ENUM_LOOKUP_RESULTS;i++){
		end=strstr(begin,"!");
		if (end==NULL) goto parse_error;
		end[0]='\0';
		(*res)->sip_address[i]=ms_strdup(begin);
		err++;
		begin=strstr(end+1,"sip:");
		if (begin==NULL) break;
	}
	ms_free(host_result);
	return err;

	parse_error:
		ms_free(*res);
		ms_free(host_result);
		*res=NULL;
		ms_warning("Parse error in enum_lookup().");
		return -1;
}

void enum_lookup_res_free(enum_lookup_res_t *res){
	int i;
	for (i=0;i<MAX_ENUM_LOOKUP_RESULTS;i++){
		if (res->sip_address[i]!=NULL) ms_free(res->sip_address[i]);
	}
	ms_free(res);
}
