/* Copyright (C) 1995 NetWin World, New Zealand, All rights reserved. */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#define ISCONF TRUE
#include "emsg.h"
#include "lib.h"
#include "dnews.h"
#include "sary.h"
#include "nntp.h"
#include "conf.h"

#ifdef unix
/*Should try this without the directory and disk part sys: isn't needed */
#ifdef NETWARE
#define DNEWS_CONFIG "\\system\\dnews.con"
#else
#define DNEWS_CONFIG get_dconfig()
#endif

#else
#define DNEWS_CONFIG "dnews_top:dnews.conf"
#endif

char *get_dconfig(void);

#define MAX_CONF 1000
static char *conf_value[MAX_CONF];
static int conf_true[MAX_CONF];
extern char dnews_conf[];
static int gotconfig;
int config_true(int x)
{
        if (!gotconfig) config_load();
        return conf_true[x];
}

static int item_max;
static int real_max;
int conf_item_max(void)
{
	if (real_max==0) real_max = atoi(config_get(C_REAL_MAX));
	if (real_max==0) real_max = 10000000;
        if (item_max==0) item_max = atoi(config_get(C_ITEM_MAX));
        if (item_max==0) item_max = 1000000;
	if (item_max>real_max) item_max = real_max;
        return item_max;
}

char *config_get(int x)
{
        if (!gotconfig) config_load();
        
        if (conf_value[x]==NULL) {
                return "";
        } else {
                return conf_value[x];
        }
}
void config_load(void)
{
        int i,j;
        char nam[1201];
        char bf[1501];
        char bf3[1501];
	static Sary *config;
	item_max = 0;
        if (config!=NULL) s_free(config);
	gotconfig = TRUE;
        config = s_alloc();
        s_read_sz(config,DNEWS_CONFIG,BFSZ-1);
        if (s_len(config)==0) {
                printf("Unable to find config file {%s} \n",DNEWS_CONFIG);
                exit(1);
        }
        for (i=0; i<MAX_CONF; i++) {
		conf_true[i] = FALSE;
		conf_value[i] = NULL;
	}
	/* conf_true[C_NNTP_SLOW] = TRUE;*/
        for (i=0; i<s_len(config); i++) {
                ncpy(bf,s_line(config,i),500-1);
                ncpy(nam,get_word(bf,0),100);
                strupr(nam);
                if (*nam=='#') continue;
		if (strlen(nam)==0) continue;
                for (j=0; conf_name[j]!=NULL; j++) {
                        if (strcmp(nam,conf_name[j])==0) {
xxx:                            conf_value[j] = mystrdup(get_rest(bf,1),SD_DB);
                                ncpy(bf3,conf_value[j],30);
                                strlwr(bf3); 
                                if (strstr(bf3,"false")!=NULL) conf_true[j] = FALSE;
                                if (strstr(bf3,"true")!=NULL) conf_true[j] = TRUE;
                                if (strstr(bf3,"on")!=NULL) conf_true[j] = TRUE;
                                str_trimtabs(conf_value[j]);
                                break;
                        }
			if (strcmp(nam,"nntp_suck")==0) {j=C_NNTP_SUCK1; goto xxx;}
			if (strcmp(nam,"nntp_suck1")==0) {j=C_NNTP_SUCK1; goto xxx;}
                }
                if (conf_name[j]==NULL) if (strlen(bf)>0) {
                        printf("lib: Configuration line problem line %d {%s} len=%d char=%d (%s)\n",i+1,bf,strlen(bf),bf[0],nam);
                }
        }

        if (conf_value[C_MANAGER]==NULL) conf_value[C_MANAGER] = mystrdup("usenet",SD_DB);
        if (conf_value[C_MYNAME]==NULL) conf_value[C_MYNAME] = mystrdup(nntp_hostname(),SD_DB);
        if (conf_value[C_FROM]==NULL) conf_value[C_FROM] = mystrdup(DNEWS_NAME,SD_DB);
        if (conf_value[C_DF]==NULL) conf_value[C_DF] = mystrdup("df",SD_DB);
        if (conf_value[C_FTS_DIR]!=NULL) conf_true[C_FTS_EXPIRE] = TRUE;
/*        if (conf_value[C_LOG_INLINE]==NULL) conf_true[C_LOG_INLINE] = TRUE;*/
        if (conf_value[C_TCP_NODELAY]==NULL) conf_true[C_TCP_NODELAY] = TRUE;
        if (conf_value[C_LOG_NNTP]==NULL) conf_true[C_LOG_NNTP] = TRUE;
        if (conf_value[C_LIVE_STREAM]==NULL) conf_true[C_LIVE_STREAM] = TRUE;
        if (conf_value[C_REJECT_ADDHIST]==NULL) conf_true[C_REJECT_ADDHIST] = TRUE;
        if (conf_value[C_SORT_LASTMB]==NULL) conf_true[C_SORT_LASTMB] = FALSE;
        if (conf_value[C_AUTH_NOGROUP]==NULL) conf_true[C_AUTH_NOGROUP] = TRUE;
        if (conf_value[C_LOG_FILES]==NULL) conf_true[C_LOG_FILES] = TRUE;
        if (conf_value[C_POST_REC]==NULL) conf_true[C_POST_REC] = TRUE;
        if (conf_value[C_GSTAT]==NULL) conf_true[C_GSTAT] = TRUE;
        if (conf_value[C_XREF_ALWAYS]==NULL) conf_true[C_XREF_ALWAYS] = TRUE;
        if (conf_value[C_HIDE_QUEUE]==NULL) conf_true[C_HIDE_QUEUE] = TRUE;
        if (conf_value[C_POST_CANCEL]==NULL) conf_true[C_POST_CANCEL] = TRUE;
        if (conf_value[C_POST_PROT_PINE]==NULL) conf_true[C_POST_PROT_PINE] = TRUE;
        if (conf_value[C_COMPRESS_DISABLE]==NULL) conf_true[C_COMPRESS_DISABLE] = TRUE;
        if (conf_value[C_AUTHINFO_STRICT]==NULL) conf_true[C_AUTHINFO_STRICT] = TRUE;
        if (conf_value[C_SPAM_IGNORE_PARTS]==NULL) conf_true[C_SPAM_IGNORE_PARTS] = TRUE;
	if (conf_value[C_SLAVE_N]!=NULL) if (atoi(conf_value[C_SLAVE_N])>0) {
	        if (conf_value[C_SLAVE_BYFILE]==NULL) conf_true[C_SLAVE_BYFILE] = TRUE;
	        if (conf_value[C_INDEX_CHANGES]==NULL) conf_true[C_INDEX_CHANGES] = TRUE;			
	}
/* Changed default threading to on for 5.4j4 and later */
        if (conf_value[C_THREAD_TIMEOUT]==NULL) conf_true[C_THREAD_TIMEOUT] = TRUE;

#ifdef DOTHREADS
#ifdef WIN32
#define GOOD_SYSTEM 1
#endif
#endif
#ifdef LINUX
#define GOOD_SYSTEM 1
#endif
#ifdef ISSOLARIS
#define GOOD_SYSTEM 1
#endif

#ifdef GOOD_SYSTEM
        if (conf_value[C_THREAD_IN]==NULL) conf_true[C_THREAD_IN] = TRUE;
#endif


        /*CHANGED default in 5.5a8, prevents continuous rebuilds */
	if (conf_value[C_XOVER_EXPIRE_NORMAL]==NULL) conf_true[C_XOVER_EXPIRE_NORMAL] = TRUE;

        /*CHANGED default in 5.5a6 */
	if (conf_value[C_REINDEX_STACK]==NULL) conf_true[C_REINDEX_STACK] = TRUE;

        if (conf_value[C_SPAWN_EXPIRE]==NULL) conf_true[C_SPAWN_EXPIRE] = TRUE;
/* Changed control_me default to true in 5.3 */
        if (conf_value[C_CONTROL_ME]==NULL) conf_true[C_CONTROL_ME] = TRUE;
/*        if (conf_value[C_CONTROL_RULES_ONLY]==NULL) conf_true[C_CONTROL_RULES_ONLY] = TRUE;*/

        if (conf_value[C_ACCESS_FORWARD]==NULL) conf_true[C_ACCESS_FORWARD] = TRUE;
#ifndef WIN32
        if (conf_value[C_ACCESS_FORWARD]==NULL) conf_true[C_ACCESS_FORWARD] = TRUE;
#endif
	/* debuging index*/
/*         if (conf_value[C_INDEX_DEBUG]==NULL) conf_true[C_INDEX_DEBUG] = TRUE;
*/
        
	conf_true[C_DB_SPLIT] = FALSE; /* buggie so force it */
#ifndef WIN32
        if (conf_value[C_THREAD_REUSE]==NULL) conf_true[C_THREAD_REUSE] = TRUE;
#endif
#ifndef WIN32
        if (conf_value[C_TIMING]==NULL) conf_true[C_TIMING] = TRUE;
#endif
		s_free(config); config = NULL;
}



#ifndef NETWARE
#define dirfix(x) (x)
#endif
char *config_getu(int x)
{
#ifdef unix
        int len;
        static char bf[300];
        ncpy(bf,config_get(x),299);
        len = strlen(bf);
/*RHP mac uses : not slash*/
#ifdef Mac
        if (len>0) if (bf[len-1]!=':') strcat(bf,":");
#else
        if (len>0) if (bf[len-1]!='/') strcat(bf,"/");
#endif
        return dirfix(bf);
#else
        return config_get(x);
#endif  
}
char *config_getu(int x);
char *file_config(char *s)
{
        static char bf[300];
        lprintf(bf,300-1,"%s%s",config_getu(C_CONFIG),s);
        return dirfix(bf);
}
char *file_hist(char *s)
{
        static char bf[300];
        lprintf(bf,300-1,"%s%s",config_getu(C_HISTORY),s);
        return bf;
}

char *file_dnews_config(void)
{
	return DNEWS_CONFIG;
}

char *file_work(char *s)
{
        static char bf[300];
        lprintf(bf,300-1,"%s%s",config_getu(C_WORKAREA),s);
        return bf;
}
char *db_spool_dir(int d);
char *file_spool(int d, char *s)
{
        static char bf[300];
#ifdef VMS
        lprintf(bf,300-1,"%s%s",db_spool_dir(d),s);
#else
        lprintf(bf,300-1,"%s%s",db_spool_dir(d),s);
#endif
        return bf;
}
char *file_fts(char *s)
{
        static char bf[300];
        lprintf(bf,300-1,"%s%s",config_getu(C_WORKAREA),s);
 	if (strlen(config_get(C_FTS_DIR))>0) 
          lprintf(bf,300-1,"%s%s",config_getu(C_FTS_DIR),s);
        return bf;
}
char *file_log(char *s)
{
        static char bf[300];
        lprintf(bf,300-1,"%s%s",config_getu(C_LOGDIR),s);
        return bf;
}
#ifdef NETWARE
#define PFILE file_work("tell.pas")
#else
#define PFILE file_work("tellnews.pass")
#endif
char *conf_getpass(void)
{
        FILE *f;
        char *s;
        char bf[BFSZ];
        static char r[100];
        strcpy(r,"NOPRIV");
again:
        f = xfopen(PFILE,"r");
        if (f==NULL) {
		keeplog("Unable to open file (%s) %s\n",PFILE,strerror(errno));
                if (errno!=ENOENT) {
			emsg("tellnews.pass could not be read %s\n",strerror(errno));
			return r;
		}
		if (!conf_setpass()) return r; 
                goto again;
        }
        if (fgets(bf,20,f)==NULL) {xfclose(f); goto xxx;}
        xfclose(f);
        s = strtok(bf,"\n\t  ");
        if (s!=NULL) strcpy(r,s);
	else {
xxx:		emsg("tellnews.pass was blank\n");
		remove(PFILE);
		keeplog("It was blank (%s) %s\n",PFILE,strerror(errno));
		if (!conf_setpass()) return r;
		goto again;
	}
        return r;
}
int conf_setpass(void)
{
        FILE *f;
	keeplog("conf_setpass called\n");
	if (config_true(C_SETPASS_DISABLE)) return FALSE;

        f = xfopen(PFILE,"w");
        if (f==NULL) {
                filemsg("Can't write %s \n",PFILE);
                return FALSE;
        }
	srand(lib_gmtime());
        fprintf(f,"%d%d",rand()%10000,rand()%10000);   
        xfclose(f);
        return TRUE;
}
int conf_setapass(char *pass)
{
        FILE *f;
	keeplog("conf_setapass called\n");
	if (config_true(C_SETPASS_DISABLE)) return FALSE;
        f = xfopen(PFILE,"w");
        if (f==NULL) {
                filemsg("Can't write %s \n",PFILE);
                return FALSE;
        }
        fprintf(f,"%s",pass);
        xfclose(f);
        return TRUE;
}
/*
        update_at 5* 12,17-7
*/
void test_at(void)
{
/*
        char bf[200];
again:
        printf("Enter text "); gets(bf);
        printf("Match %d \n",conf_isat(bf));
        goto again;*/
}

char *get_fts_dir(void)
{	
	char *s = config_get(C_FTS_DIR);
	if (strlen(s)==0) s = config_get(C_WORKAREA);	
	return s;
}

int conf_isat(char *at)
{       
        time_t ttime;
	struct tm atm;
        struct tm *t;
        char mins[100],hours[100];
        ncpy(mins,get_word(at,0),99);
        ncpy(hours,get_word(at,1),99);
        ttime = time(NULL);
        t = safe_localtime(&ttime,&atm);
        if (time_match(t->tm_min,mins) && time_match(t->tm_hour,hours)) 
                return TRUE;
        return FALSE;   
}
int conf_isat_hour(char *at)
{       
        time_t ttime;
        struct tm *t;
	struct tm atm;
        char mins[100],hours[100];
        strcpy(mins,"*");
        ncpy(hours,get_word(at,1),99);
        ttime = time(NULL);
        t = safe_localtime(&ttime,&atm);
        if (time_match(t->tm_min,mins) && time_match(t->tm_hour,hours)) 
                return TRUE;
        return FALSE;   
}
int time_match(int t, char *at)
{
        int a,b;
        char *s,*w;
        char tmp[200],tstr[200];

        lprintf(tstr,200-1,"%d",t);
        ncpy(tmp,at,100);
        w = strtok(tmp,",");
        for (;w!=NULL;) {
                s = strchr(w,'-');
                if (s!=NULL) {
                        a = atoi(w);
                        b = atoi(s+1);
                        if (a<b) {
                                if (t>=a && t<=b) return TRUE;
                        } else {
                                if (t>=a || t<=b) return TRUE;
                        }
                } else {
                        if (match_wild(w,tstr)) return TRUE;
                }       
                w = strtok(NULL,",");
        }
        return FALSE;
}
#ifdef WIN32
#include <windows.h>
char *get_dconfig(void)
{
        static char sysdir[MAX_PATH];
        static char binpath[MAX_PATH];
	if (strlen(dnews_conf)>0) return dnews_conf;
        GetSystemDirectory(sysdir,MAX_PATH);
        lprintf(binpath,MAX_PATH-1,"%s\\dnews.conf",sysdir);
        return binpath;
}
#else


#ifdef Mac
char *get_dconfig(void)
{
        if (strlen(dnews_conf)==0) lprintf(dnews_conf,BFSZ-1,":%s.conf",dnews_name);
        return dnews_conf;
}
#else
char *get_dconfig(void)
{
#ifdef OS2
        if (strlen(dnews_conf)==0) lprintf(dnews_conf,BFSZ-1,"%s.conf",dnews_name);
#else
        if (strlen(dnews_conf)==0) lprintf(dnews_conf,BFSZ-1,"/etc/%s.conf",dnews_name);
#endif
        return dnews_conf;
}
#endif
#endif

char *file_exe(char *s)
{
#ifdef WIN32
    static char sysdir[MAX_PATH];
        static char binpath[MAX_PATH];
        GetSystemDirectory(sysdir,MAX_PATH);
        lprintf(binpath,MAX_PATH-1,"%s\\%s",sysdir,s);
        return binpath;
#else
    return file_config(s);
#endif
}

