src/ihave.c
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- 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;
}