/*-
 * Copyright (c) 1998-2005 Joao Cabral
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *      DHIS(c)  Dynamic Host Information System Release 5
 */

#include "dhisd.h"
#include "db.h"
#include "misc.h"

db_t *dbase=NULL;

unsigned char dbase_file[256];

int db_add_service(unsigned char *service,db_service_t **sbp) {

	struct service_s *sp;
	db_service_t *bp;
		
	sp=service_get_by_name(service);
	if(sp==NULL) return(1);
	
	bp=(*sbp);
	if(bp==NULL) {
		(*sbp)=(db_service_t *)malloc(sizeof(db_service_t));
		if(*sbp == NULL) return(1);
		bp=(*sbp);
	} else {
		while(bp->next!=NULL) bp=bp->next;
		bp->next=(db_service_t *)malloc(sizeof(db_service_t));
		if(bp->next==NULL) return(1);
		bp=bp->next;
	}
	bp->next=NULL;
	bp->sp=sp;
	return(0);
}
	

int db_reload(void) {

	FILE *fp;
	unsigned char str[1024];
	db_t *rec;
	unsigned char keyn[1024];

	if(dbase!=NULL) db_free();

	DSYSLOG(1,(LOG_DEBUG,"db_reload(): Loading DHIS database %s\n",dbase_file));

	fp=fopen(dbase_file,"r");
	if(fp==NULL) return(0);
	while(fgets(str,1024,fp)!=NULL) {
	 off_nl(str);
         if(strchr(line_entry(1,str),';')==NULL)
	 if(!strcmp(line_entry(2,str),"{")) {
		unsigned char cmd[64];
		char *cp;
		rec=(db_t *)malloc(sizeof(db_t));
		if(rec==NULL) { fclose(fp); return(0); }
		rec->id=atoi(line_entry(1,str));
		rec->ltod=0;
		rec->oncmd[0]='\0';
		rec->offcmd[0]='\0';
		rec->service=NULL;
		rec->xstage=0;
		rec->refresh=NEXT_CHECK;
		rec->atype=0;
		keyn[0]='\0';
		do {
		if(fgets(str,1024,fp)==NULL) 
		{
		fclose(fp);
		if(rec->atype==AQRC) mpz_clear(rec->authn);
		free(rec);
		return(0);
		}
		off_nl(str);

		strcpy(cmd,line_entry(1,str));
		strtolower(cmd);
		if(!strcmp(cmd,"hostpass")) {
			strcpy(rec->pass,line_entry(2,str));
			rec->atype=APASS;

                        if((cp=strchr(rec->pass,';'))!=NULL)
                                *cp='\0';

		}

		if(!strcmp(cmd,"oncmd")) {
			strcpy(rec->oncmd,line_ptr(2,str));
                        if((cp=strchr(rec->oncmd,';'))!=NULL)
                                *cp='\0';
		}
		if(!strcmp(cmd,"offcmd")) {
			strcpy(rec->offcmd,line_ptr(2,str));
                        if((cp=strchr(rec->offcmd,';'))!=NULL)
                                *cp='\0';
		}
		if(!strcmp(cmd,"service")) {
			if(db_add_service(line_entry(2,str),&(rec->service))) {
			syslog(LOG_ERR,"Failed to load service %s for %d",
				line_entry(2,str),rec->id);

			DSYSLOG(1,(LOG_DEBUG,"db_reload(): Failed to load service %s for %d\n",
				   line_entry(2,str),rec->id));

			}
		}

		if(!strcmp(cmd,"authn")) {
			strcat(keyn,line_entry(2,str));
                        if((cp=strchr(keyn,';'))!=NULL)
                                *cp='\0';
			rec->atype=AQRC;
		}
		
		} while(strcmp(line_entry(1,str),"}"));
		
		if(!rec->atype) free(rec); else
		if(rec->atype==AQRC && keyn[0]=='\0') free(rec); else {
			if(rec->atype==AQRC) {
			mpz_init(rec->authn);
			mpz_set_str(rec->authn,keyn,10);
			}
			if(rec->service==NULL) 
				db_add_service("default",&(rec->service));
			db_add(rec);
		}

		DSYSLOG(1,(LOG_DEBUG,"db_reload(): Read record %d\n",rec->id));

	 } /* End if */
	} /* End while */
	fclose(fp);

	DSYSLOG(1,(LOG_DEBUG,"db_reload(): Database loaded\n"));

	return(1);
}

int db_free() {

	db_t *p1,*p2;

	if(dbase==NULL) return(1);
	p1=dbase;
	while(p1!=NULL) {
		db_service_t *dbp;
		
		while(p1->service!=NULL) {
		dbp=p1->service->next;
		free(p1->service);
		p1->service=dbp;
		}
		p2=p1;
		p1=p1->next;
		if(p2->atype==AQRC) mpz_clear(p2->authn);
		if(p2->atype==AQRC && p2->xstage==1) mpz_clear(p2->x); 
		free(p2);
	}
	dbase=NULL;
	return(1);
}


unsigned char *db_password(int id) {

	db_t *p;
	static unsigned char pass[MAX_PASS];

	p=dbase;
	while(p!=NULL) {
		if(p->id==id) {
			strcpy(pass,p->pass);
			return(pass);
		}
		p=p->next;
	}
	return(NULL);
}

int db_add(db_t *rec) {

	db_t *p;
	p=dbase;
	if(dbase==NULL) {
	dbase=rec;
	dbase->next=NULL;
	return(1);
	}

	while(p->next!=NULL) p=p->next;
	p->next=rec;
	p->next->next=NULL;
	return(1);
}


int db_get_ltod(int id) {

	db_t *p;

	p=dbase;
	while(p!=NULL) {
		if(id==p->id) 
			return(p->ltod);
		p=p->next;
	}
	return(0);
}

int db_set_ltod(int id,int ltod) {

	db_t *p;

	p=dbase;
	while(p!=NULL) {
		if(p->id==id) {
			p->ltod=ltod;

			DSYSLOG(1,(LOG_DEBUG,"db_set_ltod(): Setting LTOD to %d on %d\n",
				   p->ltod,p->id));

			return(1);
		}
		p=p->next;
	}
	return(0);
}

db_service_t *db_get_service_by_id(int id) {

	db_t *dp;
	dp=dbase;
	while(dp!=NULL) {
	if(dp->id==id) return(dp->service);
	dp=dp->next;
	}
	return(NULL);
}

unsigned char *db_get_oncmd(int id) {
	db_t *dp;
	dp=dbase;
	while(dp!=NULL) {
	if(dp->id==id) return(dp->oncmd);
	dp=dp->next;
	}
	return(NULL);
}

unsigned char *db_get_offcmd(int id) {
	db_t *dp;
	dp=dbase;
	while(dp!=NULL) {
	if(dp->id==id) return(dp->offcmd);
	dp=dp->next;
	}
	return(NULL);
}

