/*
* by Dirk Meyer (dinoex)
* Copyright (C) 2004-2007 Dirk Meyer
*
* By using this file, you agree to the terms and conditions set
* forth in the GNU General Public License. More information is
* available in the README file.
*
* If you received this file without documentation, it can be
* downloaded from http://iroffer.dinoex.net/
*
* $Id: dinoex_misc.c,v 1.4 2007/07/08 08:38:11 dinoex Exp $
*
*/
/* include the headers */
#include "iroffer_config.h"
#include "iroffer_defines.h"
#include "iroffer_headers.h"
#include "iroffer_globals.h"
#include "dinoex_utilities.h"
#include "dinoex_admin.h"
#include "dinoex_misc.h"
#include <ctype.h>
static void admin_line(int fd, const char *line) {
userinput *uxdl;
char *full;
if (line == NULL)
return;
uxdl = mycalloc(sizeof(userinput));
full = mycalloc(maxtextlength);
snprintf(full,maxtextlength -1,"A A A A A %s", line);
u_fillwith_msg(uxdl,NULL,full);
uxdl->method = method_fd;
uxdl->fd = fd;
u_parseit(uxdl);
mydelete(uxdl);
mydelete(full);
}
static void admin_run(const char *cmd) {
int fd;
const char *job;
char *done;
job = gdata.admin_job_file;
if (job == NULL)
return;
done = mycalloc(strlen(job)+6);
strcpy(done,job);
strcat(done,".done");
fd = open(done,
O_WRONLY | O_CREAT | O_APPEND | ADDED_OPEN_FLAGS,
CREAT_PERMISSIONS);
if (fd < 0)
{
outerror(OUTERROR_TYPE_WARN_LOUD,
"Cant Create Admin Job Done File '%s': %s",
done, strerror(errno));
}
else
{
admin_line(fd, cmd);
close(fd);
}
mydelete(done)
}
void admin_jobs(void) {
FILE *fin;
const char *job;
char *line;
char *l;
char *r;
job = gdata.admin_job_file;
if (job == NULL)
return;
fin = fopen(job, "ra" );
if (fin == NULL)
return;
line = mycalloc(maxtextlength);
while (!feof(fin)) {
r = fgets(line, maxtextlength - 1, fin);
if (r == NULL )
break;
l = line + strlen(line) - 1;
while (( *l == '\r' ) || ( *l == '\n' ))
*(l--) = 0;
admin_run(line);
}
mydelete(line)
fclose(fin);
unlink(job);
}
int hide_pack(const xdcc *xd)
{
if (gdata.hidelockedpacks == 0)
return 0;
if (xd->lock == NULL)
return 0;
return 1;
}
int check_lock(const char* lockstr, const char* pwd)
{
if (lockstr == NULL)
return 0; /* no lock */
if (pwd == NULL)
return 1; /* locked */
return strcmp(lockstr, pwd);
}
void update_natip (const char *var)
{
struct hostent *hp;
struct in_addr old;
struct in_addr in;
long oldip;
char *oldtxt;
if (var == NULL)
return;
gdata.usenatip = 1;
if (gdata.r_ourip != 0)
return;
bzero((char *)&in, sizeof(in));
if (inet_aton(var, &in) == 0)
{
hp = gethostbyname(var);
if (hp == NULL)
{
outerror(OUTERROR_TYPE_WARN_LOUD,"Invalid NAT Host, Ignoring: %s",hstrerror(h_errno));
return;
}
if ((unsigned)hp->h_length > sizeof(in) || hp->h_length < 0)
{
outerror(OUTERROR_TYPE_WARN_LOUD,"Invalid DNS response, Ignoring: %s",hstrerror(h_errno));
return;
}
memcpy(&in, hp->h_addr_list[0], sizeof(in));
}
old.s_addr = htonl(gdata.ourip);
if (old.s_addr == in.s_addr)
return;
oldip = gdata.ourip;
gdata.ourip = ntohl(in.s_addr);
if (oldip != 0 )
{
oldtxt = mystrdup(inet_ntoa(old));
ioutput(CALLTYPE_NORMAL,OUT_S|OUT_L|OUT_D,COLOR_YELLOW,
"DCC IP changed from %s to %s", oldtxt, inet_ntoa(in));
mydelete(oldtxt);
}
if (gdata.debug > 0) ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_YELLOW,"ip=0x%8.8lX\n",gdata.ourip);
/* check for 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 */
if (((gdata.ourip & 0xFF000000UL) == 0x0A000000UL) ||
((gdata.ourip & 0xFFF00000UL) == 0xAC100000UL) ||
((gdata.ourip & 0xFFFF0000UL) == 0xC0A80000UL))
{
outerror(OUTERROR_TYPE_WARN_LOUD,"usenatip of %lu.%lu.%lu.%lu looks wrong, this is probably not what you want to do",
(gdata.ourip >> 24) & 0xFF,
(gdata.ourip >> 16) & 0xFF,
(gdata.ourip >> 8) & 0xFF,
(gdata.ourip ) & 0xFF);
}
}
void stoplist(const char *nick)
{
char *item;
char *copy;
char *end;
char *inick;
int stopped = 0;
ioutput(CALLTYPE_MULTI_FIRST, OUT_S|OUT_L|OUT_D, COLOR_YELLOW,
"XDCC STOP from (%s)", nick);
item = irlist_get_head(&(gdata.xlistqueue));
while (item)
{
if (strcasecmp(item,nick) == 0)
{
stopped ++;
item = irlist_delete(&(gdata.xlistqueue), item);
continue;
}
item = irlist_get_next(item);
}
item = irlist_get_head(&(gdata.serverq_slow));
while (item)
{
inick = NULL;
copy = mystrdup(item);
inick = strchr(copy, ' ');
if (inick != NULL)
{
*(inick++) = 0;
end = strchr(inick, ' ');
if (end != NULL)
{
*(end++) = 0;
if (strcasecmp(inick,nick) == 0)
{
if ( (strcmp(copy,"PRIVMSG") == 0) || (strcmp(copy,"NOTICE") == 0) )
{
stopped ++;
mydelete(copy);
item = irlist_delete(&(gdata.serverq_slow), item);
continue;
}
}
}
}
mydelete(copy);
item = irlist_get_next(item);
}
ioutput(CALLTYPE_MULTI_END,OUT_S|OUT_L|OUT_D,COLOR_YELLOW," (stopped %d)", stopped);
}
void notifyqueued_nick(const char *nick)
{
int i;
unsigned long rtime, lastrtime;
pqueue *pq;
transfer *tr;
updatecontext();
lastrtime=0;
/* if we are sending more than allowed, we need to skip the difference */
for (i=0; i<irlist_size(&gdata.trans)-gdata.slotsmax; i++)
{
rtime=-1;
tr = irlist_get_head(&gdata.trans);
while(tr)
{
int left = min2(359999,(tr->xpack->st_size-tr->bytessent)/((int)(max2(tr->lastspeed,0.001)*1024)));
if (left > lastrtime && left < rtime)
{
rtime = left;
}
tr = irlist_get_next(tr);
}
if (rtime < 359999)
{
lastrtime=rtime;
}
}
i=1;
pq = irlist_get_head(&gdata.mainqueue);
while(pq)
{
rtime=-1;
tr = irlist_get_head(&gdata.trans);
while(tr)
{
int left = min2(359999,(tr->xpack->st_size-tr->bytessent)/((int)(max2(tr->lastspeed,0.001)*1024)));
if (left > lastrtime && left < rtime)
{
rtime = left;
}
tr = irlist_get_next(tr);
}
if (rtime < 359999)
{
lastrtime=rtime;
}
if (!strcasecmp(pq->nick, nick))
{
ioutput(CALLTYPE_NORMAL, OUT_S|OUT_D,COLOR_YELLOW,
"Notifying Queued status to %s",
nick);
notice_slow(pq->nick,"Queued %lih%lim for \"%s\", in position %i of %i. %lih%lim or %s remaining.",
(long)(gdata.curtime-pq->queuedtime)/60/60,
(long)((gdata.curtime-pq->queuedtime)/60)%60,
pq->xpack->desc,
i,
irlist_size(&gdata.mainqueue),
lastrtime/60/60,
(lastrtime/60)%60,
(rtime >= 359999) ? "more" : "less");
}
i++;
pq = irlist_get_next(pq);
}
}
static int check_for_file_remove(int n)
{
xdcc *xd;
userinput *pubplist;
char *tempstr;
updatecontext();
xd = irlist_get_nth(&gdata.xdccs, n-1);
if (look_for_file_changes(xd) == 0)
return 0;
pubplist = mycalloc(sizeof(userinput));
tempstr = mycalloc(maxtextlength);
snprintf(tempstr,maxtextlength-1,"remove %d", n);
u_fillwith_console(pubplist,tempstr);
u_parseit(pubplist);
mydelete(pubplist);
mydelete(tempstr);
return 1;
}
static int last_look_for_file_remove = -1;
void look_for_file_remove(void)
{
int i;
int p;
int m;
updatecontext();
p = irlist_size(&gdata.xdccs);
m = min2(20, p);
for (i=0; i<m; i++) {
last_look_for_file_remove ++;
if (last_look_for_file_remove < 0 || last_look_for_file_remove >= p)
last_look_for_file_remove = 0;
if (check_for_file_remove(last_look_for_file_remove + 1))
return;
}
return;
}
int has_joined_channels(int all)
{
int j;
int n;
channel_t *ch;
j=0;
ch = irlist_get_head(&gdata.channels);
while(ch)
{
if ((ch->flags & CHAN_ONCHAN) == 0)
{
if (all != 0)
return 0;
}
else
{
j++;
n++;
}
ch = irlist_get_next(ch);
}
return j;
}
void reset_download_limits(void)
{
int num;
int new;
xdcc *xd;
num = 0;
xd = irlist_get_head(&gdata.xdccs);
while(xd)
{
num++;
if (xd->dlimit_max != 0)
{
new = xd->gets + xd->dlimit_max;
ioutput(CALLTYPE_NORMAL,OUT_S|OUT_L|OUT_D,COLOR_NO_COLOR,
"Resetting download limit of pack %d, used %d",
num, new - xd->dlimit_used);
xd->dlimit_used = new;
}
xd = irlist_get_next(xd);
}
}
#ifdef USE_GEOIP
#define GEOIP_FLAGS GEOIP_MEMORY_CACHE
GeoIP *gi = NULL;
char *check_geoip(transfer *const t);
char *check_geoip(transfer *const t)
{
static char hostname[20];
static char code[20];
const char *result;
if (gi == NULL)
{
if (gdata.geoipdatabase != NULL)
gi = GeoIP_open(gdata.geoipdatabase, GEOIP_FLAGS);
else
gi = GeoIP_new(GEOIP_FLAGS);
}
if (gi == NULL)
{
code[0] = 0;
return code;
}
snprintf(hostname, sizeof(hostname), "%ld.%ld.%ld.%ld",
t->remoteip>>24, (t->remoteip>>16) & 0xFF, (t->remoteip>>8) & 0xFF, t->remoteip & 0xFF );
result = GeoIP_country_code_by_addr(gi, hostname);
if (result == NULL)
{
code[0] = 0;
return code;
}
code[0] = tolower(result[0]);
code[1] = tolower(result[1]);
code[2] = 0;
return code;
}
#endif /* USE_GEOIP */
void check_new_connection(transfer *const tr)
{
#ifdef USE_GEOIP
const char *country;
char *msg;
#endif /* USE_GEOIP */
#ifdef USE_GEOIP
country = check_geoip(tr);
ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D, COLOR_YELLOW,
"GeoIP [%s on %s]: Info %ld.%ld.%ld.%ld -> %s)",
tr->nick,
gdata.networks[ tr->net ].name,
tr->remoteip>>24, (tr->remoteip>>16) & 0xFF,
(tr->remoteip>>8) & 0xFF, tr->remoteip & 0xFF,
country);
if (irlist_size(&gdata.geoipcountry))
{
if (!verifyshell(&gdata.geoipcountry, country))
{
if (!verifyshell(&gdata.geoipexcludenick, tr->nick))
{
msg = mycalloc(maxtextlength);
if (country == NULL)
country = "error";
snprintf(msg, maxtextlength - 1, "Sorry, no downloads to your country = %s", country);
t_closeconn(tr, msg, 0);
ioutput(CALLTYPE_NORMAL,OUT_S|OUT_L|OUT_D,COLOR_NO_COLOR,
"IP from other country (%s) detected", country);
mydelete(msg);
return;
}
}
}
#endif /* USE_GEOIP */
if ((gdata.ignoreduplicateip) && (gdata.maxtransfersperperson > 0))
{
check_duplicateip(tr);
}
}
void check_duplicateip(transfer *const newtr)
{
igninfo *ignore;
char *bhostmask;
transfer *tr;
int found;
int num;
num = 24 * 60; /* 1 day */
found = 0;
tr = irlist_get_head(&gdata.trans);
while(tr)
{
if ((tr->tr_status == TRANSFER_STATUS_SENDING) &&
(tr->remoteip == newtr->remoteip))
{
if (strcmp(tr->hostname,"man"))
found ++;
}
tr = irlist_get_next(tr);
}
if (found <= gdata.maxtransfersperperson)
return;
tr = irlist_get_head(&gdata.trans);
while(tr)
{
if ((tr->tr_status == TRANSFER_STATUS_SENDING) &&
(tr->remoteip == newtr->remoteip))
{
if (strcmp(tr->hostname,"man"))
{
t_closeconn(tr, "You are being punished for pararell downloads", 0);
bhostmask = mymalloc(strlen(tr->hostname)+5);
sprintf(bhostmask, "*!*@%s", tr->hostname);
ignore = irlist_get_head(&gdata.ignorelist);
while(ignore)
{
if (ignore->regexp && !regexec(ignore->regexp,bhostmask,0,NULL,0))
{
break;
}
ignore = irlist_get_next(ignore);
}
if (!ignore)
{
char *tempstr;
ignore = irlist_add(&gdata.ignorelist, sizeof(igninfo));
ignore->regexp = mycalloc(sizeof(regex_t));
ignore->hostmask = mystrdup(bhostmask);
tempstr = hostmasktoregex(bhostmask);
if (regcomp(ignore->regexp,tempstr,REG_ICASE|REG_NOSUB))
{
ignore->regexp = NULL;
}
ignore->flags |= IGN_IGNORING;
ignore->lastcontact = gdata.curtime;
mydelete(tempstr);
}
ignore->flags |= IGN_MANUAL;
ignore->bucket = (num*60)/gdata.autoignore_threshold;
ioutput(CALLTYPE_NORMAL,OUT_S|OUT_L|OUT_D,COLOR_NO_COLOR,
"same IP detected, Ignore activated for %s which will last %i min",
bhostmask,num);
mydelete(bhostmask);
}
}
tr = irlist_get_next(tr);
}
write_statefile();
}
char* getpart_eol(const char *line, int howmany)
{
char *part;
int li;
size_t plen;
int hi;
li=0;
for (hi = 1; hi < howmany; hi++)
{
while (line[li] != ' ')
{
if (line[li] == '\0')
{
return NULL;
}
else
{
li++;
}
}
li++;
}
if (line[li] == '\0')
{
return NULL;
}
plen = strlen(line+li);
part = mycalloc(plen+1);
memcpy(part, line+li, plen);
part[plen] = '\0';
return part;
}
void identify_needed(int force)
{
if (force == 0)
{
if ((gdata.next_identify > 0) && (gdata.next_identify >= gdata.curtime))
return;
}
/* wait 1 sec before idetify again */
gdata.next_identify = gdata.curtime + 1;
privmsg("nickserv", "IDENTIFY %s", gdata.nickserv_pass);
ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D, COLOR_NO_COLOR,
"IDENTIFY send to nickserv.");
}
void identify_check(const char *line)
{
if (strstr(line, "Nickname is registered to someone else") != NULL)
{
identify_needed(0);
}
if (strstr(line, "This nickname has been registered") != NULL)
{
identify_needed(0);
}
if (strstr(line, "This nickname is registered and protected") != NULL)
{
identify_needed(0);
}
if (strstr(line, "please choose a different nick") != NULL)
{
identify_needed(0);
}
}
/* End of File */
syntax highlighted by Code2HTML, v. 0.9.1