/*
* uf_features.c -- part of share.mod
*
* $Id: uf_features.c,v 1.16 2006-03-28 02:35:51 wcc Exp $
*/
/*
* Copyright (C) 2000 - 2006 Eggheads Development Team
* Written by Fabian Knittel <fknittel@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Userfile feature protocol description:
*
*
* LEAF HUB
*
* uf_features_dump():
* Finds out which features
* it supports / wants to use
* and then dumps those. The
* list is appended to the
* user file send ack.
*
* "s uy <features>" --+
* |
* +--> uf_features_parse():
* Parses the given list of features,
* given in a string, seperated with
* spaces. Decides which features to
* accept/use. Those features are then
* locally set:
*
* dcc[idx].u.bot->uff_flags |= <feature_flag>
*
* and sent back to the LEAF:
*
* +--- "s feats <accepted_features>"
* |
* uf_features_check(): <--+
* Checks wether the responded
* features are still accepted
* by us. If they are, we set
* the flags locally:
*
* dcc[idx].u.bot->uff_flags |= <feature_flag>
*/
typedef struct uff_list_struct {
struct uff_list_struct *next; /* Pointer to next entry */
struct uff_list_struct *prev; /* Pointer to previous entry */
uff_table_t *entry; /* Pointer to entry in table. This is
* not copied or anything, we just refer
* to the original table entry. */
} uff_list_t;
typedef struct {
uff_list_t *start;
uff_list_t *end;
} uff_head_t;
static uff_head_t uff_list;
static char uff_sbuf[512];
/*
* Userfile features management functions
*/
static void uff_init(void)
{
egg_bzero(&uff_list, sizeof(uff_head_t));
}
/* Calculate memory used for list.
*/
static int uff_expmem(void)
{
uff_list_t *ul;
int tot = 0;
for (ul = uff_list.start; ul; ul = ul->next)
tot += sizeof(uff_list_t);
return tot;
}
/* Search for a feature in the uff feature list that matches a supplied
* feature flag. Returns a pointer to the entry in the list or NULL if
* no feature uses the flag.
*/
static uff_list_t *uff_findentry_byflag(int flag)
{
uff_list_t *ul;
for (ul = uff_list.start; ul; ul = ul->next)
if (ul->entry->flag & flag)
return ul;
return NULL;
}
/* Search for a feature in the uff feature list. Returns a pointer to the
* entry in the list or NULL if no such feature exists.
*/
static uff_list_t *uff_findentry_byname(char *feature)
{
uff_list_t *ul;
for (ul = uff_list.start; ul; ul = ul->next)
if (!strcmp(ul->entry->feature, feature))
return ul;
return NULL;
}
/* Insert entry into sorted list.
*/
static void uff_insert_entry(uff_list_t *nul)
{
uff_list_t *ul, *lul = NULL;
ul = uff_list.start;
while (ul && ul->entry->priority < nul->entry->priority) {
lul = ul;
ul = ul->next;
}
nul->prev = NULL;
nul->next = NULL;
if (lul) {
if (lul->next)
lul->next->prev = nul;
nul->next = lul->next;
nul->prev = lul;
lul->next = nul;
} else if (ul) {
uff_list.start->prev = nul;
nul->next = uff_list.start;
uff_list.start = nul;
} else
uff_list.start = nul;
if (!nul->next)
uff_list.end = nul;
}
/* Remove entry from sorted list.
*/
static void uff_remove_entry(uff_list_t *ul)
{
if (!ul->next)
uff_list.end = ul->prev;
else
ul->next->prev = ul->prev;
if (!ul->prev)
uff_list.start = ul->next;
else
ul->prev->next = ul->next;
}
/* Add a single feature to the list.
*/
static void uff_addfeature(uff_table_t *ut)
{
uff_list_t *ul;
if (uff_findentry_byname(ut->feature)) {
putlog(LOG_MISC, "*", "(!) share: same feature name used twice: %s",
ut->feature);
return;
}
ul = uff_findentry_byflag(ut->flag);
if (ul) {
putlog(LOG_MISC, "*", "(!) share: feature flag %d used twice by %s and %s",
ut->flag, ut->feature, ul->entry->feature);
return;
}
ul = nmalloc(sizeof(uff_list_t));
ul->entry = ut;
uff_insert_entry(ul);
}
/* Add a complete table to the list.
*/
static void uff_addtable(uff_table_t *ut)
{
if (!ut)
return;
for (; ut->feature; ++ut)
uff_addfeature(ut);
}
/* Remove a single feature from the list.
*/
static int uff_delfeature(uff_table_t *ut)
{
uff_list_t *ul;
for (ul = uff_list.start; ul; ul = ul->next)
if (!strcmp(ul->entry->feature, ut->feature)) {
uff_remove_entry(ul);
nfree(ul);
return 1;
}
return 0;
}
/* Remove a complete table from the list.
*/
static void uff_deltable(uff_table_t *ut)
{
if (!ut)
return;
for (; ut->feature; ++ut)
(int) uff_delfeature(ut);
}
/*
* Userfile feature parsing functions
*/
/* Parse the given features string, set internal flags apropriately and
* eventually respond with all features we will use.
*/
static void uf_features_parse(int idx, char *par)
{
char *buf, *s, *p;
uff_list_t *ul;
uff_sbuf[0] = 0; /* Reset static buffer */
p = s = buf = nmalloc(strlen(par) + 1); /* Allocate temp buffer */
strcpy(buf, par);
/* Clear all currently set features. */
dcc[idx].u.bot->uff_flags = 0;
/* Parse string */
while ((s = strchr(s, ' ')) != NULL) {
*s = '\0';
/* Is the feature available and active? */
ul = uff_findentry_byname(p);
if (ul && (ul->entry->ask_func == NULL || ul->entry->ask_func(idx))) {
dcc[idx].u.bot->uff_flags |= ul->entry->flag; /* Set flag */
strcat(uff_sbuf, ul->entry->feature); /* Add feature to list */
strcat(uff_sbuf, " ");
}
p = ++s;
}
nfree(buf);
/* Send response string */
if (uff_sbuf[0])
dprintf(idx, "s feats %s\n", uff_sbuf);
}
/* Return a list of features we are supporting.
*/
static char *uf_features_dump(int idx)
{
uff_list_t *ul;
uff_sbuf[0] = 0;
for (ul = uff_list.start; ul; ul = ul->next)
if (ul->entry->ask_func == NULL || ul->entry->ask_func(idx)) {
strcat(uff_sbuf, ul->entry->feature); /* Add feature to list */
strcat(uff_sbuf, " ");
}
return uff_sbuf;
}
static int uf_features_check(int idx, char *par)
{
char *buf, *s, *p;
uff_list_t *ul;
uff_sbuf[0] = 0; /* Reset static buffer */
p = s = buf = nmalloc(strlen(par) + 1); /* Allocate temp buffer */
strcpy(buf, par);
/* Clear all currently set features. */
dcc[idx].u.bot->uff_flags = 0;
/* Parse string */
while ((s = strchr(s, ' ')) != NULL) {
*s = '\0';
/* Is the feature available and active? */
ul = uff_findentry_byname(p);
if (ul && (ul->entry->ask_func == NULL || ul->entry->ask_func(idx)))
dcc[idx].u.bot->uff_flags |= ul->entry->flag; /* Set flag */
else {
/* It isn't, and our hub wants to use it! This either happens
* because the hub doesn't look at the features we suggested to
* use or because our admin changed the flags, so that formerly
* active features are now deactivated.
*
* In any case, we abort user file sharing.
*/
putlog(LOG_BOTS, "*", "Bot %s tried unsupported feature!", dcc[idx].nick);
dprintf(idx, "s e Attempt to use an unsupported feature\n");
zapfbot(idx);
nfree(buf);
return 0;
}
p = ++s;
}
nfree(buf);
return 1;
}
/* Call all active feature functions, sorted by their priority. This
* should be called when we're about to send a user file.
*/
static int uff_call_sending(int idx, char *user_file)
{
uff_list_t *ul;
for (ul = uff_list.start; ul; ul = ul->next)
if (ul->entry && ul->entry->snd &&
(dcc[idx].u.bot->uff_flags & ul->entry->flag))
if (!(ul->entry->snd(idx, user_file)))
return 0; /* Failed! */
return 1;
}
/* Call all active feature functions, sorted by their priority. This
* should be called when we've received a user file and are about to
* parse it.
*/
static int uff_call_receiving(int idx, char *user_file)
{
uff_list_t *ul;
for (ul = uff_list.end; ul; ul = ul->prev)
if (ul->entry && ul->entry->rcv &&
(dcc[idx].u.bot->uff_flags & ul->entry->flag))
if (!(ul->entry->rcv(idx, user_file)))
return 0; /* Failed! */
return 1;
}
/*
* Userfile feature handlers
*/
/* Feature `overbots'
*/
static int uff_ask_override_bots(int idx)
{
if (overr_local_bots)
return 1;
else
return 0;
}
/*
* Internal user file feature table
*/
static uff_table_t internal_uff_table[] = {
{"overbots", UFF_OVERRIDE, uff_ask_override_bots, 0, NULL, NULL},
{"invites", UFF_INVITE, NULL, 0, NULL, NULL},
{"exempts", UFF_EXEMPT, NULL, 0, NULL, NULL},
{NULL, 0, NULL, 0, NULL, NULL}
};
syntax highlighted by Code2HTML, v. 0.9.1