/*
* transferqueue.c -- part of transfer.mod
*
* $Id: transferqueue.c,v 1.7 2006-03-28 02:35:51 wcc Exp $
*
* Copyright (C) 2003 - 2006 Eggheads Development Team
*
* 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.
*/
static int expmem_fileq()
{
fileq_t *q;
int tot = 0;
for (q = fileq; q; q = q->next)
tot += strlen(q->dir) + strlen(q->file) + 2 + sizeof(fileq_t);
return tot;
}
static void queue_file(char *dir, char *file, char *from, char *to)
{
fileq_t *q = fileq;
fileq = nmalloc(sizeof *fileq);
fileq->next = q;
fileq->dir = nmalloc(strlen(dir) + 1);
fileq->file = nmalloc(strlen(file) + 1);
strcpy(fileq->dir, dir);
strcpy(fileq->file, file);
strcpy(fileq->nick, from);
strcpy(fileq->to, to);
}
static void deq_this(fileq_t *this)
{
fileq_t *q = fileq, *last = NULL;
while (q && q != this) {
last = q;
q = q->next;
}
if (!q)
return;
if (last)
last->next = q->next;
else
fileq = q->next;
nfree(q->dir);
nfree(q->file);
nfree(q);
}
/* Remove all files queued to a certain user.
*/
static void flush_fileq(char *to)
{
fileq_t *q = fileq;
int fnd = 1;
while (fnd) {
q = fileq;
fnd = 0;
while (q != NULL) {
if (!egg_strcasecmp(q->to, to)) {
deq_this(q);
q = NULL;
fnd = 1;
}
if (q != NULL)
q = q->next;
}
}
}
static void send_next_file(char *to)
{
fileq_t *q, *this = NULL;
char *s, *s1;
int x;
for (q = fileq; q; q = q->next)
if (!egg_strcasecmp(q->to, to))
this = q;
if (this == NULL)
return;
if (this->dir[0] == '*') { /* Absolute path */
s = nmalloc(strlen(&this->dir[1]) + strlen(this->file) + 2);
sprintf(s, "%s/%s", &this->dir[1], this->file);
} else {
char *p = strchr(this->dir, '*');
if (p == NULL) {
send_next_file(to);
return;
}
p++;
s = nmalloc(strlen(p) + strlen(this->file) + 2);
sprintf(s, "%s%s%s", p, p[0] ? "/" : "", this->file);
strcpy(this->dir, &(p[atoi(this->dir)]));
}
if (copy_to_tmp) {
s1 = nmalloc(strlen(tempdir) + strlen(this->file) + 1);
sprintf(s1, "%s%s", tempdir, this->file);
if (copyfile(s, s1) != 0) {
putlog(LOG_FILES | LOG_MISC, "*", TRANSFER_COPY_FAILED, this->file,
tempdir);
dprintf(DP_HELP, TRANSFER_FILESYS_BROKEN, this->to);
strcpy(s, this->to);
flush_fileq(s);
nfree(s1);
nfree(s);
return;
}
} else {
s1 = nmalloc(strlen(s) + 1);
strcpy(s1, s);
}
if (this->dir[0] == '*') {
s = nrealloc(s, strlen(&this->dir[1]) + strlen(this->file) + 2);
sprintf(s, "%s/%s", &this->dir[1], this->file);
} else {
s = nrealloc(s, strlen(this->dir) + strlen(this->file) + 2);
sprintf(s, "%s%s%s", this->dir, this->dir[0] ? "/" : "", this->file);
}
x = raw_dcc_send(s1, this->to, this->nick, s);
if (x == DCCSEND_OK) {
if (egg_strcasecmp(this->to, this->nick))
dprintf(DP_HELP, TRANSFER_FILE_ARRIVE, this->to, this->nick);
deq_this(this);
nfree(s);
nfree(s1);
return;
}
wipe_tmp_filename(s1, -1);
if (x == DCCSEND_FULL) {
putlog(LOG_FILES, "*", TRANSFER_LOG_CONFULL, s1, this->nick);
dprintf(DP_HELP, TRANSFER_NOTICE_CONFULL, this->to);
strcpy(s, this->to);
flush_fileq(s);
} else if (x == DCCSEND_NOSOCK) {
putlog(LOG_FILES, "*", TRANSFER_LOG_SOCKERR, s1, this->nick);
dprintf(DP_HELP, TRANSFER_NOTICE_SOCKERR, this->to);
strcpy(s, this->to);
flush_fileq(s);
} else {
if (x == DCCSEND_FEMPTY) {
putlog(LOG_FILES, "*", TRANSFER_LOG_FILEEMPTY, this->file);
dprintf(DP_HELP, TRANSFER_NOTICE_FILEEMPTY, this->to, this->file);
}
deq_this(this);
}
nfree(s);
nfree(s1);
return;
}
static void show_queued_files(int idx)
{
int i, cnt = 0, len;
char spaces[] = " ";
fileq_t *q;
for (q = fileq; q; q = q->next) {
if (!egg_strcasecmp(q->nick, dcc[idx].nick)) {
if (!cnt) {
spaces[HANDLEN - 9] = 0;
dprintf(idx, TRANSFER_SEND_TO, spaces);
dprintf(idx, TRANSFER_LINES, spaces);
spaces[HANDLEN - 9] = ' ';
}
cnt++;
spaces[len = HANDLEN - strlen(q->to)] = 0;
if (q->dir[0] == '*')
dprintf(idx, " %s%s %s/%s\n", q->to, spaces, &q->dir[1], q->file);
else
dprintf(idx, " %s%s /%s%s%s\n", q->to, spaces, q->dir,
q->dir[0] ? "/" : "", q->file);
spaces[len] = ' ';
}
}
for (i = 0; i < dcc_total; i++) {
if ((dcc[i].type == &DCC_GET_PENDING || dcc[i].type == &DCC_GET) &&
(!egg_strcasecmp(dcc[i].nick, dcc[idx].nick) ||
!egg_strcasecmp(dcc[i].u.xfer->from, dcc[idx].nick))) {
char *nfn;
if (!cnt) {
spaces[HANDLEN - 9] = 0;
dprintf(idx, TRANSFER_SEND_TO, spaces);
dprintf(idx, TRANSFER_LINES, spaces);
spaces[HANDLEN - 9] = ' ';
}
nfn = strrchr(dcc[i].u.xfer->origname, '/');
if (nfn == NULL)
nfn = dcc[i].u.xfer->origname;
else
nfn++;
cnt++;
spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
if (dcc[i].type == &DCC_GET_PENDING)
dprintf(idx, TRANSFER_WAITING, dcc[i].nick, spaces, nfn);
else
dprintf(idx, TRANSFER_DONE, dcc[i].nick, spaces, nfn, (100.0 *
((float) dcc[i].status / (float) dcc[i].u.xfer->length)));
spaces[len] = ' ';
}
}
if (!cnt)
dprintf(idx, TRANSFER_QUEUED_UP);
else
dprintf(idx, TRANSFER_TOTAL, cnt);
}
static void fileq_cancel(int idx, char *par)
{
int fnd = 1, matches = 0, atot = 0, i;
fileq_t *q;
char *s = NULL;
while (fnd) {
q = fileq;
fnd = 0;
while (q != NULL) {
if (!egg_strcasecmp(dcc[idx].nick, q->nick)) {
s = nrealloc(s, strlen(q->dir) + strlen(q->file) + 3);
if (q->dir[0] == '*')
sprintf(s, "%s/%s", &q->dir[1], q->file);
else
sprintf(s, "/%s%s%s", q->dir, q->dir[0] ? "/" : "", q->file);
if (wild_match_file(par, s)) {
dprintf(idx, TRANSFER_CANCELLED, s, q->to);
fnd = 1;
deq_this(q);
q = NULL;
matches++;
}
if (!fnd && wild_match_file(par, q->file)) {
dprintf(idx, TRANSFER_CANCELLED, s, q->to);
fnd = 1;
deq_this(q);
q = NULL;
matches++;
}
}
if (q != NULL)
q = q->next;
}
}
if (s)
nfree(s);
for (i = 0; i < dcc_total; i++) {
if ((dcc[i].type == &DCC_GET_PENDING || dcc[i].type == &DCC_GET) &&
(!egg_strcasecmp(dcc[i].nick, dcc[idx].nick) ||
!egg_strcasecmp(dcc[i].u.xfer->from, dcc[idx].nick))) {
char *nfn = strrchr(dcc[i].u.xfer->origname, '/');
if (nfn == NULL)
nfn = dcc[i].u.xfer->origname;
else
nfn++;
if (wild_match_file(par, nfn)) {
dprintf(idx, TRANSFER_ABORT_DCCSEND, nfn);
if (egg_strcasecmp(dcc[i].nick, dcc[idx].nick))
dprintf(DP_HELP, TRANSFER_NOTICE_ABORT, dcc[i].nick, nfn,
dcc[idx].nick);
if (dcc[i].type == &DCC_GET)
putlog(LOG_FILES, "*", TRANSFER_DCC_CANCEL, nfn, dcc[i].nick,
dcc[i].status, dcc[i].u.xfer->length);
wipe_tmp_filename(dcc[i].u.xfer->filename, i);
atot++;
matches++;
killsock(dcc[i].sock);
lostdcc(i);
}
}
}
if (!matches)
dprintf(idx, TRANSFER_NO_MATCHES);
else
dprintf(idx, TRANSFER_CANCELLED_FILE, matches, (matches != 1) ? "s" : "");
for (i = 0; i < atot; i++)
if (!at_limit(dcc[idx].nick))
send_next_file(dcc[idx].nick);
}
syntax highlighted by Code2HTML, v. 0.9.1