#include <bzlib.h>
#include <zlib.h>
#include <sys/stat.h>
+#include <stdint.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
* considering it was developed without i18n support under Windows */
#define DCCHARSET "windows-1252"
-#ifdef DCPP_MASQUERADE
-/*
- * I honestly don't want to pretend being a client that I'm not, but
- * there are so many hubs that simply do not accept any clients
- * outside their whitelists, for no obvious reasons, so I feel that I
- * am left with little choice. Anyhow, as long as I actually support
- * all the features that my faked DC++ version does, there should be
- * very little harm done.
- */
-#define DCIDTAG "++"
-#define DCIDTAGV "0.674"
-#define DCIDFULL "DC++ 0.674"
-#else
-#define DCIDTAG "Dolda"
-#define DCIDTAGV VERSION
-#define DCIDFULL "DoldaConnect " VERSION
-#endif
-
#define PEER_CMD 0
#define PEER_STOP 1
#define PEER_TRNS 2
char *inbuf;
size_t inbufdata, inbufsize;
off_t curread, totalsize;
- int freeing;
+ int close;
struct timer *timeout;
struct qcmdqueue queue;
struct transfer *transfer;
if((buf = path2nmdc(peer->transfer->path, DCCHARSET)) == NULL)
{
transferseterror(peer->transfer, TRNSE_NOTFOUND);
- freedcpeer(peer);
+ peer->close = 1;
return;
}
/* The transfer will be restarted later from
if((buf = getadcid(peer)) == NULL)
{
transferseterror(peer->transfer, TRNSE_NOTFOUND);
- freedcpeer(peer);
+ peer->close = 1;
return;
}
sendadc(peer->sk, buf);
if(forkfilter(peer->transfer))
{
flog(LOG_WARNING, "could not fork filter for transfer %i: %s", peer->transfer->id, strerror(errno));
- freedcpeer(peer);
+ peer->close = 1;
return;
}
CBREG(peer->transfer, trans_filterout, (int (*)(struct transfer *, wchar_t *, wchar_t *, void *))trresumecb, NULL, peer);
if((buf = getadcid(peer)) == NULL)
{
transferseterror(peer->transfer, TRNSE_NOTFOUND);
- freedcpeer(peer);
+ peer->close = 1;
return;
}
sendadc(peer->sk, buf);
if((buf = path2nmdc(peer->transfer->path, "UTF-8")) == NULL)
{
transferseterror(peer->transfer, TRNSE_NOTFOUND);
- freedcpeer(peer);
+ peer->close = 1;
return;
}
qstrf(peer->sk, "$UGetBlock %ji %ji %s|", (intmax_t)peer->transfer->curpos, (intmax_t)(peer->transfer->size - peer->transfer->curpos), buf);
if((buf = path2nmdc(peer->transfer->path, DCCHARSET)) == NULL)
{
transferseterror(peer->transfer, TRNSE_NOTFOUND);
- freedcpeer(peer);
+ peer->close = 1;
return;
}
qstrf(peer->sk, "$Get %s$%ji|", buf, (intmax_t)peer->transfer->curpos + 1);
size_t buflen;
int termnum, satisfied, skipcheck;
int level, tersat[32];
- wchar_t *terms[32];
+ wchar_t *terms[32], *lname;
char hashtth[24];
hub = fn->data;
memcpy(hashtth, buf, 24);
free(buf);
} else {
- if((terms[termnum] = icmbstowcs(p, hub->charset)) != NULL)
+ if((terms[termnum] = icmbstowcs(p, hub->charset)) != NULL) {
+ wcslower(terms[termnum]);
termnum++;
+ }
}
}
p = p2 + 1;
}
if(!skipcheck)
{
+ lname = wcslower(swcsdup(node->name));
for(i = 0; i < termnum; i++)
{
if(tersat[i] >= 0)
continue;
- if(wcsexists(node->name, terms[i]))
+ if(wcsstr(lname, terms[i]))
{
tersat[i] = level;
satisfied++;
break;
}
}
+ free(lname);
}
if(!skipcheck && (satisfied == termnum))
{
free(peer->wcsname);
if((peer->wcsname = icmbstowcs(peer->nativename, peer->charset)) == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if(peer->accepted)
{
if((peer->transfer == NULL) || (mydir != peer->direction))
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if(peer->direction == TRNSD_DOWN)
} else {
if(peer->wcsname == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
peer->direction = mydir;
{
if(confgetint("transfer", "ulquota") && hasupload(&dcnet, peer->wcsname))
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
transfer = newupload(peer->fn, &dcnet, peer->wcsname, &dctransfer, peer);
} else {
if((transfer = finddownload(peer->wcsname)) == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
transferattach(transfer, &dctransfer, peer);
{
if(peer->wcsname == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
sendmynick(peer);
{
if(confgetint("transfer", "ulquota") && hasupload(&dcnet, peer->wcsname))
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
peer->direction = TRNSD_UP;
if(peer->transfer == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
size = strtoll(args, NULL, 10);
{
transfersetsize(peer->transfer, size);
transfer = peer->transfer;
- freedcpeer(peer);
+ peer->close = 1;
+ resettransfer(transfer);
trytransferbypeer(transfer->fnet, transfer->peerid);
return;
}
resettransfer(peer->transfer);
return;
}
- freedcpeer(peer);
+ peer->close = 1;
}
static void cmd_maxedout(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
resettransfer(peer->transfer);
return;
}
- freedcpeer(peer);
+ peer->close = 1;
}
static struct
if(peer->transfer == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if((p = strchr(args, '$')) == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
*(p++) = 0;
if((offset = (strtoll(p, NULL, 10) - 1)) < 0)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if(((fd = openfilelist(args)) < 0) && (errno != 0))
{
qstr(sk, "$Error Could not send file list|");
- freedcpeer(peer);
+ peer->close = 1;
return;
} else if(fd >= 0) {
if((buf2 = nmdc2path(args, DCCHARSET)) != NULL) {
if((node = resdcpath(args, DCCHARSET, '\\')) == NULL)
{
qstrf(sk, "$Error File not in share|");
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if((fd = opensharecache(node)) < 0)
{
qstrf(sk, "$Error %s|", strerror(errno));
- freedcpeer(peer);
+ peer->close = 1;
return;
}
buf = getfspath(node);
close(fd);
flog(LOG_WARNING, "could not stat file %ls: %s", node->name, strerror(errno));
qstrf(sk, "$Error|");
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if(sb.st_size < 65536)
if(!peer->transfer->flags.b.minislot && (slotsleft() < 1)) {
close(fd);
qstr(sk, "$MaxedOut|");
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if((offset != 0) && (lseek(fd, offset, SEEK_SET) < 0))
{
close(fd);
qstrf(sk, "$Error Offset out of range|");
- freedcpeer(peer);
+ peer->close = 1;
return;
}
lesk = wrapsock(fd);
{
if(peer->transfer == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if(peer->transfer->localend == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
peer->ptclose = 1;
if(peer->transfer == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
p = args;
if((p2 = strchr(p, ' ')) == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
*(p2++) = 0;
p = p2;
if((p2 = strchr(p, ' ')) == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
*(p2++) = 0;
if(peer->transfer == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if((argv = parseadc(args)) == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if(parrlen(argv) < 4)
{
- freedcpeer(peer);
+ peer->close = 1;
goto out;
}
start = strtoll(argv[2], NULL, 10);
} else if(fd >= 0) {
if((wbuf = adc2path(argv[1])) != NULL)
transfersetpath(peer->transfer, wbuf);
+ free(wbuf);
peer->transfer->flags.b.minislot = 1;
}
if(fd < 0)
if(peer->transfer == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if((argv = parseadc(args)) == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
if(parrlen(argv) < 4)
{
- freedcpeer(peer);
+ peer->close = 1;
goto out;
}
start = strtoll(argv[2], NULL, 10);
if((start != 0) || (numbytes % 24 != 0))
{
/* Weird. Bail out. */
- freedcpeer(peer);
+ peer->close = 1;
goto out;
}
if(peer->timeout != NULL)
} else if(!strcmp(argv[0], "file")) {
if(start != peer->transfer->curpos)
{
- freedcpeer(peer);
+ peer->close = 1;
goto out;
}
if(start + numbytes != peer->transfer->size)
{
transfersetsize(peer->transfer, start + numbytes);
- freedcpeer(peer);
+ peer->close = 1;
goto out;
}
startdl(peer);
}
} else {
/* We certainly didn't request this...*/
- freedcpeer(peer);
+ peer->close = 1;
goto out;
}
if(peer->transfer == NULL)
{
- freedcpeer(peer);
+ peer->close = 1;
return;
}
numbytes = strtoll(args, NULL, 10);
if(peer->transfer->size - peer->transfer->curpos != numbytes)
{
transfersetsize(peer->transfer, peer->transfer->curpos + numbytes);
- freedcpeer(peer);
+ peer->close = 1;
return;
}
startdl(peer);
static void dctransdetach(struct transfer *transfer, struct dcpeer *peer)
{
CBUNREG(transfer, trans_filterout, peer);
- if(peer->freeing)
- return;
peer->transfer = NULL;
- freedcpeer(peer);
+ peer->close = 1;
}
static void dctransgotdata(struct transfer *transfer, struct dcpeer *peer)
struct command *cmd;
char *newbuf;
size_t datalen, cnlen;
- char *p;
+ char *p, *p2;
hub = (struct dchub *)fn->data;
if((newbuf = sockgetinbuf(sk, &datalen)) == NULL)
sizebuf2(hub->inbuf, hub->inbufdata + datalen, 1);
memcpy(hub->inbuf + hub->inbufdata, newbuf, datalen);
free(newbuf);
- p = hub->inbuf + hub->inbufdata;
+ p = hub->inbuf;
hub->inbufdata += datalen;
- while((datalen > 0) && ((p = memchr(p, '|', datalen)) != NULL))
+ while((p - hub->inbuf < hub->inbufdata) && ((p2 = memchr(p, '|', hub->inbufdata - (p - hub->inbuf))) != NULL))
{
- *(p++) = 0;
+ *(p2++) = 0;
for(cmd = hubcmds; cmd->handler != NULL; cmd++)
{
cnlen = strlen(cmd->name);
- if(!strncmp(hub->inbuf, cmd->name, cnlen) && ((hub->inbuf[cnlen] == ' ') || (hub->inbuf[cnlen] == 0)))
+ if(!strncmp(p, cmd->name, cnlen) && ((p[cnlen] == ' ') || (p[cnlen] == 0)))
break;
}
if((cmd->limit == 0) || (hub->queue.size < cmd->limit))
- newqcmd(&hub->queue, hub->inbuf);
- memmove(hub->inbuf, p, hub->inbufdata -= p - hub->inbuf);
- datalen = hub->inbufdata;
- p = hub->inbuf;
+ newqcmd(&hub->queue, p);
+ p = p2;
}
+ memmove(hub->inbuf, p, hub->inbufdata -= p - hub->inbuf);
if(hub->queue.size > 1000)
sk->ignread = 1;
}
int i;
struct qcommand *qcmd;
- peer->freeing = 1;
if(peers == peer)
peers = peer->next;
if(peer->next != NULL)
peer->transfer->close = 1;
if(peer->transfer->dir == TRNSD_DOWN)
resettransfer(peer->transfer);
- transferdetach(peer->transfer);
}
if(peer->timeout != NULL)
canceltimer(peer->timeout);
hub->sk->close = 1;
}
-static wchar_t *dcbasename(wchar_t *filename)
-{
- wchar_t *ret;
-
- if((ret = wcsrchr(filename, L'/')) != NULL)
- return(ret + 1);
- return(filename);
-}
-
static struct transferiface dctransfer =
{
.detach = (void (*)(struct transfer *, void *))dctransdetach,
.reqconn = hubreqconn,
.sendchat = hubsendchat,
.search = hubsearch,
- .filebasename = dcbasename
};
static void peerread(struct socket *sk, struct dcpeer *peer)
char *buf, *buf2, numbuf[32];
size_t bufsize, bufdata;
int fd, ibuf;
+ FILE *out;
bufdata = 0;
buf = smalloc(bufsize = 65536);
free(hmlistname);
hmlistname = NULL;
} else {
+ out = fdopen(fd, "w");
/*
* I do not want to implement a good Huffman encoder, and it's not
* like Huffman encoding actually yields any impressive results
* for DC file lists anyway, so I'll just output a bogus
* tree. Implement a good encoder if you want to.
*/
- write(fd, "HE3\r\0", 5);
- write(fd, &bufdata, 4);
+ fwrite("HE3\r\0", 1, 5, out);
+ fwrite(&bufdata, 4, 1, out); /* XXX: Endian unsafe */
ibuf = 256;
- write(fd, &ibuf, 2);
+ fwrite(&ibuf, 2, 1, out);
ibuf = 8;
for(i = 0; i < 256; i++)
{
- write(fd, &i, 1);
- write(fd, &ibuf, 1);
+ fwrite(&i, 1, 1, out);
+ fwrite(&ibuf, 1, 1, out);
}
for(i = 0; i < 256; i++)
- write(fd, &i, 1);
+ fwrite(&i, 1, 1, out);
for(buf2 = buf; bufdata > 0;)
{
- if((ret = write(fd, buf2, bufdata)) < 0)
+ if((ret = fwrite(buf2, 1, bufdata, out)) < 0)
{
flog(LOG_WARNING, "could not write file list: %s", strerror(errno));
break;
bufdata -= ret;
buf2 += ret;
}
- close(fd);
+ fclose(out);
}
free(buf);
}
break;
}
quota = 20;
- for(peer = peers; peer != NULL; peer = nextpeer)
+ for(peer = peers; peer != NULL; peer = peer->next)
{
- nextpeer = peer->next;
- while((quota > 0) && ((qcmd = ulqcmd(&peer->queue)) != NULL))
+ while(!peer->close && (quota > 0) && ((qcmd = ulqcmd(&peer->queue)) != NULL))
{
if(peer->timeout != NULL)
canceltimer(peer->timeout);
if(quota < 1)
break;
}
+ for(peer = peers; peer != NULL; peer = nextpeer)
+ {
+ nextpeer = peer->next;
+ if(peer->close)
+ freedcpeer(peer);
+ }
return(ret);
}