/* Copyright (C) 1995 NetWin World, New Zealand, All rights reserved. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifdef isunix
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#endif

#include "dnews.h"
#include "conf.h"
#include "lib.h"
#include "emsg.h"
#include "nntp.h"
#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif
char *reg_address(void)   ;
char *reg_address2(void) ;
char *reg_address3(void);
char *hide_data(char *a, char *b, char *c);
char *unhide_data(char *s);
int debug_lvl;
char dnews_conf[BFSZ];
int do_register(void);
int isslave;
int slave_i;
int isbusy;
char *strip_cr(char *out);
void do_user_add(int argc, char *argv[]);

int main(int argc, char *argv[])
{
        char bf[300];
        static char bf2[300];
	int r=0;
        char out[1001];
        char myname[300];
	int xx;
        char *s,*z;
        char aline[8000];
        int c;
        int i,n;
	int isnotbusy = FALSE;
#ifdef Mac
	
	SetApplLimit(GetApplLimit()-100000);

#endif
#ifdef OS2x
	setvbuf(stdin,NULL,_IONBF,1000);
	setvbuf(stdout,NULL,_IONBF,1000);
#endif

	if (argc>30) {
		printf("Too many arguments, on unix you must quote wild card arguments\ne.g. tellnews cached \"rec.*\"\n");
		return 1;
	}
        nntp_startup();
        for (i=1; i<argc; i++) {
#ifndef KEYLIB
                if (strcmp(argv[i],"register")==0) {do_register(); return 0;}
                if (strcmp(argv[i],"REGISTER")==0) {do_register(); return 0;}
                if (strcmp(argv[i],"-register")==0) {do_register(); return 0;}
#endif
                if (strcmp(argv[i],"-adduser")==0) {do_user_add(argc,argv); return 0;}
                if (strcmp(argv[i],"-testing")==0) {do_testing(); return 0;}
                if (strncmp(argv[i],"-s",2)==0) {
                        isslave = TRUE;
			z = argv[i];
			if (isdigit(z[2])) slave_i = atoi(z+2);
			else {
				slave_i = atoi(argv[i+1]);
	                        i++;
			}
		} else if (strncmp(argv[i],"-c",2)==0) {
                        strcpy(dnews_conf,argv[i+1]);
                        i++;
                } else {
                        strcat(bf2,argv[i]);
                        strcat(bf2," ");
                }
        }
#ifdef Mac
again:
		printf("Enter tellnews command> ");
		gets(bf2);
		if (strcmp(bf2,"register")==0) {do_register(); goto again;}
		if (strcmp(bf2,"REGISTER")==0) {do_register(); goto again;}
#endif
        sprintf(bf,"fcmd %s %s",conf_getpass(),bf2);
        strcat(bf,"\015\012");


        strcpy(myname,config_get(C_BIND_IN));
        if (strlen(myname)==0) strcpy(myname,config_get(C_MYNAME));
	if (isslave) {
		xx = atoi(config_get(C_SLAVE_PORTS)) ;
		if (xx==0) xx = 7500;
		sprintf(bf2,"%s:%d",myname,xx+ slave_i);
		strcpy(myname,bf2);
		goto gotit;
	} else {
		/* connect to master by default if running dmulti */
		xx = atoi(config_get(C_SLAVE_N));
		if (xx>1) {
		    xx = atoi(config_get(C_SLAVE_PORTS));
		    if (xx==0) xx = 7500;
		    sprintf(bf2,"%s:%d",myname,xx);
		    strcpy(myname,bf2);
		    goto gotit;
		}
	}
	
	if (strlen(config_get(C_PORT))>0) {
                strcat(myname,":"); 
                strcat(myname,config_get(C_PORT));
        }
        
gotit:
	nntp_alwaysblock();
        c = nntp_open(myname);
        if (c<0) {
		r = 1;
		goto the_end;
        }
        nntp_setblock(c,TRUE); /* Set to blocking IO */
        nntp_write_s(c,bf,strlen(bf)); 
        strcpy(bf,"quit\015\012");
        nntp_write_s(c,bf,strlen(bf)); 

        n = nntp_read(c,out,1000);
        for (;n>=0;) {
                out[n] = 0;
                out[n+1] = 0;
		if (strstr(out,"is not busy")!=NULL) isnotbusy = TRUE;
		if (strstr(out,"is still busy")!=NULL) isbusy = TRUE;
#ifdef Mac
				strcat(aline,out);
				aline[strlen(aline)+1] = 0;
				for (s = strchr(aline,'\n'); s!=NULL; ) {
					*s = 0;
					if (strlen(aline)>0) if (aline[strlen(aline)-1]=='\015') aline[strlen(aline)-1] = 0;
					printf("%s\n",aline);
					memcpy(aline,s+1,strlen(s+1)+1);
					s = strchr(aline,'\n');
				}				

#else
                printf("%s",strip_cr(out));
#endif
                n = nntp_read(c,out,1000);
              
        }
#ifdef Mac
	goto again;
#endif
the_end:
	if (isbusy) return 0;
	if (isnotbusy) return 1;
#ifdef NETWARE
	mem_exit();
#endif
        return r;
}
char *group_name(int i)
{
        return "(none)";
}
char *group_name_x(int i)
{
        return "(none)";
}
char *strip_cr(char *out)
{
	char *s = out;
	for (;*s!=0;s++) {
	  if (*s=='\r') {
		memmove(s,s+1,strlen(s));	
	  }
	}
	return out;
}

int dmsg(char * arg_list, ...)
{
        return TRUE;
}
int  filemsg(char * arg_list, ...)
{
        va_list arg_ptr;
        char *format, output[1000];
        va_start(arg_ptr, arg_list);
        format = arg_list;
        vsprintf(output, format, arg_ptr);
        perror("File error:");
        printf("%s",output);
	return TRUE;
}
void fimsg(char * arg_list, ...)
{
        va_list arg_ptr;
        char *format, output[1000];
        va_start(arg_ptr, arg_list);
        format = arg_list;
        vsprintf(output, format, arg_ptr);
        perror("File error:");
        printf("%s",output);

}
int imsg(const char * arg_list, ...)
{
        va_list arg_ptr;
        char *format, output[1000];
        va_start(arg_ptr, arg_list);
        format = (char *) arg_list;
        vsprintf(output, format, arg_ptr);
	return 0;
/* printf("%s",output); */
}
int wmsg(char * arg_list, ...)
{
        va_list arg_ptr;
        char *format, output[1000];
        va_start(arg_ptr, arg_list);
        format = arg_list;
        vsprintf(output, format, arg_ptr);
        printf("%s",output);
	return 0;
}
int emsg(char * arg_list, ...)
{
        va_list arg_ptr;
        char *format, output[1000];
        va_start(arg_ptr, arg_list);
        format = arg_list;
        vsprintf(output, format, arg_ptr);
        printf("%s",output);
	return 0;
}
#ifndef unix
int lib_mail_filezz(char *to, char *subj, char *fname)
{
        return TRUE;
}
int lib_freespace(char *s)
{
        return 100000;
}
#endif
int diskuse_get(void)
{
        return 0;
}
char *nt_pcname(void);

int do_register(void)
{
        FILE *f;
        char *tname[]={"1 485 Full License"
                , "8 345 2 Gig, unlimited users"
		, "3 222 Limited License"
                , "7 95 Single User License"
                , "4 free license for school", "5 320 Support for school"
                , "5 320 Support", "6 2950 Priority"
		
                 };
        char name[200],org[200],email[200],rtype[200],phone[200],fax[200];
        char address1[200];
        char address2[200];
        char address3[200];
        char comments[200];
        char where[200];
	char isp[200];
        char visa_number[200];
        char visa_name[200];
        char visa_expirey[200];
        char visa_type[200];
        char bf[500];
        char *s;
	int rrtype;

        printf("\n\nDNEWS Registration \n");
        printf("Your Name ? "); gets(name);
        printf("Company or Organization Name ? "); gets(org);
        printf("Phone Number (include area code) ? "); gets(phone);
        printf("Fax Number (include area code) ? "); gets(fax);
        printf("Email address ? "); gets(email);
        printf("Address line 1/3 ? "); gets(address1);
        printf("Address line 2/3 ? "); gets(address2);
        printf("Address line 3/3 ? "); gets(address3);
        printf("Registration type: (we mail invoices except for type 3) \n");
        printf(" 1) Full version with unlimited user access and 1 years email help & upgrades US$485 \n");
        printf(" 2) Limited to 2Gig, Unlimited users, plus 1 years email help & upgrades US$345 \n");
        printf(" 3) Lite version with 2 concurrent user access and 1 years email help US$222\n");
        printf(" 4) Single User license and 1 years email help US$95\n");
        printf(" 5) School or University using DNEWS for non profit use with no support\n");
        printf(" 6) School or University using DNEWS with email support and updates US$320\n");
        printf(" 7) Extending support and updates for 12 months US$320 \n");
        printf(" 8) Priority support with remote assistance for 12 months US$2950 \n");

again:  printf("Registration type 1-8 ? "); gets(rtype);
        if (atoi(rtype)<=0) goto again;
        if (atoi(rtype)>8) goto again;
	rrtype = atoi(rtype);
        printf("NOTE: Payment is required before a permanent license key will be issued\n");
        printf("Fill in these details if you wish to pay by VISA/Master/AMEX card\n");
        printf("Credit card type (Visa/Master/AMEX) ? "); gets(visa_type);
        printf("Name of card holder ? "); gets(visa_name);
        printf("Credit Card Number ? "); gets(visa_number);
        printf("Credit Card Expirey date ? "); gets(visa_expirey);
        
/*        printf("Who is your Internet Service/Access Provider, give EMAIL or HTML\nISP ? "); gets(isp);*/
        printf("Comments ? "); gets(comments);
        printf("Where did you first hear about DNEWS \ne.g. Magazine, Web page, Friend, please give details ? "); gets(where);

        f = fopen("register.txt","w");
        if (f==NULL) {perror("Cannot open register.txt"); return TRUE;}
        fprintf(f,"Email this file to  %s \n\n",reg_address()); 
        fprintf(f,"Please register my copy of DNEWS, my details are:\n\n");     
        fprintf(f,"Name: %s\n",name);
        fprintf(f,"Version: %s\n",DNEWS_VERSION);
        fprintf(f,"ComputerName: %s\n",host_details());
        fprintf(f,"ComputerType: %s\n",SYSTEM_TYPE);
        fprintf(f,"Organization: %s\n",org);
        fprintf(f,"Email: %s\n",email); 
        fprintf(f,"FAX: %s\n",fax);     
        fprintf(f,"Phone: %s\n",phone); 
        fprintf(f,"Address1: %s\n",address1);
        fprintf(f,"Address2: %s\n",address2);
        fprintf(f,"Address3: %s\n",address3);
        fprintf(f,"Type: %s\n",tname[rrtype-1]);

        sprintf(bf,"%s:%s",visa_type,visa_name);
        s = hide_data(bf,visa_number,visa_expirey);
        strcpy(bf,s); bf[60] = 0;
        fprintf(f,"Data1: %s\n",bf);
        strcpy(bf,s+60); bf[60] = 0;
        fprintf(f,"Data2: %s\n",bf);
        strcpy(bf,s+120); bf[60] = 0;
        fprintf(f,"Data3: %s\n",bf);

        fprintf(f,"Comments: %s\n",comments);
        fprintf(f,"Where: %s\n",where);
        fprintf(f,"ISP: %s\n",isp);
        fclose(f);
        printf("Note: If you plan to install dnews on a machine with a different\n");
        printf("      computer name then you should modify register.txt before sending it\n");
        printf("\n Orders can also be sent to:\n");
        printf("        %s\n",reg_address2());
        printf("        %s\n",reg_address3());
        printf("\nNow email register.txt to %s (or your local reseller)\n",reg_address());
        return TRUE;
}
char *reg_address(void)
{
        static char bf[512];
        strcpy(bf,config_get(C_RESELL_MAIL));
        if (strlen(bf)==0) strcpy(bf,"netwin@netwinsite.com");
        return bf;
}
char *reg_address2(void)
{
        static char bf[512];
        strcpy(bf,config_get(C_RESELL_ADDRESS1));
        if (strlen(bf)==0) strcpy(bf,"NetWin, PO Box 27-574, Mt Roskill, Auckland, New Zealand.");
        return bf;
}
char *reg_address3(void)
{
        static char bf[512];
        strcpy(bf,config_get(C_RESELL_ADDRESS2));
        if (strlen(bf)==0) strcpy(bf,"FAX: +64-9630-0689 ");
        return bf;
}
char *lib_findfile(char *x)
{
        return NULL;
}
void dnews_manager_report(char *s)
{
        
}
int post_local(String *xitem, char *addr, int ismod)
{
        return TRUE;
}
void dnews_exit(char *reason, char *file, int line)
{
        printf("Crashing\n");
        exit(1);
}



#ifdef WIN32
#define KEY_COMPUTER_NAME "SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName"
#include <windows.h>
#include <winnt.h>
char *nt_pcname(void)
{
    HKEY MyKey;
        static    char Line[64];
    int  linelen = 64;
    DWORD type_of_entry, result;

        RegCreateKey(HKEY_LOCAL_MACHINE, KEY_COMPUTER_NAME, &MyKey);
        result = RegQueryValueEx(MyKey, "ComputerName", 0, &type_of_entry, 
                (unsigned char *)Line, &linelen);
        RegCloseKey(MyKey);
        if (result == ERROR_SUCCESS && type_of_entry == REG_SZ) {
                return Line;
        }
	return "127.0.0.1";
}

#endif


int xtable[281];
#define xswitch(aa,bb) {cc=aa; aa=bb; bb=cc;}
char *hide_data(char *a, char *b, char *c)
{
        static unsigned char bf[BFSZ];
        static char out[BFSZ];
        unsigned char *s;
        int i,x,j,cc;
        sprintf((char *) bf,"%s|%s|%s|||",a,b,c);

        for (i=0; i<180; i++) xtable[i] = i;
        for (i=0,x=0,j=0; i<180; i++,x+=5,j+=11) {
                xswitch(xtable[i],xtable[(i*i+x+j) % 180]);
        }
        for (i=0,x=0; i<180; i++,x+=19) out[i] = ((x+i*i*123) % 26) + 'a';
        
        for (s=bf; *s!=0; s++) {
                if (*s==' ') *s = '~';
                if (*s=='\t') *s = '^';
                if (*s>='0' && *s<='9') *s = '0' + 9 - (*s - '0');
                if (*s>='a' && *s<='z') *s = 'a' + 25 - (*s - 'a');
                if (*s>='A' && *s<='Z') *s = 'A' + 25 - (*s - 'A');
        }
        for (i=0; (i<80) && (bf[i]!=0); i++) {
                out[xtable[i]] = bf[i];
        }               
        out[180] = 0;
        return out;
}
#ifdef WIN32
char *nt_other(void)
{
	return "";
}
#endif
int lib_msec(void)
{
	return 1;
}
#define FILE_USERS file_config("users.dat")
#define FILE_USERS_NEW file_config("users.new")

int user_add(char *user, char *pass, char *full, char *groups, char *access, char *access_wild,  char *msg);
int user_del(char *user, char *pass, char *msg);
/* tellnews -register user password usergroups*/
void do_user_add(int argc, char *argv[])
{
	char xpass[BFSZ];
	char xmsg[BFSZ];
	if (argc<5) {printf("Usage: tellnews -adduser username password usergroups\n"); exit(0); }
	/* 
	   Search for 'users' in users.dat
	   Remove entry
	   Add new entry
	
	*/
	printf("Set user (%s)\n",argv[2]);
	user_del(argv[2],xpass,xmsg);
	user_add(argv[2],argv[3],"none",argv[4],"*","*",xmsg);
}

int pass_hash(int n, char *s)
{
	int total=0;
	for (;*s!=0;s++) {
		total += *s;
		total *= 64;
		total = total+n+total/3 % (1000000+*s + n);
		n = (n + total)/2;
		total = total % 1000000;
	}
	if (total<0) total = -total;
	return total;
}
char *pass_encrypt(char *s)
{
	int r,h;
	static char bf[BFSZ];
	srand(time(NULL)+ *s *4000);
	r = rand();
	if (r<0) r = -r;
	h = pass_hash(r,s);
	sprintf(bf,"$1%d.%d",r,h);
	return bf;
}
int user_add(char *user, char *pass, char *full, char *groups, char *access, char *access_wild,  char *msg)
{
	FILE *f;
	char *wild;
	char xpass[BFSZ];
	user_del(user,xpass,msg);
	
	wild = access_wild;
	if (strlen(wild)==0) wild = "*";
	f = fopen(FILE_USERS,"a");
	if (f==NULL) {
		sprintf(msg,"Could not write %s %s \n",FILE_USERS,strerror(errno));
		return FALSE;
	}
	if (strlen(pass)!=0) strcpy(xpass,pass); strlwr(xpass);
	fprintf(f,"%s:%s:%s:%s:%s:%s\n",user,pass_encrypt(xpass),access,wild,full,groups);
	fclose(f);
	fix_owner(FILE_USERS);

	sprintf(msg,"User %s successfully added to users.dat file\n",user);
	return TRUE;
}
int user_del(char *user, char *pass, char *msg)
{
	int notfound = TRUE;
	int n;
	char *p[100];
	FILE *fin,*fout;
	char bf[BFSZ];
	char orig[BFSZ];
	fin = fopen(FILE_USERS,"r");
	fout = fopen(FILE_USERS_NEW,"w");
	if (fin==NULL) {
		sprintf(msg,"Could not read %s %s \n",FILE_USERS,strerror(errno));
		return FALSE;
	}
	if (fout==NULL) {
		sprintf(msg,"Could not write %s %s \n",FILE_USERS_NEW,strerror(errno));
		return FALSE;
	}
	fprintf(fout,"#user:password:manager access(none,full):managed groups:full name:usergroups\n");
	for (;!feof(fin);) {
		if (fgets(bf,BFSZ-1,fin)==NULL) break;
		strcpy(orig,bf);
                n = token_split2(bf,p,":",90);
		if (n<4) goto cont;
		if (strcmp(p[0],user)==0) {
			sprintf(msg,"User %s deleted\n",user);
			notfound = FALSE;
			strcpy(pass,p[1]);
			continue;
		}
cont:
		if (strstr(orig,"#user:password:manager access(none,full):managed")!=NULL) continue;
		fprintf(fout,"%s",orig);
	}
	fclose(fin);
	fclose(fout);
	if (notfound) {
		sprintf(msg,"User %s does not exist\n",user);
		remove(FILE_USERS_NEW);
		return FALSE;
	}


	strcpy(bf,FILE_USERS);
	if (remove(FILE_USERS)!=0) printf("Remove (%s) failed (%s)\n",FILE_USERS,strerror(errno));
	if (rename(FILE_USERS_NEW,bf)!=0) printf("Rename (%s) failed (%s)\n",FILE_USERS_NEW,strerror(errno));
	/*printf("Rename (%s) to (%s)\n",FILE_USERS_NEW,bf);*/
	fix_owner(bf);
	return TRUE;	
}

int fix_owner(char *fname)
{
#ifdef isunix
	static int done;
	static struct stat sb;

	if (!done) {
		if (stat(config_get(C_SPOOL), &sb) < 0 || !S_ISDIR(sb.st_mode)) {
			imsg("DNEWS cant stat %s %s\n", config_get(C_SPOOL),strerror(errno));
			return FALSE;
		}
		done = TRUE;
	}
	chown(fname,sb.st_uid,sb.st_gid);
	if (strstr(fname,"users.dat")!=NULL) {
		chmod(fname,0600);
	}
#endif
	return TRUE;
}
#ifdef VMS
int usleep(int x)
{
	return 0;
}
void lib_createdir(char *s)
{
}
#endif


int do_testing(void)
{
	char bf[BFSZ];
again:
	printf("string ? "); gets(bf);
	printf("get rest (%s) \n",get_rest_better(bf,2));
	goto again;

}