/*
 * Copyright (c) 1998,1999,2000  Kazushi (Jam) Marukawa
 * All rights of my changes are 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 in the documentation and/or other materials provided with
 *    the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
 */

#ifdef SOCKS
#include <socks.h>
#endif

#include <sys/types.h>
#ifdef BSD
#include <sys/errno.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>

#include "leafnode.h"

#include "leafnode.h"

const char* spooldir = 0;
const char* libdir = 0;
const char* defspooldir = SPOOLDIR;
const char* deflibdir = LIBDIR;
const char* version = VERSION;
const char* id = "@(#) leafnode+ " VERSION;

static char s[PATH_MAX+1024]; /* long string, used as temporary */

void initconfig(void)
{
    if (spooldir == 0)
	if ((spooldir = getenv("SPOOLDIR")) == 0)
	    spooldir = defspooldir;
    if (libdir == 0)
	if ((libdir = getenv("LEAFNODE")) == 0)
	    if ((libdir = getenv("LIBDIR")) == 0)
		libdir = deflibdir;
}

const char* getconfigfname(void)
{
    static struct string a = { 0, 0 };
    initconfig();
    sprintf(s, "%s/config", libdir);
    setstring(&a, s);
    return a.str;
}

const char* getinfofname(void)
{
    static struct string a = { 0, 0 };
    initconfig();
    sprintf(s, "%s/groupinfo", libdir);
    setstring(&a, s);
    return a.str;
}

const char* getinfonewfname(void)
{
    static struct string a = { 0, 0 };
    initconfig();
    sprintf(s, "%s/groupinfo.new", libdir);
    setstring(&a, s);
    return a.str;
}

const char* getactivefname(const char* servername)
{
    static struct string a = { 0, 0 };
    assert(servername != 0 && *servername != '\0');
    initconfig();
    sprintf(s, "%s/%s.active", libdir, servername);
    setstring(&a, s);
    return a.str;
}

const char* getserverfname(const char* servername)
{
    static struct string a = { 0, 0 };
    assert(servername != 0 && *servername != '\0');
    initconfig();
    sprintf(s, "%s/%s", libdir, servername);
    setstring(&a, s);
    return a.str;
}

const char* getservernewfname(const char* servername)
{
    static struct string a = { 0, 0 };
    assert(servername != 0 && *servername != '\0');
    initconfig();
    sprintf(s, "%s/%s.new", libdir, servername);
    setstring(&a, s);
    return a.str;
}

const char* getinterestingdname(void)
{
    static struct string a = { 0, 0 };
    initconfig();
    sprintf(s, "%s/interesting.groups", spooldir);
    setstring(&a, s);
    return a.str;
}

const char* getinterestingngfname(const struct newsgroup* ng)
{
    static struct string a = { 0, 0 };
    assert(ng != 0);
    initconfig();
    sprintf(s, "%s/interesting.groups/%s", spooldir, ng->name);
    setstring(&a, s);
    return a.str;
}

const char* getinterestingngdotfname(const struct newsgroup* ng)
{
    static struct string a = { 0, 0 };
    assert(ng != 0);
    initconfig();
    sprintf(s, "%s/interesting.groups/.%s", spooldir, ng->name);
    setstring(&a, s);
    return a.str;
}

const char* getoutgoingdname(void)
{
    static struct string a = { 0, 0 };
    initconfig();
    sprintf(s, "%s/out.going", spooldir);
    setstring(&a, s);
    return a.str;
}

extern const char* getoutgoingfname(const char* fname)
{
    static struct string a = { 0, 0 };
    initconfig();
    sprintf(s, "%s/out.going/%s", spooldir, fname);
    setstring(&a, s);
    return a.str;
}

const char* getfailedpostingsdname(void)
{
    static struct string a = { 0, 0 };
    initconfig();
    sprintf(s, "%s/failed.postings", spooldir);
    setstring(&a, s);
    return a.str;
}

const char* getfailedpostingsfname(const char* fname)
{
    static struct string a = { 0, 0 };
    initconfig();
    sprintf(s, "%s/failed.postings/%s", spooldir, fname);
    setstring(&a, s);
    return a.str;
}

const char* getngdname(const struct newsgroup* ng)
{
    static struct string a = { 0, 0 };
    char* p;
    assert(ng != 0);
    initconfig();
    sprintf(s, "%s/%s", spooldir, ng->name);
    p = s + strlen(spooldir) + 1;
    while (*p) {
	if (*p == '.')
	    *p = '/';
	else
	    *p = tolower(*p);
	p++;
    }
    setstring(&a, s);
    return a.str;
}

const char* getartfname(const struct newsgroup* ng, const unsigned long art)
{
    static struct string a = { 0, 0 };
    assert(ng != 0 && art > 0);
    initconfig();
    sprintf(s, "%s/%lu", getngdname(ng), art);
    setstring(&a, s);
    return a.str;
}

static enum { OLD, NEW } hashalg = OLD;

const char* getmsgiddname(const unsigned int hash)
{
    static struct string a = { 0, 0 };

    initconfig();
    if (hashalg == OLD)
	sprintf(s, "%s/message.id/%03d", spooldir, hash);
    else
	sprintf(s, "%s/message.id/X%03d", spooldir, hash);
    setstring(&a, s);
    return a.str;
}

const char* getmsgidfname(const char* msgid)
{
    static struct string a = { 0, 0 };
    char msgidbuf[1024];
    unsigned long hash;
    char* p;

    assert(msgid != 0 && *msgid != '\0');
    strcpy(msgidbuf, msgid);
    msgid = p = skipspaces(msgidbuf);
    *skipnonspaces(p) = '\0';
    initconfig();

    hash = 0;
    if (hashalg == OLD) {
	int i;
	char* q = p;

	/* uniform message-id */
	i = strlen(spooldir) + 16;
	do {
	    if (*q == '/')
		*q = '@';
	    else if (*q == '>')
		q[1] = '\0';
	    hash += (int)(*q++);
	    hash += ++i;
	} while (*q);

	hash = (hash % 999) + 1;
    } else {
	char* q = p;
	int i;

	/* uniform message-id */
	i = 1;
	while (*q != '\0') {
	    if (*q == '/')
		*q = '@';
	    hash += i++ * (int)(*q++);
	}

	/* calculate index */
	hash = hash % 997;
    }
    sprintf(s, "%s/%s", getmsgiddname(hash), msgid);
    setstring(&a, s);
    return a.str;
}


syntax highlighted by Code2HTML, v. 0.9.1