src/ihave.c

/* [<][>]
[^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. CMDihave

/* $Id: ihave.c,v 1.1.1.1 1998/08/19 11:09:27 proff Exp $
 * $Copyright$
 */

#include "nglobal.h"
#include "acc.h"

#include "ihave.h"

EXPORT bool CMDihave(char *args)
/* [<][>][^][v][top][bottom][index][help] */
{
        struct server_cfg *scfg;
        char buf[MAX_LINE];
        int good = 0;
        char *goodmsg = NULL;
        int err = 0;
        char *errmsg = NULL;
        struct authent *auth;
        struct strList *sl;
        struct strStack *art = NULL;
        if (ModeReader)
        {       
                emitf ("%d Can't IHAVE in reader mode\r\n", NNTP_ACCESS_VAL); /* XXX AUTH_NEEDED isn't appropriate */
                return FALSE;
        }
        auth = authorise(RemoteHosts, NULL);
        if (!auth || !auth->ihave || (auth->auth && AuthState != valid))
        {
                log (("%s denied ihave access", ClientHost));
                emitf ("%d Transfer permission denied\r\n", NNTP_AUTH_NEEDED_VAL);
                return FALSE;
        }
        for (sl = con->ihaveServers; sl; sl = sl->next)
        {
                scfg = findScfg(sl->data);
                if (!scfg)
                {
                        logen (("bad IHAVE server '%s', check 'ihaveServers' configuration variable", sl->data));
                        continue;
                }
                if (!attachServer(scfg))
                {
                bad:
                        scfg->share->ihave_fail++;
                        logw (("IHAVE failed with '%s'", sl->data));
                        continue;
                }
                Cfemit (scfg, args);
                Cfflush (scfg);
                if (!Cfget (scfg, buf, sizeof buf))
                        goto bad;
                if (strToi (buf) != NNTP_SENDIT_VAL)
                {
                        if (!errmsg)
                                errmsg = Sstrdup(buf);
                        continue;
                }
                if (!art)
                {
                        emit (buf);
                        buf[0] = '\0';
                        flush ();
                        do
                        {
                                if (!Get (buf, sizeof buf))
                                        break;
                                strStackAdd (art, buf);
                        } while (!EL (buf));
                        if (!art || !EL(buf))
                        {
                                logw (("incomplete IHAVE article"));
                                if (art)
                                        strStackFree (art);
                                if (goodmsg)
                                        free (goodmsg);
                                if (errmsg)
                                        free (errmsg);
                                /* return server to sane state */
                                Cfemitf(scfg, "\r\n.\r\n");
                                Cfflush(scfg);
                                Cget (buf, sizeof buf);
                                emit (buf);
                                scfg->share->ihave_fail++;
                                return FALSE;
                        }
                        logd (("IHAVE received %d byte article", art->used));
                }
                CurrentScfg = scfg;
                Cemit (art->data);
                if (!Cget (buf, sizeof buf))
                {
                        logw (("IHAVE failed with '%s'", scfg->host));
                        CurrentScfg->share->ihave_fail++;
                        continue;
                }
                if (strToi(buf) == NNTP_TOOKIT_VAL)
                {
                        logd (("IHAVE article accepted by '%s'", scfg->host));
                        CurrentScfg->share->ihave_good++;
                        if (good++ < 1)
                        {
                                if (con->ihaveSpeedHandshake)
                                        emit (buf);
                                else
                                        goodmsg = Sstrdup (buf);
                        }
                } else
                {
                        err++;
                        if (!errmsg)
                                errmsg = Sstrdup (buf);
                        strStripEOL (buf);
                        logwn (("IHAVE article rejected by '%s': '%s'", scfg->host, buf));
                        CurrentScfg->share->ihave_fail++;
                }
        }
        if (art)
                strStackFree (art);
        if (good)
        {
                if (goodmsg)
                        emit (goodmsg);
                if (errmsg)
                        free (errmsg);
                return TRUE;
        }
        if (errmsg)
        {
                emit (errmsg);
                free (errmsg);
        } else
                emitrn (NNTP_SERVERDOWN);       /* XXX consider NNTP_SERVERTEMPDOWN */
        return FALSE;
}

/* [<][>][^][v][top][bottom][index][help] */