GOOGLE
/************************************************************************
* psybnc2.3, src/p_dcc.c
* Copyright (C) 2001 the most psychoid and
* the cool lam3rz IRC Group, IRCnet
* http://www.psychoid.lam3rz.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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef lint
static char rcsid[] = "@(#)$Id: p_dcc.c, v 2.3 2001/07/13 02:03:00 psychoid Exp $";
#endif
#define P_DCC
#include <p_global.h>
#ifdef DCCCHAT
/* DCC - Support */
/* adding a dcc */
int adddcc(int usern, char *host, int port, char *luser, char *pass, char *name,int noini)
{
char buf[400];
char buf2[400];
struct linknodes *thisdcc;
char afile[30];
char *ppt;
int userp;
pcontext;
if (user(usern)->parent!=0) userp=user(usern)->parent; else userp=usern;
ap_snprintf(afile,sizeof(afile),gettxt(286),usern);
thisdcc=user(usern)->dcc;
while (1)
{
if (thisdcc->link==NULL) {
thisdcc->link=(struct datalinkt *)pmalloc(sizeof(struct datalinkt));
break;
}
if (thisdcc->next==NULL)
{
thisdcc->next=(struct linknodes *)pmalloc(sizeof(struct linknodes));
thisdcc->next->link=(struct datalinkt *)pmalloc(sizeof(struct datalinkt));
thisdcc=thisdcc->next;
break;
}
thisdcc=thisdcc->next;
}
thisdcc->link->outstate==0;
thisdcc->link->outsock=0;
thisdcc->link->port=port;
thisdcc->uid=usern;
thisdcc->link->type=LI_DCC;
thisdcc->link->delayed=1;
strmncpy(thisdcc->link->user,luser,sizeof(thisdcc->link->user));
strmncpy(thisdcc->link->name,name,sizeof(thisdcc->link->user));
strmncpy(thisdcc->link->pass,pass,sizeof(thisdcc->link->user));
strmncpy(thisdcc->link->host,host,sizeof(thisdcc->link->user));
if (noini==1) return 0x0;
strmncpy(buf,pass,sizeof(buf));
ppt=cryptit(buf);
ap_snprintf(buf,sizeof(buf),gettxt(287),thisdcc->link->name,thisdcc->link->user,ppt);
ap_snprintf(buf2,sizeof(buf2),gettxt(288),thisdcc->link->host,thisdcc->link->port);
writelist(buf,buf2,afile,NULL);
log(LOG_INFO,usern,gettxt(289),thisdcc->link->name,thisdcc->link->host,thisdcc->link->port,user(usern)->login);
return 0x0;
}
#endif
/* load all dccs of a user */
int loaddccs(int usern)
{
#ifdef DCCCHAT
char buf[400];
struct linknodes *thisdcc;
char afile[30];
char section[30];
char entry[30];
char *hpt;
char *upt;
char *ppt;
char *npt;
char *spt;
int port;
int cnt=0;
ap_snprintf(afile,sizeof(afile),gettxt(290),usern);
strcpy(section,"DCC");
for(cnt=0;cnt<20;cnt++)
{
ap_snprintf(entry,sizeof(entry),gettxt(291),cnt);
if(getini(section,entry,afile)==0)
{
npt=value;
upt=strchr(npt,' ');
if (upt!=NULL)
{
*upt=0;upt++;
ppt=strchr(upt,' ');
if (ppt!=NULL)
{
*ppt=0;ppt++;
hpt=strchr(ppt,';');
if (hpt!=NULL)
{
*hpt=0;hpt++;
spt=strchr(hpt,':');
if(spt!=NULL)
{
while(strchr(spt+1,':')!=NULL)
{
spt=strchr(spt+1,':');
}
}
if (spt!=NULL)
{
*spt=0;spt++;
port=atoi(spt);
adddcc(usern,hpt,port,upt,decryptit(ppt),npt,1);
}
}
}
}
}
}
#endif
return 0x0;
}
#ifdef DCCCHAT
/* listing dccs */
int listdccs(int usern)
{
char buf[400];
struct linknodes *thisdcc;
int cnt;
char l;
int userp;
pcontext;
if (user(usern)->parent!=0) userp=user(usern)->parent; else userp=usern;
cnt =1;
thisdcc=user(usern)->dcc;
ssnprintf(user(usern)->insock,gettxt(292),user(userp)->nick);
while (thisdcc != NULL)
{
if (thisdcc->link!=NULL)
{
if (thisdcc->link->outstate==STD_CONN)
l='*';
else
l=' ';
ssnprintf(user(usern)->insock,gettxt(293),user(userp)->nick,cnt,l,thisdcc->link->name,thisdcc->link->host,thisdcc->link->port);
cnt++;
}
thisdcc=thisdcc->next;
}
ssnprintf(user(usern)->insock,gettxt(294),user(userp)->nick);
listpdccs(usern);
return 0x0;
}
/* erasing dccs */
int erasedcc(int usern,int dccn)
{
struct linknodes *thisdcc;
struct linknodes *lastdcc;
char l;
FILE *infile;
FILE *tmp;
char fbuf[40];
char afile[30];
char section[30];
char entry[30];
int userp;
int cnt;
pcontext;
if (user(usern)->parent!=0) userp=user(usern)->parent; else userp=usern;
cnt =1;
thisdcc=user(usern)->dcc;
lastdcc=thisdcc;
while (thisdcc != NULL)
{
if (thisdcc->link!=NULL)
{
if (cnt==dccn) break;
lastdcc=thisdcc;
cnt++;
}
thisdcc=thisdcc->next;
}
if (thisdcc==NULL || thisdcc->link==NULL)
{
ssnprintf(user(usern)->insock,gettxt(295),user(userp)->nick);
return 0x0;
}
if (thisdcc->link->outstate==STD_CONN)
{
killsocket(thisdcc->link->outsock);
ssnprintf(user(usern)->insock,gettxt(296),user(userp)->nick);
}
if (thisdcc==user(usern)->dcc)
{
if (thisdcc->next==NULL)
{
free(thisdcc->link);
thisdcc->link=NULL;
} else {
user(usern)->dcc=thisdcc->next;
free(thisdcc->link);
free(thisdcc);
}
} else {
lastdcc->next=thisdcc->next;
free(thisdcc->link);
free(thisdcc);
}
ap_snprintf(afile,sizeof(afile),gettxt(297),usern);
ap_snprintf(entry,sizeof(entry),gettxt(298),dccn-1);
strcpy(section,"DCC");
writeini(section,entry,afile,NULL);
cnt=dccn;
ap_snprintf(entry,sizeof(entry),gettxt(299),cnt);
while(getini(section,entry,afile)==0)
{
writeini(section,entry,afile,NULL);
ap_snprintf(entry,sizeof(entry),gettxt(300),cnt-1);
writeini(section,entry,afile,value);
cnt++;
ap_snprintf(entry,sizeof(entry),gettxt(301),cnt);
}
ssnprintf(user(usern)->insock,gettxt(302),user(userp)->nick,dccn);
return 0x0;
}
#endif
/* check a dcc connection */
struct datalinkt *checkdcc(int usern, char *dccname)
{
struct linknodes *th;
th=user(usern)->dcc;
while (th!=NULL)
{
if (th->link != NULL)
{
if (strlen(th->link->name)==strlen(dccname))
{
if (strstr(th->link->name,dccname)!=NULL)
return th->link;
}
}
th=th->next;
}
return NULL;
}
#ifdef DCCCHAT
int dcchandler(int usern)
{
struct linknodes *lkm;
struct datalinkt *th;
char l=')';
char netc[15];
int rc;
netc[0]=0;
pcontext;
if (user(usern)->parent!=0)
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
else
memset(netc,0x0,sizeof(netc));
lkm=user(usern)->dcc;
while(lkm!=NULL)
{
if(lkm->link!=NULL)
if(lkm->link->outsock==currentsocket->sock->syssock) break;
lkm=lkm->next;
}
if (lkm==NULL) return 0x0;
th=lkm->link;
if(th->outstate==STD_CONN)
{
if (user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(303),netc,l,th->name,th->host,user(usern)->nick,ircbuf);
return 0x0;
}
}
}
/* connected dcc */
int connecteddcc(int usern)
{
struct linknodes *lkm;
struct datalinkt *th;
char *pt;
char buf[100];
pcontext;
lkm=user(usern)->dcc;
while(lkm!=NULL)
{
if(lkm->link!=NULL)
if(lkm->link->outsock==currentsocket->sock->syssock) break;
lkm=lkm->next;
}
if (lkm==NULL) return 0x0;
th=lkm->link;
log(LOG_INFO,usern,gettxt(304),user(usern)->login,th->name,th->host,th->port);
th->delayed=1;
ap_snprintf(buf,sizeof(buf),gettxt(305),th->user);
writesock_DELAY(th->outsock,buf,10); /* should be enough */
pt=rtrim(th->pass);
ap_snprintf(buf,sizeof(buf),gettxt(306),pt);
writesock_DELAY(th->outsock,buf,5);
th->outstate=STD_CONN;
th->delayed=1;
}
/* connection terminated */
int killeddcc(int usern)
{
struct linknodes *lkm;
struct datalinkt *th;
pcontext;
lkm=user(usern)->dcc;
while(lkm!=NULL)
{
if(lkm->link!=NULL)
if(lkm->link->outsock==currentsocket->sock->syssock) break;
lkm=lkm->next;
}
if (lkm==NULL) return 0x0;
th=lkm->link;
log(LOG_WARNING,usern,gettxt(307),user(usern)->login,th->name,th->host,th->port);
th->delayed=1;
killsocket(th->outsock);
th->outstate=0;
return 0x0;
}
/* connection could not be established */
int errordcc(int usern, int errn)
{
struct linknodes *lkm;
struct datalinkt *th;
pcontext;
lkm=user(usern)->dcc;
while(lkm!=NULL)
{
if(lkm->link!=NULL)
if(lkm->link->outsock==currentsocket->sock->syssock) break;
lkm=lkm->next;
}
if (lkm==NULL) return 0x0;
currentsocket->sock->destructor=NULL;
th=lkm->link;
log(LOG_ERROR,usern,gettxt(308),user(usern)->login,th->name,th->host,th->port);
th->delayed=1;
th->outstate=0;
killsocket(th->outsock);
return 0x0;
}
/* checking a single dcc link */
int checkdcclink(int usern, struct datalinkt *th)
{
char buf[8192];
char l=')';
char netc[15];
int proto;
char *ho;
int rc;
#ifdef HAVE_SSL
int issl=SSL_OFF;
#else
int issl=0;
#endif
netc[0]=0;
#ifdef DYNAMIC
if(user(usern)->instate!=STD_CONN) return 0x0;
#endif
if (user(usern)->parent!=0)
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
else
memset(netc,0x0,sizeof(netc));
if (th->outstate==0) {
if (th->delayed >0)
{
th->delayed-=delayinc;
return 0x0;
}
pcontext;
#ifdef HAVE_SSL
if(strstr(th->host,"S=")==th->host)
{
ho=th->host+1;
issl=SSL_ON;
} else
ho=th->host;
#endif
#ifdef HAVE_SSL
if(issl==SSL_ON)
log(LOG_INFO,usern,gettxt(309),user(usern)->login,th->name,ho,th->port);
else
#endif
log(LOG_INFO,usern,gettxt(310),user(usern)->login,th->name,ho,th->port);
proto=getprotocol(ho);
th->outsock=createsocket(0,ST_CONNECT,usern,NULL,connecteddcc,errordcc,dcchandler,killeddcc,proto,issl);
th->outsock=connectto(th->outsock,ho,th->port,NULL);
th->outstate=STD_NEWCON;
if (th->outsock==0)
{
log(LOG_ERROR,usern,gettxt(311),user(usern)->login,th->name,ho,th->port);
th->delayed=1;
return 0x0;
}
return 0x1;
}
return 0x0;
}
#endif
/* checking all dcc links */
int checkdccs()
{
#ifdef DCCCHAT
struct usernodes *th;
struct linknodes *dh;
th=usernode;
while (th!=NULL)
{
if (th->user != NULL)
{
#ifdef DYNAMIC
if(user(th->uid)->instate==STD_CONN)
{
#endif
dh=th->user->dcc;
while (dh!=NULL)
{
if (dh->link!=NULL)
{
if(checkdcclink(th->uid,dh->link)==1) break;
}
dh=dh->next;
}
#ifdef DYNAMIC
}
#endif
}
th=th->next;
}
#endif
return 0x0;
}
/*
* pending dcc support for files and chats
* this allows the user to send and receive files from and to the
* bouncer host and to receive or to send chats.
*
*/
int randport()
{
unsigned short port;
port=random();
while(port<1024)
port+=1024;
return port;
}
char stdcc[2048];
/* strip the filename without . and / */
char *stripdccfile(char *realname,int rec)
{
char *pt;
pt=realname;
if(rec==0)
{
if(strstr(pt,gettxt(312))==pt) /* so we send a device ? yes, right. */
return NULL;
if(strstr(pt,gettxt(313))==pt) /* so we send from etc ? yes, right. */
return NULL;
}
if(strchr(pt,'?')!=NULL) return NULL;
if(strchr(pt,'*')!=NULL) return NULL;
while(strchr(pt,'/')!= NULL)
{
if(rec==1) return NULL;
pt=strchr(pt,'/');
pt++;
}
while(strchr(pt,'\\')!= NULL)
{
pt=strchr(pt,'\\');
pt++;
}
if(rec==1)
{
if(strstr(pt,"..")!=NULL)
return NULL;
}
strmncpy(stdcc,pt,sizeof(stdcc));
return pt;
}
/* create a new pdcc entry */
struct dcct *createpdcc(int usern)
{
struct dcct *pd;
pd=user(usern)->pdcc;
if(pd==NULL)
{
user(usern)->pdcc=(struct dcct *)pmalloc(sizeof(struct dcct));
pd=user(usern)->pdcc;
} else {
while(pd->next!=NULL) pd=pd->next;
pd->next=(struct dcct *)pmalloc(sizeof(struct dcct));
pd=pd->next;
}
return pd;
}
/* get the current dcc struct */
struct dcct *getpsocketpdcc(int usern, struct socketnodes *psock)
{
struct dcct *pdcc;
pdcc=user(usern)->pdcc;
while(pdcc!=NULL && psock!=NULL)
{
if(psock->sock->syssock==pdcc->sock) return pdcc;
pdcc=pdcc->next;
}
return NULL;
}
/* remove a dcc struct entry */
int removepdcc(int usern)
{
struct dcct *apdcc,*pdcc,*epdcc=NULL;
struct socketnodes *ps;
apdcc=getpsocketpdcc(usern,currentsocket);
if(apdcc==NULL) return 0x0;
pdcc=user(usern)->pdcc;
while(pdcc!=NULL)
{
if(pdcc==apdcc)
{
if(epdcc==NULL)
{
user(usern)->pdcc=pdcc->next;
} else {
epdcc->next=pdcc->next;
}
if(pdcc->sock>0)
{
ps=getpsocketbysock(pdcc->sock);
if(ps!=NULL)
{
ps->sock->destructor=NULL;
ps->sock->errorhandler=NULL;
#ifdef SCRIPTING
if(pdcc->pid!=0)
{
if(getsubtaskbypid(pdcc->pid)!=NULL)
terminatetask(pdcc->pid,0);
}
#endif
killsocket(pdcc->sock);
}
}
free(pdcc);
return 0x0;
}
epdcc=pdcc;
pdcc=pdcc->next;
}
return 0x0;
}
/* event routines for dcc chats */
int pdccconnected(int usern)
{
struct dcct *pdcc;
#ifdef SCRIPTING
struct subtask *stsk;
#endif
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc==NULL) return 0x0;
pdcc->delay=0;
if(user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(314),netc,pdcc->nick,pdcc->host,user(usern)->nick,currentsocket->sock->syssock);
}
#ifdef SCRIPTING
if(pdcc->pid!=0)
{
stsk=getsubtaskbypid(pdcc->pid);
if(stsk!=NULL)
{
ssnprintf(stsk->fdout,gettxt(315));
}
}
#endif
return 0x0;
}
int pdccerror(int usern, int r)
{
struct dcct *pdcc;
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc==NULL) return 0x0;
if(user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(316),netc,pdcc->nick,pdcc->host,user(usern)->nick,currentsocket->sock->syssock);
}
removepdcc(usern);
}
int pdccquery(int usern)
{
#ifdef SCRIPTING
struct subtask *stsk;
#endif
struct dcct *pdcc;
char netc[20];
char *pt;
pcontext;
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc!=NULL)
{
if(user(usern)->instate==STD_CONN)
ssnprintf(user(usern)->insock,gettxt(317),netc,pdcc->nick,pdcc->host,user(usern)->nick,ircbuf);
#ifdef SCRIPTING
if(pdcc->pid!=0)
{
stsk=getsubtaskbypid(pdcc->pid);
if(stsk!=NULL)
{
pt=strchr(ircbuf,'\r');
if(pt!=NULL)
{
*pt='\n';
pt++;
*pt=0;
}
writesock_STREAM(stsk->fdout,ircbuf,strlen(ircbuf));
}
}
} else {
log(LOG_ERROR,-1,"Unknown DCC for socket %d",currentsocket->sock->syssock);
}
#endif
return 0x0;
}
int pdccclosed(int usern)
{
pdccerror(usern,0);
return 0x0;
}
/* event for the incoming chat */
int acceptpdccchat(int usern)
{
struct dcct *pdcc;
int nsock;
int userp=usern;
int rc;
struct socketnodes *ps,*eps;
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,mastersocket);
if(pdcc==NULL) return 0x0;
nsock=currentsocket->sock->syssock;
if(nsock<=0) return 0x0;
ps=getpsocketbysock(nsock);
if(ps==NULL) return 0x0;
pdcc->delay=0;
pdcc->type=PDC_CHATTO;
pdcc->sock=nsock;
killsocket(mastersocket->sock->syssock);
strmncpy(pdcc->host,acceptip,sizeof(pdcc->host));
if(user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(318),netc,pdcc->nick,pdcc->host,user(usern)->nick,nsock);
}
return 0x0;
}
/* events for the incoming file transfers */
int pdccfileerror(int usern, int r)
{
struct dcct *pdcc;
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc==NULL) return 0x0;
if(user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(319),user(usern)->nick,pdcc->file,netc,pdcc->nick);
}
fclose(pdcc->fhandle);
removepdcc(usern);
}
int pdccfileclosed(int usern)
{
struct dcct *pdcc;
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc==NULL) return 0x0;
if(user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(320),user(usern)->nick,pdcc->file,netc,pdcc->nick);
}
fclose(pdcc->fhandle);
removepdcc(usern);
}
int pdccfilesendack(int usern)
{
struct dcct *pdcc;
char *pt=ircbuf;
unsigned long *addrp;
unsigned long ackdcc;
int rc;
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
addrp=(unsigned long *)pt;
ackdcc=ntohl(*addrp);
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc==NULL) return 0x0;
if(pdcc->transferred!=ackdcc)
{
return 0x0;
}
if(feof(pdcc->fhandle)!=0)
{
if(user(usern)->instate==STD_CONN)
{
log(LOG_INFO,usern,gettxt(321),pdcc->file,netc,pdcc->nick);
}
fclose(pdcc->fhandle);
removepdcc(usern);
} else {
rc=fread(stdcc,1,2048,pdcc->fhandle);
pdcc->lasttransferred=rc;
pdcc->transferred+=rc;
writesock_STREAM(pdcc->sock,stdcc,rc);
}
return 0x0;
}
int acceptpdccfile(int usern)
{
struct dcct *pdcc;
int nsock,rc;
int userp=usern;
struct socketnodes *ps;
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,mastersocket);
if(pdcc==NULL) return 0x0;
nsock=currentsocket->sock->syssock;
if(nsock<=0) return -1;
pdcc->fhandle=fopen(pdcc->file,"r");
if(pdcc->fhandle==NULL)
{
killsocket(nsock);
return 0x0;
}
ps=getpsocketbysock(nsock);
if(ps==NULL) return 0x0;
ps->sock->dataflow=SD_STREAM;
pdcc->delay=0;
pdcc->sock=nsock;
pdcc->type=PDC_SENDTO;
mastersocket->sock->destructor=NULL;
mastersocket->sock->errorhandler=NULL;
killsocket(mastersocket->sock->syssock);
strmncpy(pdcc->host,acceptip,sizeof(pdcc->host));
if(user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(322),user(usern)->nick,netc,pdcc->nick,pdcc->host,pdcc->file);
}
rc=fread(stdcc,1,2048,pdcc->fhandle);
pdcc->lasttransferred=rc;
pdcc->transferred=rc;
writesock_STREAM(nsock,stdcc,rc);
return 0x0;
}
/* file receive */
int pdccfconnected(int usern)
{
struct dcct *pdcc;
char netc[20];
char mypath[100];
mode_t oldum;
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc==NULL) return 0x0;
oldum=umask(0000);
umask(0000);
mkdir(gettxt(323), 0777 );
ap_snprintf(mypath,sizeof(mypath),gettxt(324),usern);
mkdir(mypath, 0777 );
umask(oldum);
unlink(pdcc->file);
pdcc->fhandle=fopen(pdcc->file,"w");
if(pdcc->fhandle==NULL)
{
log(LOG_ERROR,usern,gettxt(325),pdcc->file);
killsocket(currentsocket->sock->syssock);
return 0x0;
}
if(user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(326),user(usern)->nick,netc,pdcc->nick,pdcc->host,pdcc->file);
}
return 0x0;
}
int pdccferror(int usern,int r)
{
struct dcct *pdcc;
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc==NULL) return 0x0;
if(pdcc->fhandle!=NULL)
fclose(pdcc->fhandle);
if(user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(327),user(usern)->nick,netc,pdcc->nick,pdcc->host,pdcc->file);
}
removepdcc(usern);
}
int pdccfget(int usern)
{
unsigned long acks;
unsigned long *addrptr;
char *pt;
int rc;
struct dcct *pdcc;
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc==NULL) return 0x0;
pdcc->lasttransferred=currentsocket->sock->datalen;
pdcc->transferred+=pdcc->lasttransferred;
/* store data */
rc=fwrite(ircbuf,1,pdcc->lasttransferred,pdcc->fhandle);
if(rc!=pdcc->lasttransferred)
{
if(user(usern)->instate==STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(328),user(usern)->nick,netc,pdcc->nick,pdcc->host,pdcc->file);
fclose(pdcc->fhandle);
removepdcc(usern);
return 0x0;
}
}
/* send back ack */
acks=htonl(pdcc->transferred);
addrptr=&acks;
pt=(char *)addrptr;
writesock_STREAM(currentsocket->sock->syssock,pt,4);
return 0x0;
}
int pdccfclosed(int usern)
{
struct dcct *pdcc;
char netc[20];
netc[0]=0;
if(user(usern)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
pdcc=getpsocketpdcc(usern,currentsocket);
if(pdcc==NULL) return 0x0;
{
if(pdcc->filesize!=pdcc->transferred)
ssnprintf(user(usern)->insock,gettxt(329),user(usern)->nick,netc,pdcc->nick,pdcc->host,pdcc->file);
else
log(LOG_INFO,usern,gettxt(330),pdcc->file,netc,pdcc->nick,pdcc->host);
}
if(pdcc->fhandle!=NULL)
fclose(pdcc->fhandle);
removepdcc(usern);
}
/* add a pending dcc connection */
int addpendingdcc(int usern, int type, char *host, int port, char *nick, char *file, char *newfile, unsigned long fsize, int eproto)
{
struct dcct *pd;
struct socketnodes *ps;
int prt;
char c=1;
int sck;
int proto;
int rc,cnt=0;
#ifdef IPV6
struct hostent *he;
struct sockaddr_in6 sin6;
#endif
struct sockaddr_in sin;
unsigned long flen;
unsigned long dip;
FILE *check;
char myfile[800];
char myhost[200];
char ihost[60];
char en[64],an[64];
char netc[20];
char *nck;
char *fil;
#ifdef HAVE_SSL
int issl=SSL_OFF;
#else
int issl=0;
#endif
int mf=0;
unsigned long dccreq;
int userp=usern;
pcontext;
netc[0]=0;
if(eproto!=0) proto=eproto;
if(user(usern)->parent!=0)
{
userp=user(usern)->parent;
ap_snprintf(netc,sizeof(netc),"%s~",user(usern)->network);
}
switch(type)
{
case PDC_CHATTORQ:
if(user(usern)->outstate!=STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(331),user(usern)->nick);
return -1;
}
if(dcchost[0]==0)
{
log(LOG_ERROR,usern,gettxt(332));
return -1;
}
sck=0;cnt=0;
while(sck<=0 && cnt<20)
{
prt=randport();
sck=createlistener(dcchost,prt,getprotocol(dcchost),1,acceptpdccchat,pdccerror,pdccquery,pdccclosed);
cnt++;
}
if(sck<=0)
{
log(LOG_ERROR,usern,gettxt(333));
return -1;
}
ps=getpsocketbysock(sck);
if(ps==NULL)
{
log(LOG_ERROR,usern,gettxt(334));
return -1;
}
ps->sock->param=usern;
strmncpy(ps->sock->dest,"DCC",sizeof(ps->sock->dest));
pd=createpdcc(usern);
#ifdef HAVE_SSL
if(strstr(nick,"S=")==nick)
{
nck=nick+2;
ps->sock->ssl=SSL_ON;
pd->ssl=SSL_ON;
} else
#endif
nck=nick;
strmncpy(pd->nick,nck,sizeof(pd->nick));
strmncpy(pd->host,ps->sock->source,sizeof(pd->host));
pd->type=PDC_CHATTORQ;
pd->port=prt;
pd->sock=sck;
pd->uid=usern;
pd->delay=50;
if(user(usern)->instate==STD_CONN)
ssnprintf(user(usern)->insock,gettxt(335),user(usern)->nick,netc,pd->nick,pd->host,pd->port);
/* telling the user we want to dcc chat him */
#ifdef HAVE_SSL
if(pd->ssl==SSL_ON)
ssnprintf(user(usern)->outsock,gettxt(336),pd->nick,pd->host);
else
#endif
ssnprintf(user(usern)->outsock,gettxt(337),pd->nick,pd->host);
/* sending the request */
#ifdef IPV6
if(getprotocol(dcchost)==AF_INET6)
{
#ifdef SUNOS
he=getipnodebyname(dcchost,AF_INET6,AI_DEFAULT,&error_num);
#else
he=gethostbyname2(dcchost,AF_INET6);
#endif
if(he!=NULL)
{
memcpy(&sin6.sin6_addr,he->h_addr,he->h_length);
sin6.sin6_family=he->h_addrtype;
inet_ntop(AF_INET6,&sin6,myhost,sizeof(myhost));
ssnprintf(user(usern)->outsock,gettxt(338),pd->nick,c,myhost,pd->port,c);
}
} else
#endif
ssnprintf(user(usern)->outsock,gettxt(339),pd->nick,c,htonl(inet_addr(pd->host)),pd->port,c);
return 0x0;
case PDC_CHATFROMRQ:
dccreq=user(usern)->lastdccchat;
time(&user(usern)->lastdccchat);
if((user(usern)->lastdccchat-dccreq)<5) return -1; /* 5 seconds before next chat */
if(port<1024) return -1; /* silent ignore */
pd=createpdcc(usern);
if(pd!=NULL)
{
pd->delay=50;
pd->uid=usern;
pd->type=PDC_CHATFROMRQ;
pd->port=port;
if(getprotocol(host)==AF_INET) /* bsd does not resolve longs */
{
sscanf(host,"%lu",&dip);
sin.sin_addr.s_addr=htonl(dip);
strmncpy(pd->host,inet_ntoa(sin.sin_addr),sizeof(pd->host));
} else
strmncpy(pd->host,host,sizeof(pd->host));
strmncpy(pd->nick,nick,sizeof(pd->nick));
#ifdef HAVE_SSL
ssnprintf(user(usern)->insock,gettxt(340),user(usern)->nick,netc,pd->nick,pd->nick,pd->nick,pd->host,pd->port);
#else
ssnprintf(user(usern)->insock,gettxt(341),user(usern)->nick,netc,pd->nick,pd->nick,pd->host,pd->port);
#endif
#ifdef SCRIPTING
pd->pid=dccchatscript(usern,ircfrom);
#endif
return 0x0;
}
break;
case PDC_CHATFROM:
pd=user(usern)->pdcc;
#ifdef HAVE_SSL
issl=SSL_OFF;
if(strstr(nick,"S=")==nick)
{
nck=nick+2;
strmncpy(en,nck,sizeof(en));
issl=SSL_ON;
} else
#endif
strmncpy(en,nick,sizeof(en));
ucase(en);
while(pd!=NULL)
{
strmncpy(an,pd->nick,sizeof(an));
ucase(an);
if(pd->type==PDC_CHATFROMRQ && strmcmp(en,an)==1)
{
proto=getprotocol(pd->host);
#ifdef HAVE_SSL
sck=createsocket(0,ST_CONNECT,usern,NULL,pdccconnected,pdccerror,pdccquery,pdccclosed,proto,SSL_OFF);
#else
sck=createsocket(0,ST_CONNECT,usern,NULL,pdccconnected,pdccerror,pdccquery,pdccclosed,proto,0);
#endif
sck=connectto(sck,pd->host,pd->port,NULL);
if(sck!=0) /* silently ignore errors */
{
#ifdef HAVE_SSL
ps=getpsocketbysock(sck);
if(ps!=NULL)
ps->sock->ssl=issl;
pd->ssl=issl;
#endif
pd->sock=sck;
pd->delay=0;
pd->type=PDC_CHATFROM;
return 0;
}
}
pd=pd->next;
}
if(user(usern)->instate==STD_CONN)
ssnprintf(user(usern)->insock,gettxt(342),user(usern)->nick,nick);
break;
case PDC_SENDTORQ:
if(user(usern)->outstate!=STD_CONN)
{
ssnprintf(user(usern)->insock,gettxt(343),user(usern)->nick);
return -1;
}
if(dcchost[0]==0)
{
log(LOG_ERROR,usern,gettxt(344));
return -1;
}
fil=stripdccfile(file,0);
if(fil==NULL)
{
log(LOG_ERROR,usern,gettxt(345),file);
return -1;
}
check=fopen(file,"r");
if(check==NULL)
{
ap_snprintf(myfile,sizeof(myfile),gettxt(346),usern,fil);
check=fopen(myfile,"r");
if(check==NULL)
{
ssnprintf(user(usern)->insock,gettxt(347),user(usern)->nick,file);
return -1;
}
mf=1;
}
fseek(check,0,SEEK_END);
flen=ftell(check);
fclose(check);
sck=0;cnt=0;
while(sck<=0 && cnt<20)
{
prt=randport();
sck=createlistener(dcchost,prt,getprotocol(dcchost),1,acceptpdccfile,pdccfileerror,pdccfilesendack,pdccfileclosed);
cnt++;
}
if(sck<=0)
{
log(LOG_ERROR,usern,gettxt(348));
return -1;
}
ps=getpsocketbysock(sck);
if(ps==NULL)
{
log(LOG_ERROR,usern,gettxt(349));
return -1;
}
ps->sock->param=usern;
strmncpy(ps->sock->dest,"DCC",sizeof(ps->sock->dest));
pd=createpdcc(usern);
#ifdef HAVE_SSL
issl=SSL_OFF;
#else
issl=0;
#endif
#ifdef HAVE_SSL
if(strstr(nick,"S=")==nick)
{
nck=nick+2;
issl=SSL_ON;
} else
nck=nick;
#endif
strmncpy(pd->nick,nck,sizeof(pd->nick));
strmncpy(pd->host,ps->sock->source,sizeof(pd->host));
if(mf==1)
strmncpy(pd->file,myfile,sizeof(pd->file));
else
strmncpy(pd->file,file,sizeof(pd->file));
pd->type=PDC_SENDTORQ;
#ifdef HAVE_SSL
pd->ssl=issl;
ps->sock->ssl=issl;
#endif
pd->port=prt;
pd->sock=sck;
pd->uid=usern;
pd->filesize=flen;
pd->delay=50;
if(user(usern)->instate==STD_CONN)
{
#ifdef HAVE_SSL
if(issl==SSL_ON)
ssnprintf(user(usern)->insock,gettxt(350),user(usern)->nick,fil,netc,pd->nick,pd->host,pd->port);
else
#endif
ssnprintf(user(usern)->insock,gettxt(351),user(usern)->nick,fil,netc,pd->nick,pd->host,pd->port);
}
/* telling the user we want to dcc send him a file */
#ifdef HAVE_SSL
if(issl==SSL_ON)
ssnprintf(user(usern)->outsock,gettxt(352),pd->nick,fil,pd->host);
else
#endif
ssnprintf(user(usern)->outsock,gettxt(353),pd->nick,fil,pd->host);
/* sending the request */
#ifdef IPV6
if(getprotocol(dcchost)==AF_INET6)
{
#ifdef SUNOS
he=getipnodebyname(dcchost,AF_INET6,AI_DEFAULT,&error_num);
#else
he=gethostbyname2(dcchost,AF_INET6);
#endif
if(he!=NULL)
{
memcpy(&sin6.sin6_addr,he->h_addr,he->h_length);
sin6.sin6_family=he->h_addrtype;
inet_ntop(AF_INET6,&sin6,myhost,sizeof(myhost));
ssnprintf(user(usern)->outsock,gettxt(354),pd->nick,c,fil,myhost,pd->port,flen,c);
}
} else
#endif
ssnprintf(user(usern)->outsock,gettxt(355),pd->nick,c,fil,htonl(inet_addr(pd->host)),pd->port,flen,c);
return 0x0;
case PDC_RECVFROMRQ:
if(port<1024) return -1; /* silent ignore of lame from ports */
fil=stripdccfile(file,1);
if(fil==NULL) return -1; /* silent ignore of bogus file sends */
/* file should be the file itself now, without /,.. or ~ */
ap_snprintf(myfile,sizeof(myfile),gettxt(356),usern,fil);
pd=createpdcc(usern);
if(pd!=NULL)
{
pd->delay=50;
pd->uid=usern;
pd->type=PDC_RECVFROMRQ;
pd->port=port;
strmncpy(pd->file,myfile,sizeof(pd->file));
pd->filesize=fsize;
if(getprotocol(host)==AF_INET) /* bsd does not resolve longs */
{
sscanf(host,"%lu",&dip);
sin.sin_addr.s_addr=htonl(dip);
strmncpy(pd->host,inet_ntoa(sin.sin_addr),sizeof(pd->host));
} else
strmncpy(pd->host,host,sizeof(pd->host));
strmncpy(pd->nick,nick,sizeof(pd->nick));
if(user(usern)->autogetdcc==1)
{
ssnprintf(user(usern)->insock,gettxt(357),user(usern)->nick,netc,pd->nick,fil,netc,pd->host,pd->port);
/* recursive */
addpendingdcc(usern, PDC_RECVFROM, pd->host, pd->port, pd->nick, fil, NULL, pd->filesize, getprotocol(pd->host));
} else {
#ifdef HAVE_SSL
ssnprintf(user(usern)->insock,gettxt(358),user(usern)->nick,netc,pd->nick,fil,netc,pd->nick,fil,netc,pd->nick,fil,pd->host,pd->port);
#else
ssnprintf(user(usern)->insock,gettxt(359),user(usern)->nick,netc,pd->nick,fil,netc,pd->nick,fil,pd->host,pd->port);
#endif
}
#ifdef SCRIPTING
strmncpy(irccontent,pd->file,sizeof(irccontent));
pd->pid=dccfilescript(usern,ircfrom);
#endif
return 0x0;
}
break;
case PDC_RECVFROM:
pd=user(usern)->pdcc;
#ifdef HAVE_SSL
issl=SSL_OFF;
if(strstr(nick,"S=")==nick)
{
nck=nick+2;
issl=SSL_ON;
} else
nck=nick;
#endif
while(pd!=NULL)
{
if(pd->type==PDC_RECVFROMRQ && strmcmp(nck,pd->nick)==1)
{
fil=stripdccfile(pd->file,0);
if(fil!=NULL)
{
if (strmcmp(file,fil)!=0 || *file == '*')
{
proto=getprotocol(pd->host);
sck=createsocket(0,ST_CONNECT,usern,NULL,pdccfconnected,pdccferror,pdccfget,pdccfclosed,proto,issl);
sck=connectto(sck,pd->host,pd->port,NULL);
/* offering a possibility to change the filename (RFC..) */
if(newfile!=NULL && *file != '*')
{
strmncpy(pd->file,newfile,sizeof(pd->file));
}
if(sck!=0) /* silently ignore errors */
{
ps=getpsocketbysock(sck);
if(ps!=NULL)
{
ps->sock->dataflow=SD_STREAM;
#ifdef HAVE_SSL
ps->sock->ssl=issl;
#endif
pd->sock=sck;
pd->delay=0;
pd->type=PDC_RECVFROM;
#ifdef HAVE_SSL
pd->ssl=issl;
#endif
return 0x0;
}
}
}
}
}
pd=pd->next;
}
if(user(usern)->instate==STD_CONN)
ssnprintf(user(usern)->insock,gettxt(360),user(usern)->nick,nick,file);
break;
}
return -1;
}
/* querying to a dcc chat */
int querydccchat(int usern, char *nick)
{
struct dcct *pdcc;
pdcc=user(usern)->pdcc;
while(pdcc!=NULL)
{
if(pdcc->type==PDC_CHATFROM || pdcc->type==PDC_CHATTO)
{
if(strmcmp(nick,pdcc->nick)==1)
{
writesock(pdcc->sock,irccontent);
return 0x1;
}
}
pdcc=pdcc->next;
}
return 0x0;
}
/* checking timeouts for userdccs */
int checkdcctimeouts()
{
struct usernodes *un;
struct socketnodes *ps;
struct dcct *pdcc,*epdcc=NULL,*prevdcc=NULL,*ipdcc;
pcontext;
un=usernode;
while(un!=NULL)
{
if(un->user!=NULL)
{
if(un->user->pdcc!=NULL)
{
pdcc=un->user->pdcc;
epdcc=NULL;prevdcc=NULL;
while(pdcc!=NULL)
{
epdcc=pdcc->next;
ipdcc=pdcc;
if((pdcc->type==PDC_SENDTORQ || pdcc->type==PDC_RECVFROMRQ ||
pdcc->type==PDC_CHATTORQ || pdcc->type==PDC_CHATFROMRQ) &&
pdcc->delay>0)
{
pdcc->delay--;
if(pdcc->delay==0)
{
if(prevdcc==NULL)
{
un->user->pdcc=epdcc;
ipdcc=NULL;
} else {
prevdcc->next=epdcc;
ipdcc=prevdcc; /* bug -> just a case of prevdcc */
}
#ifdef SCRIPTING
if(pdcc->pid!=0)
{
if(getsubtaskbypid(pdcc->pid)!=NULL)
terminatetask(pdcc->pid,0);
}
#endif
ps=getpsocketbysock(pdcc->sock);
if(ps!=NULL)
{
killsocket(pdcc->sock);
}
free(pdcc);
}
}
prevdcc=ipdcc;
pdcc=epdcc;
}
}
}
un=un->next;
}
return 0x0;
}
/* list the pending dccs */
int listpdccs(int usern)
{
char *dcckind[]={
"Unknown",
"DCC Chat Request To",
"DCC Chat To",
"DCC Chat Request From",
"DCC Chat From",
"DCC Send Request To",
"DCC Send To ",
"DCC Send Request From",
"DCC Send From",
"Unknown"
};
int idx,pnd=0;
struct dcct *pdcc;
pdcc=user(usern)->pdcc;
while(pdcc!=NULL)
{
idx=pdcc->type;
if(idx>0 && idx <9)
{
if(pnd==0)
{
ssnprintf(user(usern)->insock,gettxt(361),user(usern)->nick);
pnd=1;
}
if(idx>4)
ssnprintf(user(usern)->insock,gettxt(362),user(usern)->nick,pdcc->sock,dcckind[idx],pdcc->nick,pdcc->file);
else
ssnprintf(user(usern)->insock,gettxt(363),user(usern)->nick,pdcc->sock,dcckind[idx],pdcc->nick);
}
pdcc=pdcc->next;
}
if(pnd==1)
{
ssnprintf(user(usern)->insock,gettxt(364),user(usern)->nick);
}
return 0x0;
}
/* cancel a dcc */
int canceldcc(int usern, char *nick, char *file)
{
struct dcct *pdcc,*epdcc;
struct socketnodes *sckn;
char *fil;
sckn=currentsocket;
pdcc=user(usern)->pdcc;
while(pdcc!=NULL)
{
epdcc=pdcc->next;
if(file==NULL && (pdcc->type==PDC_CHATTO || pdcc->type==PDC_CHATFROM))
{
if(strmcmp(nick,pdcc->nick)==1)
{
currentsocket=getpsocketbysock(pdcc->sock);
if(currentsocket!=NULL)
{
pdccerror(usern,0);
}
currentsocket=sckn;
return 0x0;
}
} else
if (file!=NULL)
{
if(pdcc->type==PDC_RECVFROM || pdcc->type==PDC_SENDTO)
{
fil=stripdccfile(pdcc->file,0);
if(fil==NULL) return 0x0;
if(strmcmp(nick,pdcc->nick)==1 && (strmcmp(file,fil)==1 || *file=='*'))
{
currentsocket=getpsocketbysock(pdcc->sock);
if(currentsocket!=NULL)
{
pdccferror(usern,0);
}
currentsocket=sckn;
return 0x0;
}
}
}
pdcc=epdcc;
}
ssnprintf(user(usern)->insock,gettxt(365),user(usern)->nick);
return 0x0;
}
/* answering a ctcp request */
int answerctcp(int usern,char *nick, char *ctcp)
{
char c=1;
char buf[300];
#ifdef SCRIPTING
if(ctcpscript(usern,ctcp)==0)
{
#endif
#ifdef CTCPVERSION
if(strmcmp(ctcp,gettxt(366)))
{
snprintf(buf,sizeof(buf),gettxt(367),nick,c);
ssnprintf(user(usern)->outsock,"%s%s%c",buf,CTCPVERSION,c);
}
#endif
#ifdef SCRIPTING
}
#endif
return 0x0;
}
/* parsing a sent request from a user */
int parsectcps(int usern)
{
static char host[200],file[200];
int port;
unsigned long filelen;
char *pt,*ept,*pt2;
if(*irccontent==0x1 && strmcmp(ircto,user(usern)->nick)==1)
{
if(strchr(irccontent,' ')==NULL)
{
pt=irccontent+1;
pt2=strchr(pt,1);
if(pt2!=NULL)
{
*pt2=0;
return answerctcp(usern,ircnick,pt);
}
/* a request for a ctcp */
} else {
/* an answer or a dcc */
#ifdef DCCCHAT
ept=irccontent+1;
if(strstr(ept,gettxt(368))==ept && user(usern)->dccenabled==1)
{
pt=irccontent+10;
pt=strchr(pt,' ');
if(pt!=NULL)
{
pt++;
pt2=strchr(pt,' ');
if(pt2!=NULL)
{
*pt2=0;
strmncpy(host,pt,sizeof(host));
pt2++;
pt=strchr(pt2,1);
if(pt!=NULL)
{
*pt=0;
port=atoi(pt2);
addpendingdcc(usern, PDC_CHATFROMRQ, host, port, ircnick, NULL, NULL, 0L, getprotocol(host));
return 0x1;
}
}
}
}
#endif
#ifdef DCCFILES
ept=irccontent+1;
if(strstr(ept,gettxt(369))==ept && strmcmp(ircnick,user(usern)->nick)==0 && user(usern)->dccenabled==1)
{
pt=irccontent+10;
pt=strchr(pt,' ');
if(pt!=NULL)
{
*pt=0;
ept=irccontent+10;
strmncpy(file,ept,sizeof(file));
pt++;
pt2=strchr(pt,' ');
if(pt2!=NULL)
{
*pt2=0;
strmncpy(host,pt,sizeof(host));
pt2++;
pt=strchr(pt2,' ');
if(pt!=NULL)
{
*pt=0;
port=atoi(pt2);
pt++;
pt2=strchr(pt,1);
if(pt2!=NULL)
{
*pt2=0;
filelen=atol(pt);
addpendingdcc(usern, PDC_RECVFROMRQ, host, port, ircnick, file, NULL, filelen, getprotocol(host));
return 0x1;
}
}
}
}
}
#endif
}
}
return 0x0;
}
Copyright © 1945 -