/*
 * 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 <assert.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <netdb.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <dirent.h>

#include "leafnode.h"

static struct article* findarticle(const char* ngstr, const char* msgid)
{
    struct newsgroup* ng = findgroup(ngstr);
    unsigned long art;
    static struct article a = { 0, 0UL };

    if (ng == 0)
	return 0;

    chdirgroup(ng, 1);
    /* look for an article having same message-id */
    getxover();
    for (art = xfirst; art <= xlast; art++) {
	if (xoverinfo[art-xfirst].text) {
	    char* p = strchr(xoverinfo[art-xfirst].text, '\t');
	    char* q = NULL;
	    if (p) p = strchr(p + 1, '\t');
	    if (p) p = strchr(p + 1, '\t');
	    if (p) p = strchr(p + 1, '\t');
	    if (p) q = strchr(p + 1, '\t');
	    if (p && q && strncmp(p + 1, msgid, q-p-1) == 0)
		break;
	}
    }
    if (art <= xlast) {
	a.ng = ng;
	a.art = art;
	return &a;
    } else {
	return 0;
    }
}

void addarticle(struct articles* p, const struct article* a)
{
    if (p->num + 1 >= p->size) {
	p->size = (p->num + 1 + 255) / 256 * 256;
	p->arts = critrealloc(p->arts, p->size * sizeof(struct article),
			      "addarticle");
    }
    p->arts[p->num++] = *a;
}

struct articles* findarticles(const char* msgid)
{
    static struct articles arts = { 0, 0, 0 };

    FILE* f;
    char* p;

    assert(msgid != NULL && *msgid != '\0');
    if ((f = fopen(getmsgidfname(msgid), "r")) == 0)
	return 0;
    p = getaheader(f, "Xref");

    /* clear arts */
    arts.num = 0;

    if (!*p) {
	/*
	 * No Xref header, so look for articles in each newsgroup
	 * by using msgid and "Newsgroups" header.
	 */
	char* ngstr = getaheader(f, "Newsgroups");
	char* q;
	fclose(f);
	for (p = ngstr; p != 0; p = q) {
	    struct article* a;
	    q = strchr(p, ',');
	    if (q)
		*q++ = '\0';
	    p = skipspaces(p);
	    a = findarticle(p, msgid);
	    if (a != 0) {
		addarticle(&arts, a);
	    }
	}
    } else {
	/*
	 * Find Xref header, so use it to build articles' array.
	 * Sometimes, articles may already be expired by texpire,
	 * so this result may be not accurate.
	 */
	fclose(f);

	/* skip 1st strings as hostname */
	p = skipnonspaces(p);
	p = skipspaces(p);

	/* build articles' array */
	while (*p) {
	    char* q;
	    struct newsgroup* ng;
	    unsigned long art;

	    /* fetch string before ':' as newsgroup name */
	    q = p;
	    while (*q && *q != ':')
		q++;
	    if (*q == '\0')
		break;	/* cannot find ':'.  it means xref: may be broken. */
	    *q++ = '\0';
	    ng = findgroup(p);
	    /* fetch string after ':' as article number */
	    p = skipnonspaces(q);
	    if (*p)
		*p++ = '\0';
	    art = strtoul(q, NULL, 10);
	    if (ng && art > 0) {
		struct article a;
		a.ng = ng;
		a.art = art;
		addarticle(&arts, &a);
	    }
	}
    }
    if (arts.num > 0)
	return &arts;
    else
	return 0;
}



syntax highlighted by Code2HTML, v. 0.9.1