/***************
*
* g:\exe\txl\src\txlpswd.c
*/
#include "txl.h"

#define MAX_CHR 128

static unsigned long next = 1;
int randx() {
	next = next * 1103515245 + 12345;
	return (unsigned int)(next/65536) % 32768;
}
void srandx(unsigned int seed)
{
	next = seed;
}

unsigned char *get_use_string()
{
	int i, dst;
	static unsigned char str[132];
	static int already_init = FALSE;

	if (already_init) {
		return (str);
	}
	srandx(0);
	strcpy(str, "!#%&@$~(^_-)｢ｦ=[]?+.*");
	for (i = 'A'; i <= 'Z'; i++) {
		str[21 + i - 'A'] = (char)(i);
	}
	for (i = '0'; i <= '9'; i++) {
		str[47 + i - '0'] = (char)(i);
	}
	for (i = 'a'; i <= 'z'; i++) {
		str[57 + i - 'a'] = (char)(i);
	}
	for (i = 'ｱ'; i <= 'ﾝ'; i++) {
		str[83 + i - 'ｱ'] = (char)(i);
	}

	str[MAX_CHR] = NUL;
	for (i = 0; i < MAX_CHR; i++) {
		dst = randx() % MAX_CHR;
		str[131] = str[i];
		str[i] = str[dst];
		str[dst] = str[131];
	}
#if 0
	printf("password:");
	for (i = 0; i < MAX_CHR; i++) {
		printf("%c", str[i]);
	}
	puts("");
#endif
	already_init = TRUE;
	return (str);
}

int getposnum(int c)
{
	static unsigned char *str = NULL;
#if 0
	unsigned char *tmp;
#else
	int i;
#endif

	if (str == NULL) {
		str = get_use_string();
	}
#if 0
	if ((tmp = strchr(str, c)) == NULL) {
		return (-1);
	}
	return ((int)(tmp - str));
#else
	for (i = 0; i < MAX_CHR; i++) {
		if (c == str[i]) {
			return (i);
		}
	}
	return (-1);
#endif

}

int getposchr(int c)
{
	static unsigned char *str = NULL;

	if (str == NULL) {
		str = get_use_string();
	}
	if (c >= MAX_CHR) {
		return (-1);
	}
	return (str[c]);
}

void expand_passwd(char *val[])
{
	int pos, c, i, sum, len, c1, c2, c3, plen;
	FILE *fw;
	unsigned char passwd[16];
	unsigned char code[32];

	for (i = 0; i < 16; i++) {
		passwd[i] = 0;
	}

	if ((fw = fopen(val[1], "wb")) == NULL) {
		Exit(1);
	}

	if (strlen(val[0]) > 31) {
		fputs("Expand Error", fw);
		fclose(fw);
		Exit(1);	/* コードデータが長過ぎ */
	}
	strcpy(code, val[0]);
	len = strlen(code);

	sum = 0;
	for (i = 0; i < len - 2; i++) {
		sum += code[i];
	}
	if (code[len - 2] != getposchr(sum / MAX_CHR) ||
			code[len - 1] != getposchr(sum % MAX_CHR)) {
		fputs("Error(SUM)", fw);
		fclose(fw);
		Exit(1);
	}
	if (code[0] != '0') {
		fputs("Error(TAG)", fw);
		fclose(fw);
		Exit(1);
	}
	c1 = getposnum(code[1]);
	c2 = getposnum(code[2]);
	c3 = getposnum(code[3]);
	plen = (MAX_CHR + c3 - abs(c1 - c2)) % MAX_CHR;
	if (plen > 9) {
		fputs("Error(LENGTH)", fw);
		fclose(fw);
		Exit(1);
	}

	c = (abs(c3 - c1) + plen) % MAX_CHR;
	pos = 0;
	for (i = 4; i < 4 + plen; i++) {
/*		printf("c1=%d\n",getposnum(code[i]));	*/
		c1 = getposnum(code[i]);
/*		printf("password[%d]=%d\n",pos,(c1 + c + i - 4));	*/
		passwd[pos++] = ((c1 + c + i - 4) & 0x7f)/* + 1 */;
	}											/* ↑ １スライド */

	fputs(passwd, fw);
	fclose(fw);
	Exit(0);
}

void compress_passwd(char *val[], int dmy)
{
	int pos, c, i, sum, c1, c2, c3;
	FILE *fw;
	unsigned char passwd[16];
	unsigned char code[32];

	getposchr(0);		/* 初回はrandxを初期化するのでダミー呼び出し */
	getposnum('0');		/* 上に同じ */
	srandx((unsigned int)(clock() & 0x0ffff));
	for (i = 1; i < 32; i++) {
		code[i] = 0;
	}
	pos = 0;
	code[pos++] = '0';

	if ((fw = fopen(val[1], "wb")) == NULL) {
		Exit(1);
	}

	if (strlen(&(val[0][dmy])) > 9) {
		fputs("Error(LENGTH)", fw);
		fclose(fw);
		Exit(1);	/* パスワードが長過ぎ */
	}
	strcpy(passwd, &(val[0][dmy]));
	while (strlen(passwd) < 10) {
		strncat(passwd, &(val[0][dmy]), 10 - strlen(passwd));
	}
#if 1
	c1 = randx() % MAX_CHR;
	c2 = randx() % MAX_CHR;
#else
	c2 = randx() % (MAX_CHR/2);
	c1 = c2 + MAX_CHR/2;
#endif
	c3 = (MAX_CHR + abs(c1 - c2) + strlen(&(val[0][dmy]))) % MAX_CHR;
/*	printf("code[%d]=%d\n",pos,c1);	*/
	code[pos++] = getposchr(c1);
/*	printf("code[%d]=%d\n",pos,c2);	*/
	code[pos++] = getposchr(c2);
/*	printf("code[%d]=%d\n",pos,c3);	*/
	code[pos++] = getposchr(c3);

	c = (MAX_CHR + abs(c3 - c1) + strlen(&(val[0][dmy]))) % MAX_CHR;
	for (i = 0; i < 10; i++) {
/*		printf("code[%d]=%d\n",pos, getposchr((MAX_CHR*2 + passwd[i] - c - i) % MAX_CHR));	*/
		code[pos++] = getposchr((MAX_CHR*2 + passwd[i] - c - i) % MAX_CHR);
	}
	sum = 0;
	for (i = 0; code[i] != NUL; i++) {
		sum += code[i];
	}
/*	printf("code[%d]=%d\n",pos,getposchr(sum / MAX_CHR));	*/
	code[pos++] = getposchr(sum / MAX_CHR);
/*	printf("code[%d]=%d\n",pos,getposchr(sum % MAX_CHR));	*/
	code[pos++] = getposchr(sum % MAX_CHR);
	fputs(code, fw);
	fclose(fw);
	Exit(0);
}

