00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #define MODULE_NAME "share"
00026 #define MAKING_SHARE
00027
00028 #include "src/mod/module.h"
00029
00030 #include <netinet/in.h>
00031 #include <arpa/inet.h>
00032 #include <sys/stat.h>
00033
00034 #include "src/chan.h"
00035 #include "src/users.h"
00036 #include "transfer.mod/transfer.h"
00037 #include "channels.mod/channels.h"
00038
00039
00040 static const int min_share = 1029900;
00041
00042
00043 static const int min_exemptinvite = 1032800;
00044
00045
00046 static const int min_uffeature = 1050200;
00047
00048 static Function *global = NULL, *transfer_funcs = NULL, *channels_funcs = NULL;
00049
00050 static int private_global = 0;
00051 static int private_user = 0;
00052 static char private_globals[50];
00053 static int allow_resync = 0;
00054 static struct flag_record fr = { 0, 0, 0, 0, 0, 0 };
00055 static int resync_time = 900;
00056 static int overr_local_bots = 0;
00057
00058
00059
00060 struct share_msgq {
00061 struct chanset_t *chan;
00062 char *msg;
00063 struct share_msgq *next;
00064 };
00065
00066 typedef struct tandbuf_t {
00067 char bot[HANDLEN + 1];
00068 time_t timer;
00069 struct share_msgq *q;
00070 struct tandbuf_t *next;
00071 } tandbuf;
00072
00073 tandbuf *tbuf;
00074
00075
00076 static void start_sending_users(int);
00077 static void shareout_but EGG_VARARGS(struct chanset_t *, arg1);
00078 static int flush_tbuf(char *);
00079 static int can_resync(char *);
00080 static void dump_resync(int);
00081 static void q_resync(char *, struct chanset_t *);
00082 static void cancel_user_xfer(int, void *);
00083 static int private_globals_bitmask();
00084
00085 #include "share.h"
00086
00087 #include "uf_features.c"
00088
00089
00090
00091
00092
00093 struct delay_mode {
00094 struct delay_mode *next;
00095 struct chanset_t *chan;
00096 int plsmns;
00097 int mode;
00098 char *mask;
00099 time_t seconds;
00100 };
00101
00102 static struct delay_mode *delay_head = NULL, *delay_tail = NULL;
00103
00104 static void add_delay(struct chanset_t *chan, int plsmns, int mode, char *mask)
00105 {
00106 struct delay_mode *d = NULL;
00107
00108 d = nmalloc(sizeof *d);
00109
00110 d->chan = chan;
00111 d->plsmns = plsmns;
00112 d->mode = mode;
00113 d->seconds = now + randint(30);
00114
00115 d->mask = nmalloc(strlen(mask) + 1);
00116 strncpyz(d->mask, mask, strlen(mask) + 1);
00117
00118 if (!delay_head)
00119 delay_head = d;
00120 else
00121 delay_tail->next = d;
00122
00123 d->next = NULL;
00124 delay_tail = d;
00125 }
00126
00127 static void check_delay()
00128 {
00129 struct delay_mode *d = NULL, *prev = NULL, *dnext = NULL;
00130
00131 for (d = delay_head; d; d = dnext) {
00132 dnext = d->next;
00133
00134 if (d->seconds <= now) {
00135
00136 add_mode(d->chan, d->plsmns, d->mode, d->mask);
00137
00138 if (prev)
00139 prev->next = d->next;
00140 else
00141 delay_head = d->next;
00142
00143 if (delay_tail == d)
00144 delay_tail = prev;
00145
00146 if (d->mask)
00147 nfree(d->mask);
00148
00149 nfree(d);
00150 }
00151 else {
00152 prev = d;
00153 }
00154 }
00155 }
00156
00157 static void delay_free_mem()
00158 {
00159 struct delay_mode *d = NULL, *dnext = NULL;
00160
00161 for (d = delay_head; d; d = dnext) {
00162 dnext = d->next;
00163
00164 if (d->mask)
00165 nfree(d->mask);
00166
00167 nfree(d);
00168 }
00169
00170 delay_head = NULL;
00171 delay_tail = NULL;
00172 }
00173
00174 static int delay_expmem()
00175 {
00176 int size = 0;
00177 struct delay_mode *d = NULL;
00178
00179 for (d = delay_head; d; d = d->next) {
00180
00181 if (d->mask)
00182 size += strlen(d->mask) + 1;
00183
00184 size += sizeof(struct delay_mode);
00185 }
00186
00187 return size;
00188 }
00189
00190
00191
00192
00193
00194 static void share_stick_ban(int idx, char *par)
00195 {
00196 char *host, *val;
00197 int yn;
00198
00199 if (dcc[idx].status & STAT_SHARE) {
00200 host = newsplit(&par);
00201 val = newsplit(&par);
00202 yn = atoi(val);
00203 noshare = 1;
00204 if (!par[0]) {
00205 if (u_setsticky_ban(NULL, host, yn) > 0) {
00206 putlog(LOG_CMDS, "*", "%s: %s %s", dcc[idx].nick,
00207 (yn) ? "stick" : "unstick", host);
00208 shareout_but(NULL, idx, "s %s %d\n", host, yn);
00209 }
00210 } else {
00211 struct chanset_t *chan = findchan_by_dname(par);
00212 struct chanuserrec *cr;
00213
00214 if ((chan != NULL) && ((channel_shared(chan) &&
00215 ((cr = get_chanrec(dcc[idx].user, par)) &&
00216 (cr->flags & BOT_AGGRESSIVE))) ||
00217 (bot_flags(dcc[idx].user) & BOT_GLOBAL)))
00218 if (u_setsticky_ban(chan, host, yn) > 0) {
00219 putlog(LOG_CMDS, "*", "%s: %s %s %s", dcc[idx].nick,
00220 (yn) ? "stick" : "unstick", host, par);
00221 shareout_but(chan, idx, "s %s %d %s\n", host, yn, chan->dname);
00222 noshare = 0;
00223 return;
00224 }
00225 putlog(LOG_CMDS, "*", "Rejecting invalid sticky ban: %s on %s%s",
00226 host, par, yn ? "" : " (unstick)");
00227 }
00228 noshare = 0;
00229 }
00230 }
00231
00232
00233
00234 static void share_stick_exempt(int idx, char *par)
00235 {
00236 char *host, *val;
00237 int yn;
00238
00239 if (dcc[idx].status & STAT_SHARE) {
00240 host = newsplit(&par);
00241 val = newsplit(&par);
00242 yn = atoi(val);
00243 noshare = 1;
00244 if (!par[0]) {
00245 if (u_setsticky_exempt(NULL, host, yn) > 0) {
00246 putlog(LOG_CMDS, "*", "%s: %s %s", dcc[idx].nick,
00247 (yn) ? "stick" : "unstick", host);
00248 shareout_but(NULL, idx, "se %s %d\n", host, yn);
00249 }
00250 } else {
00251 struct chanset_t *chan = findchan_by_dname(par);
00252 struct chanuserrec *cr;
00253
00254 if ((chan != NULL) && ((channel_shared(chan) &&
00255 ((cr = get_chanrec(dcc[idx].user, par)) &&
00256 (cr->flags & BOT_AGGRESSIVE))) ||
00257 (bot_flags(dcc[idx].user) & BOT_GLOBAL)))
00258 if (u_setsticky_exempt(chan, host, yn) > 0) {
00259 putlog(LOG_CMDS, "*", "%s: %s %s %s", dcc[idx].nick,
00260 (yn) ? "stick" : "unstick", host, par);
00261 shareout_but(chan, idx, "se %s %d %s\n", host, yn, chan->dname);
00262 noshare = 0;
00263 return;
00264 }
00265 putlog(LOG_CMDS, "*", "Rejecting invalid sticky exempt: %s on %s%s",
00266 host, par, yn ? "" : " (unstick)");
00267 }
00268 noshare = 0;
00269 }
00270 }
00271
00272
00273
00274 static void share_stick_invite(int idx, char *par)
00275 {
00276 char *host, *val;
00277 int yn;
00278
00279 if (dcc[idx].status & STAT_SHARE) {
00280 host = newsplit(&par);
00281 val = newsplit(&par);
00282 yn = atoi(val);
00283 noshare = 1;
00284 if (!par[0]) {
00285 if (u_setsticky_invite(NULL, host, yn) > 0) {
00286 putlog(LOG_CMDS, "*", "%s: %s %s", dcc[idx].nick,
00287 (yn) ? "stick" : "unstick", host);
00288 shareout_but(NULL, idx, "sInv %s %d\n", host, yn);
00289 }
00290 } else {
00291 struct chanset_t *chan = findchan_by_dname(par);
00292 struct chanuserrec *cr;
00293
00294 if ((chan != NULL) && ((channel_shared(chan) &&
00295 ((cr = get_chanrec(dcc[idx].user, par)) &&
00296 (cr->flags & BOT_AGGRESSIVE))) ||
00297 (bot_flags(dcc[idx].user) & BOT_GLOBAL)))
00298 if (u_setsticky_invite(chan, host, yn) > 0) {
00299 putlog(LOG_CMDS, "*", "%s: %s %s %s", dcc[idx].nick,
00300 (yn) ? "stick" : "unstick", host, par);
00301 shareout_but(chan, idx, "sInv %s %d %s\n", host, yn, chan->dname);
00302 noshare = 0;
00303 return;
00304 }
00305 putlog(LOG_CMDS, "*", "Rejecting invalid sticky invite: %s on %s%s",
00306 host, par, yn ? "" : " (unstick)");
00307 }
00308 noshare = 0;
00309 }
00310 }
00311
00312 static void share_chhand(int idx, char *par)
00313 {
00314 char *hand;
00315 struct userrec *u;
00316
00317 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00318 hand = newsplit(&par);
00319 u = get_user_by_handle(userlist, hand);
00320 if (u && !(u->flags & USER_UNSHARED)) {
00321 shareout_but(NULL, idx, "h %s %s\n", hand, par);
00322 noshare = 1;
00323 if (change_handle(u, par))
00324 putlog(LOG_CMDS, "*", "%s: handle %s->%s", dcc[idx].nick, hand, par);
00325 noshare = 0;
00326 }
00327 }
00328 }
00329
00330 static void share_chattr(int idx, char *par)
00331 {
00332 char *hand, *atr, s[100];
00333 struct chanset_t *cst;
00334 struct userrec *u;
00335 struct flag_record fr2;
00336 int bfl, ofl;
00337 module_entry *me;
00338
00339 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00340 hand = newsplit(&par);
00341 u = get_user_by_handle(userlist, hand);
00342 if (u && !(u->flags & USER_UNSHARED)) {
00343 atr = newsplit(&par);
00344 cst = findchan_by_dname(par);
00345 if (!par[0] || (cst && channel_shared(cst))) {
00346 if (!(dcc[idx].status & STAT_GETTING) && (cst || !private_global))
00347 shareout_but(cst, idx, "a %s %s %s\n", hand, atr, par);
00348 noshare = 1;
00349 if (par[0] && cst) {
00350 fr.match = (FR_CHAN | FR_BOT);
00351 get_user_flagrec(dcc[idx].user, &fr, par);
00352 if (bot_chan(fr) || bot_global(fr)) {
00353 fr.match = FR_CHAN;
00354 fr2.match = FR_CHAN;
00355 break_down_flags(atr, &fr, 0);
00356 get_user_flagrec(u, &fr2, par);
00357 fr.chan = (fr2.chan & BOT_AGGRESSIVE) |
00358 (fr.chan & ~BOT_AGGRESSIVE);
00359 set_user_flagrec(u, &fr, par);
00360 check_dcc_chanattrs(u, par, fr.chan, fr2.chan);
00361 noshare = 0;
00362 build_flags(s, &fr, 0);
00363 if (!(dcc[idx].status & STAT_GETTING))
00364 putlog(LOG_CMDS, "*", "%s: chattr %s %s %s",
00365 dcc[idx].nick, hand, s, par);
00366 if ((me = module_find("irc", 0, 0))) {
00367 Function *func = me->funcs;
00368
00369 (func[IRC_RECHECK_CHANNEL]) (cst, 0);
00370 }
00371 } else
00372 putlog(LOG_CMDS, "*",
00373 "Rejected flags for unshared channel %s from %s",
00374 par, dcc[idx].nick);
00375 } else if (!private_global) {
00376 int pgbm = private_globals_bitmask();
00377
00378
00379 fr.match = FR_GLOBAL;
00380 break_down_flags(atr, &fr, 0);
00381 bfl = u->flags & USER_BOT;
00382 ofl = fr.global;
00383 fr.global = (fr.global &~pgbm) | (u->flags & pgbm);
00384 fr.global = sanity_check(fr.global |bfl);
00385
00386 set_user_flagrec(u, &fr, 0);
00387 check_dcc_attrs(u, ofl);
00388 noshare = 0;
00389 build_flags(s, &fr, 0);
00390 fr.match = FR_CHAN;
00391 if (!(dcc[idx].status & STAT_GETTING))
00392 putlog(LOG_CMDS, "*", "%s: chattr %s %s", dcc[idx].nick, hand, s);
00393 if ((me = module_find("irc", 0, 0))) {
00394 Function *func = me->funcs;
00395
00396 for (cst = chanset; cst; cst = cst->next)
00397 (func[IRC_RECHECK_CHANNEL]) (cst, 0);
00398 }
00399 } else
00400 putlog(LOG_CMDS, "*", "Rejected global flags for %s from %s",
00401 hand, dcc[idx].nick);
00402 noshare = 0;
00403 }
00404 }
00405 }
00406 }
00407
00408 static void share_pls_chrec(int idx, char *par)
00409 {
00410 char *user;
00411 struct chanset_t *chan;
00412 struct userrec *u;
00413
00414 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00415 user = newsplit(&par);
00416 if ((u = get_user_by_handle(userlist, user))) {
00417 chan = findchan_by_dname(par);
00418 fr.match = (FR_CHAN | FR_BOT);
00419 get_user_flagrec(dcc[idx].user, &fr, par);
00420 if (!chan || !channel_shared(chan) || !(bot_chan(fr) || bot_global(fr)))
00421 putlog(LOG_CMDS, "*",
00422 "Rejected info for unshared channel %s from %s",
00423 par, dcc[idx].nick);
00424 else {
00425 noshare = 1;
00426 shareout_but(chan, idx, "+cr %s %s\n", user, par);
00427 if (!get_chanrec(u, par)) {
00428 add_chanrec(u, par);
00429 putlog(LOG_CMDS, "*", "%s: +chrec %s %s", dcc[idx].nick, user, par);
00430 }
00431 noshare = 0;
00432 }
00433 }
00434 }
00435 }
00436
00437 static void share_mns_chrec(int idx, char *par)
00438 {
00439 char *user;
00440 struct chanset_t *chan;
00441 struct userrec *u;
00442
00443 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00444 user = newsplit(&par);
00445 if ((u = get_user_by_handle(userlist, user))) {
00446 chan = findchan_by_dname(par);
00447 fr.match = (FR_CHAN | FR_BOT);
00448 get_user_flagrec(dcc[idx].user, &fr, par);
00449 if (!chan || !channel_shared(chan) || !(bot_chan(fr) || bot_global(fr)))
00450 putlog(LOG_CMDS, "*",
00451 "Rejected info for unshared channel %s from %s",
00452 par, dcc[idx].nick);
00453 else {
00454 noshare = 1;
00455 del_chanrec(u, par);
00456 shareout_but(chan, idx, "-cr %s %s\n", user, par);
00457 noshare = 0;
00458 putlog(LOG_CMDS, "*", "%s: -chrec %s %s", dcc[idx].nick, user, par);
00459 }
00460 }
00461 }
00462 }
00463
00464 static void share_newuser(int idx, char *par)
00465 {
00466 char *nick, *host, *pass, s[100];
00467 struct userrec *u;
00468
00469 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00470 nick = newsplit(&par);
00471 host = newsplit(&par);
00472 pass = newsplit(&par);
00473
00474 if (!(u = get_user_by_handle(userlist, nick)) ||
00475 !(u->flags & USER_UNSHARED)) {
00476 fr.global = 0;
00477
00478 fr.match = FR_GLOBAL;
00479 break_down_flags(par, &fr, NULL);
00480
00481
00482 shareout_but(NULL, idx, "n %s %s %s %s\n", nick, host, pass,
00483 private_global ? (fr.global &USER_BOT ? "b" : "-") : par);
00484
00485 if (!u) {
00486 noshare = 1;
00487 if (strlen(nick) > HANDLEN)
00488 nick[HANDLEN] = 0;
00489
00490 if (private_global)
00491 fr.global &=USER_BOT;
00492
00493 else {
00494
00495 int pgbm = private_globals_bitmask();
00496
00497 fr.match = FR_GLOBAL;
00498 fr.global &=~pgbm;
00499 }
00500
00501 build_flags(s, &fr, 0);
00502 userlist = adduser(userlist, nick, host, pass, 0);
00503
00504
00505 u = get_user_by_handle(userlist, nick);
00506 set_user_flagrec(u, &fr, 0);
00507 fr.match = FR_CHAN;
00508 noshare = 0;
00509 putlog(LOG_CMDS, "*", "%s: newuser %s %s", dcc[idx].nick, nick, s);
00510 }
00511 }
00512 }
00513 }
00514
00515 static void share_killuser(int idx, char *par)
00516 {
00517 struct userrec *u;
00518
00519
00520 if ((dcc[idx].status & STAT_SHARE) && !private_user &&
00521 (u = get_user_by_handle(userlist, par)) &&
00522 !(u->flags & USER_UNSHARED) &&
00523 !((u->flags & USER_BOT) && (bot_flags(u) & BOT_SHARE))) {
00524 noshare = 1;
00525 if (deluser(par)) {
00526 shareout_but(NULL, idx, "k %s\n", par);
00527 putlog(LOG_CMDS, "*", "%s: killuser %s", dcc[idx].nick, par);
00528 }
00529 noshare = 0;
00530 }
00531 }
00532
00533 static void share_pls_host(int idx, char *par)
00534 {
00535 char *hand;
00536 struct userrec *u;
00537
00538 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00539 hand = newsplit(&par);
00540 if ((u = get_user_by_handle(userlist, hand)) &&
00541 !(u->flags & USER_UNSHARED)) {
00542 shareout_but(NULL, idx, "+h %s %s\n", hand, par);
00543 set_user(&USERENTRY_HOSTS, u, par);
00544 putlog(LOG_CMDS, "*", "%s: +host %s %s", dcc[idx].nick, hand, par);
00545 }
00546 }
00547 }
00548
00549 static void share_pls_bothost(int idx, char *par)
00550 {
00551 char *hand, p[32];
00552 struct userrec *u;
00553
00554 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00555 hand = newsplit(&par);
00556 if (!(u = get_user_by_handle(userlist, hand)) ||
00557 !(u->flags & USER_UNSHARED)) {
00558 if (!(dcc[idx].status & STAT_GETTING))
00559 shareout_but(NULL, idx, "+bh %s %s\n", hand, par);
00560
00561 if (u) {
00562 if (!(u->flags & USER_BOT))
00563 return;
00564 set_user(&USERENTRY_HOSTS, u, par);
00565 } else {
00566 makepass(p);
00567 userlist = adduser(userlist, hand, par, p, USER_BOT);
00568 }
00569 if (!(dcc[idx].status & STAT_GETTING))
00570 putlog(LOG_CMDS, "*", "%s: +host %s %s", dcc[idx].nick, hand, par);
00571 }
00572 }
00573 }
00574
00575 static void share_mns_host(int idx, char *par)
00576 {
00577 char *hand;
00578 struct userrec *u;
00579
00580 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00581 hand = newsplit(&par);
00582 if ((u = get_user_by_handle(userlist, hand)) &&
00583 !(u->flags & USER_UNSHARED)) {
00584 shareout_but(NULL, idx, "-h %s %s\n", hand, par);
00585 noshare = 1;
00586 delhost_by_handle(hand, par);
00587 noshare = 0;
00588 putlog(LOG_CMDS, "*", "%s: -host %s %s", dcc[idx].nick, hand, par);
00589 }
00590 }
00591 }
00592
00593 static void share_change(int idx, char *par)
00594 {
00595 char *key, *hand;
00596 struct userrec *u;
00597 struct user_entry_type *uet;
00598 struct user_entry *e;
00599
00600 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00601 key = newsplit(&par);
00602 hand = newsplit(&par);
00603 if (!(u = get_user_by_handle(userlist, hand)) ||
00604 !(u->flags & USER_UNSHARED)) {
00605 if (!(uet = find_entry_type(key)))
00606
00607 debug2("Ignore ch %s from %s (unknown type)", key, dcc[idx].nick);
00608 else {
00609 if (!(dcc[idx].status & STAT_GETTING))
00610 shareout_but(NULL, idx, "c %s %s %s\n", key, hand, par);
00611 noshare = 1;
00612 if (!u && (uet == &USERENTRY_BOTADDR)) {
00613 char pass[30];
00614
00615 makepass(pass);
00616 userlist = adduser(userlist, hand, "none", pass, USER_BOT);
00617 u = get_user_by_handle(userlist, hand);
00618 } else if (!u) {
00619 noshare = 0;
00620 return;
00621 }
00622 if (uet->got_share) {
00623 if (!(e = find_user_entry(uet, u))) {
00624 e = user_malloc(sizeof(struct user_entry));
00625
00626 e->type = uet;
00627 e->name = NULL;
00628 e->u.list = NULL;
00629 list_insert((&(u->entries)), e);
00630 }
00631 uet->got_share(u, e, par, idx);
00632 if (!e->u.list) {
00633 egg_list_delete((struct list_type **) &(u->entries),
00634 (struct list_type *) e);
00635 nfree(e);
00636 }
00637 }
00638 noshare = 0;
00639 }
00640 }
00641 }
00642 }
00643
00644 static void share_chchinfo(int idx, char *par)
00645 {
00646 char *hand, *chan;
00647 struct chanset_t *cst;
00648 struct userrec *u;
00649
00650 if ((dcc[idx].status & STAT_SHARE) && !private_user) {
00651 hand = newsplit(&par);
00652 if ((u = get_user_by_handle(userlist, hand)) &&
00653 !(u->flags & USER_UNSHARED) && share_greet) {
00654 chan = newsplit(&par);
00655 cst = findchan_by_dname(chan);
00656 fr.match = (FR_CHAN | FR_BOT);
00657 get_user_flagrec(dcc[idx].user, &fr, chan);
00658 if (!cst || !channel_shared(cst) || !(bot_chan(fr) || bot_global(fr)))
00659 putlog(LOG_CMDS, "*",
00660 "Info line change from %s denied. Channel %s not shared.",
00661 dcc[idx].nick, chan);
00662 else {
00663 shareout_but(cst, idx, "chchinfo %s %s %s\n", hand, chan, par);
00664 noshare = 1;
00665 set_handle_chaninfo(userlist, hand, chan, par);
00666 noshare = 0;
00667 putlog(LOG_CMDS, "*", "%s: change info %s %s", dcc[idx].nick,
00668 chan, hand);
00669 }
00670 }
00671 }
00672 }
00673
00674 static void share_mns_ban(int idx, char *par)
00675 {
00676 struct chanset_t *chan = NULL;
00677
00678 if (dcc[idx].status & STAT_SHARE) {
00679 shareout_but(NULL, idx, "-b %s\n", par);
00680 putlog(LOG_CMDS, "*", "%s: cancel ban %s", dcc[idx].nick, par);
00681 str_unescape(par, '\\');
00682 noshare = 1;
00683 if (u_delban(NULL, par, 1) > 0) {
00684 for (chan = chanset; chan; chan = chan->next)
00685 add_delay(chan, '-', 'b', par);
00686 }
00687 noshare = 0;
00688 }
00689 }
00690
00691 static void share_mns_exempt(int idx, char *par)
00692 {
00693 struct chanset_t *chan = NULL;
00694
00695 if (dcc[idx].status & STAT_SHARE) {
00696 shareout_but(NULL, idx, "-e %s\n", par);
00697 putlog(LOG_CMDS, "*", "%s: cancel exempt %s", dcc[idx].nick, par);
00698 str_unescape(par, '\\');
00699 noshare = 1;
00700 if (u_delexempt(NULL, par, 1) > 0) {
00701 for (chan = chanset; chan; chan = chan->next)
00702 add_delay(chan, '-', 'e', par);
00703 }
00704 noshare = 0;
00705 }
00706 }
00707
00708 static void share_mns_invite(int idx, char *par)
00709 {
00710 struct chanset_t *chan = NULL;
00711
00712 if (dcc[idx].status & STAT_SHARE) {
00713 shareout_but(NULL, idx, "-inv %s\n", par);
00714 putlog(LOG_CMDS, "*", "%s: cancel invite %s", dcc[idx].nick, par);
00715 str_unescape(par, '\\');
00716 noshare = 1;
00717 if (u_delinvite(NULL, par, 1) > 0) {
00718 for (chan = chanset; chan; chan = chan->next)
00719 add_delay(chan, '-', 'I', par);
00720 }
00721 noshare = 0;
00722 }
00723 }
00724
00725 static void share_mns_banchan(int idx, char *par)
00726 {
00727 char *chname;
00728 struct chanset_t *chan;
00729
00730 if (dcc[idx].status & STAT_SHARE) {
00731 chname = newsplit(&par);
00732 chan = findchan_by_dname(chname);
00733 fr.match = (FR_CHAN | FR_BOT);
00734 get_user_flagrec(dcc[idx].user, &fr, chname);
00735 if (!chan || !channel_shared(chan) || !(bot_chan(fr) || bot_global(fr)))
00736 putlog(LOG_CMDS, "*",
00737 "Cancel channel ban %s on %s rejected - channel not shared.",
00738 par, chname);
00739 else {
00740 shareout_but(chan, idx, "-bc %s %s\n", chname, par);
00741 putlog(LOG_CMDS, "*", "%s: cancel ban %s on %s", dcc[idx].nick,
00742 par, chname);
00743 str_unescape(par, '\\');
00744 noshare = 1;
00745 if (u_delban(chan, par, 1) > 0)
00746 add_delay(chan, '-', 'b', par);
00747 noshare = 0;
00748 }
00749 }
00750 }
00751
00752 static void share_mns_exemptchan(int idx, char *par)
00753 {
00754 char *chname;
00755 struct chanset_t *chan;
00756
00757 if (dcc[idx].status & STAT_SHARE) {
00758 chname = newsplit(&par);
00759 chan = findchan_by_dname(chname);
00760 fr.match = (FR_CHAN | FR_BOT);
00761 get_user_flagrec(dcc[idx].user, &fr, chname);
00762 if (!chan || !channel_shared(chan) || !(bot_chan(fr) || bot_global(fr)))
00763 putlog(LOG_CMDS, "*",
00764 "Cancel channel exempt %s on %s rejected - channel not shared.",
00765 par, chname);
00766 else {
00767 shareout_but(chan, idx, "-ec %s %s\n", chname, par);
00768 putlog(LOG_CMDS, "*", "%s: cancel exempt %s on %s", dcc[idx].nick,
00769 par, chname);
00770 str_unescape(par, '\\');
00771 noshare = 1;
00772 if (u_delexempt(chan, par, 1) > 0)
00773 add_delay(chan, '-', 'e', par);
00774 noshare = 0;
00775 }
00776 }
00777 }
00778
00779 static void share_mns_invitechan(int idx, char *par)
00780 {
00781 char *chname;
00782 struct chanset_t *chan;
00783
00784 if (dcc[idx].status & STAT_SHARE) {
00785 chname = newsplit(&par);
00786 chan = findchan_by_dname(chname);
00787 fr.match = (FR_CHAN | FR_BOT);
00788 get_user_flagrec(dcc[idx].user, &fr, chname);
00789 if (!chan || !channel_shared(chan) || !(bot_chan(fr) || bot_global(fr)))
00790 putlog(LOG_CMDS, "*",
00791 "Cancel channel invite %s on %s rejected - channel not shared.",
00792 par, chname);
00793 else {
00794 shareout_but(chan, idx, "-invc %s %s\n", chname, par);
00795 putlog(LOG_CMDS, "*", "%s: cancel invite %s on %s", dcc[idx].nick,
00796 par, chname);
00797 str_unescape(par, '\\');
00798 noshare = 1;
00799 if (u_delinvite(chan, par, 1) > 0)
00800 add_delay(chan, '-', 'I', par);
00801 noshare = 0;
00802 }
00803 }
00804 }
00805
00806 static void share_mns_ignore(int idx, char *par)
00807 {
00808 if (dcc[idx].status & STAT_SHARE) {
00809 shareout_but(NULL, idx, "-i %s\n", par);
00810 putlog(LOG_CMDS, "*", "%s: cancel ignore %s", dcc[idx].nick, par);
00811 str_unescape(par, '\\');
00812 noshare = 1;
00813 delignore(par);
00814 noshare = 0;
00815 }
00816 }
00817
00818 static void share_pls_ban(int idx, char *par)
00819 {
00820 time_t expire_time;
00821 char *ban, *tm, *from;
00822 int flags = 0;
00823
00824 if (dcc[idx].status & STAT_SHARE) {
00825 shareout_but(NULL, idx, "+b %s\n", par);
00826 noshare = 1;
00827 ban = newsplit(&par);
00828 str_unescape(ban, '\\');
00829 tm = newsplit(&par);
00830 from = newsplit(&par);
00831 if (strchr(from, 's'))
00832 flags |= MASKREC_STICKY;
00833 if (strchr(from, 'p'))
00834 flags |= MASKREC_PERM;
00835 from = newsplit(&par);
00836 expire_time = (time_t) atoi(tm);
00837 if (expire_time != 0L)
00838 expire_time += now;
00839 u_addban(NULL, ban, from, par, expire_time, flags);
00840 putlog(LOG_CMDS, "*", "%s: global ban %s (%s:%s)", dcc[idx].nick, ban,
00841 from, par);
00842 noshare = 0;
00843 }
00844 }
00845
00846 static void share_pls_banchan(int idx, char *par)
00847 {
00848 time_t expire_time;
00849 int flags = 0;
00850 struct chanset_t *chan;
00851 char *ban, *tm, *chname, *from;
00852
00853 if (dcc[idx].status & STAT_SHARE) {
00854 ban = newsplit(&par);
00855 tm = newsplit(&par);
00856 chname = newsplit(&par);
00857 chan = findchan_by_dname(chname);
00858 fr.match = (FR_CHAN | FR_BOT);
00859 get_user_flagrec(dcc[idx].user, &fr, chname);
00860 if (!chan || !channel_shared(chan) || !(bot_chan(fr) || bot_global(fr)))
00861 putlog(LOG_CMDS, "*",
00862 "Channel ban %s on %s rejected - channel not shared.",
00863 ban, chname);
00864 else {
00865 shareout_but(chan, idx, "+bc %s %s %s %s\n", ban, tm, chname, par);
00866 str_unescape(ban, '\\');
00867 from = newsplit(&par);
00868 if (strchr(from, 's'))
00869 flags |= MASKREC_STICKY;
00870 if (strchr(from, 'p'))
00871 flags |= MASKREC_PERM;
00872 from = newsplit(&par);
00873 putlog(LOG_CMDS, "*", "%s: ban %s on %s (%s:%s)", dcc[idx].nick,
00874 ban, chname, from, par);
00875 noshare = 1;
00876 expire_time = (time_t) atoi(tm);
00877 if (expire_time != 0L)
00878 expire_time += now;
00879 u_addban(chan, ban, from, par, expire_time, flags);
00880 noshare = 0;
00881 }
00882 }
00883 }
00884
00885
00886
00887 static void share_pls_exempt(int idx, char *par)
00888 {
00889 time_t expire_time;
00890 char *exempt, *tm, *from;
00891 int flags = 0;
00892
00893 if (dcc[idx].status & STAT_SHARE) {
00894 shareout_but(NULL, idx, "+e %s\n", par);
00895 noshare = 1;
00896 exempt = newsplit(&par);
00897 str_unescape(exempt, '\\');
00898 tm = newsplit(&par);
00899 from = newsplit(&par);
00900 if (strchr(from, 's'))
00901 flags |= MASKREC_STICKY;
00902 if (strchr(from, 'p'))
00903 flags |= MASKREC_PERM;
00904 from = newsplit(&par);
00905 expire_time = (time_t) atoi(tm);
00906 if (expire_time != 0L)
00907 expire_time += now;
00908 u_addexempt(NULL, exempt, from, par, expire_time, flags);
00909 putlog(LOG_CMDS, "*", "%s: global exempt %s (%s:%s)", dcc[idx].nick, exempt,
00910 from, par);
00911 noshare = 0;
00912 }
00913 }
00914
00915
00916
00917 static void share_pls_exemptchan(int idx, char *par)
00918 {
00919 time_t expire_time;
00920 int flags = 0;
00921 struct chanset_t *chan;
00922 char *exempt, *tm, *chname, *from;
00923
00924 if (dcc[idx].status & STAT_SHARE) {
00925 exempt = newsplit(&par);
00926 tm = newsplit(&par);
00927 chname = newsplit(&par);
00928 chan = findchan_by_dname(chname);
00929 fr.match = (FR_CHAN | FR_BOT);
00930 get_user_flagrec(dcc[idx].user, &fr, chname);
00931 if (!chan || !channel_shared(chan) || !(bot_chan(fr) || bot_global(fr)))
00932 putlog(LOG_CMDS, "*",
00933 "Channel exempt %s on %s rejected - channel not shared.",
00934 exempt, chname);
00935 else {
00936 shareout_but(chan, idx, "+ec %s %s %s %s\n", exempt, tm, chname, par);
00937 str_unescape(exempt, '\\');
00938 from = newsplit(&par);
00939 if (strchr(from, 's'))
00940 flags |= MASKREC_STICKY;
00941 if (strchr(from, 'p'))
00942 flags |= MASKREC_PERM;
00943 from = newsplit(&par);
00944 putlog(LOG_CMDS, "*", "%s: exempt %s on %s (%s:%s)", dcc[idx].nick,
00945 exempt, chname, from, par);
00946 noshare = 1;
00947 expire_time = (time_t) atoi(tm);
00948 if (expire_time != 0L)
00949 expire_time += now;
00950 u_addexempt(chan, exempt, from, par, expire_time, flags);
00951 noshare = 0;
00952 }
00953 }
00954 }
00955
00956
00957
00958 static void share_pls_invite(int idx, char *par)
00959 {
00960 time_t expire_time;
00961 char *invite, *tm, *from;
00962 int flags = 0;
00963
00964 if (dcc[idx].status & STAT_SHARE) {
00965 shareout_but(NULL, idx, "+inv %s\n", par);
00966 noshare = 1;
00967 invite = newsplit(&par);
00968 str_unescape(invite, '\\');
00969 tm = newsplit(&par);
00970 from = newsplit(&par);
00971 if (strchr(from, 's'))
00972 flags |= MASKREC_STICKY;
00973 if (strchr(from, 'p'))
00974 flags |= MASKREC_PERM;
00975 from = newsplit(&par);
00976 expire_time = (time_t) atoi(tm);
00977 if (expire_time != 0L)
00978 expire_time += now;
00979 u_addinvite(NULL, invite, from, par, expire_time, flags);
00980 putlog(LOG_CMDS, "*", "%s: global invite %s (%s:%s)", dcc[idx].nick,
00981 invite, from, par);
00982 noshare = 0;
00983 }
00984 }
00985
00986
00987
00988 static void share_pls_invitechan(int idx, char *par)
00989 {
00990 time_t expire_time;
00991 int flags = 0;
00992 struct chanset_t *chan;
00993 char *invite, *tm, *chname, *from;
00994
00995 if (dcc[idx].status & STAT_SHARE) {
00996 invite = newsplit(&par);
00997 tm = newsplit(&par);
00998 chname = newsplit(&par);
00999 chan = findchan_by_dname(chname);
01000 fr.match = (FR_CHAN | FR_BOT);
01001 get_user_flagrec(dcc[idx].user, &fr, chname);
01002 if (!chan || !channel_shared(chan) || !(bot_chan(fr) || bot_global(fr)))
01003 putlog(LOG_CMDS, "*",
01004 "Channel invite %s on %s rejected - channel not shared.",
01005 invite, chname);
01006 else {
01007 shareout_but(chan, idx, "+invc %s %s %s %s\n", invite, tm, chname, par);
01008 str_unescape(invite, '\\');
01009 from = newsplit(&par);
01010 if (strchr(from, 's'))
01011 flags |= MASKREC_STICKY;
01012 if (strchr(from, 'p'))
01013 flags |= MASKREC_PERM;
01014 from = newsplit(&par);
01015 putlog(LOG_CMDS, "*", "%s: invite %s on %s (%s:%s)", dcc[idx].nick,
01016 invite, chname, from, par);
01017 noshare = 1;
01018 expire_time = (time_t) atoi(tm);
01019 if (expire_time != 0L)
01020 expire_time += now;
01021 u_addinvite(chan, invite, from, par, expire_time, flags);
01022 noshare = 0;
01023 }
01024 }
01025 }
01026
01027
01028
01029 static void share_pls_ignore(int idx, char *par)
01030 {
01031 time_t expire_time;
01032 char *ign, *from, *ts;
01033
01034 if (dcc[idx].status & STAT_SHARE) {
01035 shareout_but(NULL, idx, "+i %s\n", par);
01036 noshare = 1;
01037 ign = newsplit(&par);
01038 str_unescape(ign, '\\');
01039 ts = newsplit(&par);
01040 if (!atoi(ts))
01041 expire_time = 0L;
01042 else
01043 expire_time = now + atoi(ts);
01044 from = newsplit(&par);
01045 if (strchr(from, 'p'))
01046 expire_time = 0;
01047 from = newsplit(&par);
01048 if (strlen(from) > HANDLEN + 1)
01049 from[HANDLEN + 1] = 0;
01050 par[65] = 0;
01051 putlog(LOG_CMDS, "*", "%s: ignore %s (%s: %s)",
01052 dcc[idx].nick, ign, from, par);
01053 addignore(ign, from, par, expire_time);
01054 noshare = 0;
01055 }
01056 }
01057
01058 static void share_ufno(int idx, char *par)
01059 {
01060 putlog(LOG_BOTS, "*", "User file rejected by %s: %s", dcc[idx].nick, par);
01061 dcc[idx].status &= ~STAT_OFFERED;
01062 if (!(dcc[idx].status & STAT_GETTING))
01063 dcc[idx].status &= ~(STAT_SHARE | STAT_AGGRESSIVE);
01064 }
01065
01066 static void share_ufyes(int idx, char *par)
01067 {
01068 if (dcc[idx].status & STAT_OFFERED) {
01069 dcc[idx].status &= ~STAT_OFFERED;
01070 dcc[idx].status |= STAT_SHARE;
01071 dcc[idx].status |= STAT_SENDING;
01072 uf_features_parse(idx, par);
01073 start_sending_users(idx);
01074 putlog(LOG_BOTS, "*", "Sending user file send request to %s",
01075 dcc[idx].nick);
01076 }
01077 }
01078
01079 static void share_userfileq(int idx, char *par)
01080 {
01081 int ok = 1, i, bfl = bot_flags(dcc[idx].user);
01082
01083 flush_tbuf(dcc[idx].nick);
01084 if (bfl & BOT_AGGRESSIVE)
01085 dprintf(idx, "s un I have you marked for Aggressive sharing.\n");
01086 else if (!(bfl & BOT_PASSIVE))
01087 dprintf(idx, "s un You are not marked for sharing with me.\n");
01088 else if (min_share > dcc[idx].u.bot->numver)
01089 dprintf(idx,
01090 "s un Your version is not high enough, need v%d.%d.%d\n",
01091 (min_share / 1000000), (min_share / 10000) % 100,
01092 (min_share / 100) % 100);
01093 else {
01094 for (i = 0; i < dcc_total; i++)
01095 if (dcc[i].type->flags & DCT_BOT) {
01096 if ((dcc[i].status & STAT_SHARE) &&
01097 (dcc[i].status & STAT_AGGRESSIVE) && (i != idx)) {
01098 ok = 0;
01099 break;
01100 }
01101 }
01102 if (!ok)
01103 dprintf(idx, "s un Already sharing.\n");
01104 else {
01105 if (dcc[idx].u.bot->numver >= min_uffeature)
01106 dprintf(idx, "s uy %s\n", uf_features_dump(idx));
01107 else
01108 dprintf(idx, "s uy\n");
01109
01110 dcc[idx].status |= STAT_SHARE | STAT_GETTING | STAT_AGGRESSIVE;
01111 putlog(LOG_BOTS, "*", "Downloading user file from %s", dcc[idx].nick);
01112 }
01113 }
01114 }
01115
01116
01117
01118 static void share_ufsend(int idx, char *par)
01119 {
01120 char *ip = NULL, *port;
01121 char s[1024];
01122 int i, sock;
01123 FILE *f;
01124
01125 egg_snprintf(s, sizeof s, ".share.%s.%li.users", botnetnick, now);
01126 if (!(b_status(idx) & STAT_SHARE)) {
01127 dprintf(idx, "s e You didn't ask; you just started sending.\n");
01128 dprintf(idx, "s e Ask before sending the userfile.\n");
01129 zapfbot(idx);
01130 } else if (dcc_total == max_dcc) {
01131 putlog(LOG_MISC, "*", "NO MORE DCC CONNECTIONS -- can't grab userfile");
01132 dprintf(idx, "s e I can't open a DCC to you; I'm full.\n");
01133 zapfbot(idx);
01134 } else if (!(f = fopen(s, "wb"))) {
01135 putlog(LOG_MISC, "*", "CAN'T WRITE USERFILE DOWNLOAD FILE!");
01136 zapfbot(idx);
01137 } else {
01138 ip = newsplit(&par);
01139 port = newsplit(&par);
01140 sock = getsock(SOCK_BINARY);
01141 if (sock < 0 || open_telnet_dcc(sock, ip, port) < 0) {
01142 killsock(sock);
01143 putlog(LOG_BOTS, "*", "Asynchronous connection failed!");
01144 dprintf(idx, "s e Can't connect to you!\n");
01145 zapfbot(idx);
01146 } else {
01147 i = new_dcc(&DCC_FORK_SEND, sizeof(struct xfer_info));
01148 dcc[i].addr = my_atoul(ip);
01149 dcc[i].port = atoi(port);
01150 strcpy(dcc[i].nick, "*users");
01151 dcc[i].u.xfer->filename = nmalloc(strlen(s) + 1);
01152 strcpy(dcc[i].u.xfer->filename, s);
01153 dcc[i].u.xfer->origname = dcc[i].u.xfer->filename;
01154 dcc[i].u.xfer->length = atoi(par);
01155 dcc[i].u.xfer->f = f;
01156 dcc[i].sock = sock;
01157 strcpy(dcc[i].host, dcc[idx].nick);
01158
01159 dcc[idx].status |= STAT_GETTING;
01160 }
01161 }
01162 }
01163
01164 static void share_resyncq(int idx, char *par)
01165 {
01166 if (!allow_resync)
01167 dprintf(idx, "s rn Not permitting resync.\n");
01168 else {
01169 int bfl = bot_flags(dcc[idx].user);
01170
01171 if (!(bfl & BOT_SHARE))
01172 dprintf(idx, "s rn You are not marked for sharing with me.\n");
01173 else if (can_resync(dcc[idx].nick)) {
01174 dprintf(idx, "s r!\n");
01175 dump_resync(idx);
01176 dcc[idx].status &= ~STAT_OFFERED;
01177 dcc[idx].status |= STAT_SHARE;
01178 putlog(LOG_BOTS, "*", "Resync'd user file with %s", dcc[idx].nick);
01179 updatebot(-1, dcc[idx].nick, '+', 0);
01180 } else
01181 dprintf(idx, "s rn No resync buffer.\n");
01182 }
01183 }
01184
01185 static void share_resync(int idx, char *par)
01186 {
01187 if ((dcc[idx].status & STAT_OFFERED) && can_resync(dcc[idx].nick)) {
01188 dump_resync(idx);
01189 dcc[idx].status &= ~STAT_OFFERED;
01190 dcc[idx].status |= STAT_SHARE;
01191 updatebot(-1, dcc[idx].nick, '+', 0);
01192 putlog(LOG_BOTS, "*", "Resync'd user file with %s", dcc[idx].nick);
01193 }
01194 }
01195
01196 static void share_resync_no(int idx, char *par)
01197 {
01198 putlog(LOG_BOTS, "*", "Resync refused by %s: %s", dcc[idx].nick, par);
01199 flush_tbuf(dcc[idx].nick);
01200 dprintf(idx, "s u?\n");
01201 }
01202
01203 static void share_version(int idx, char *par)
01204 {
01205
01206 dcc[idx].status &= ~(STAT_SHARE | STAT_GETTING | STAT_SENDING |
01207 STAT_OFFERED | STAT_AGGRESSIVE);
01208 dcc[idx].u.bot->uff_flags = 0;
01209 if ((dcc[idx].u.bot->numver >= min_share) &&
01210 (bot_flags(dcc[idx].user) & BOT_AGGRESSIVE)) {
01211 if (can_resync(dcc[idx].nick))
01212 dprintf(idx, "s r?\n");
01213 else
01214 dprintf(idx, "s u?\n");
01215 dcc[idx].status |= STAT_OFFERED;
01216 }
01217 }
01218
01219 static void hook_read_userfile()
01220 {
01221 int i;
01222
01223 if (!noshare) {
01224 for (i = 0; i < dcc_total; i++)
01225 if ((dcc[i].type->flags & DCT_BOT) && (dcc[i].status & STAT_SHARE) &&
01226 !(dcc[i].status & STAT_AGGRESSIVE)) {
01227
01228 if (dcc[i].status & STAT_SENDING)
01229 cancel_user_xfer(-i, 0);
01230 dprintf(i, "s u?\n");
01231 dcc[i].status |= STAT_OFFERED;
01232 }
01233 }
01234 }
01235
01236 static void share_endstartup(int idx, char *par)
01237 {
01238 dcc[idx].status &= ~STAT_GETTING;
01239
01240 hook_read_userfile();
01241 }
01242
01243 static void share_end(int idx, char *par)
01244 {
01245 putlog(LOG_BOTS, "*", "Ending sharing with %s (%s).", dcc[idx].nick, par);
01246 cancel_user_xfer(-idx, 0);
01247 dcc[idx].status &= ~(STAT_SHARE | STAT_GETTING | STAT_SENDING |
01248 STAT_OFFERED | STAT_AGGRESSIVE);
01249 dcc[idx].u.bot->uff_flags = 0;
01250 }
01251
01252 static void share_feats(int idx, char *par)
01253 {
01254 (int) uf_features_check(idx, par);
01255 }
01256
01257
01258
01259 static botcmd_t C_share[] = {
01260 {"!", (IntFunc) share_endstartup},
01261 {"+b", (IntFunc) share_pls_ban},
01262 {"+bc", (IntFunc) share_pls_banchan},
01263 {"+bh", (IntFunc) share_pls_bothost},
01264 {"+cr", (IntFunc) share_pls_chrec},
01265 {"+e", (IntFunc) share_pls_exempt},
01266 {"+ec", (IntFunc) share_pls_exemptchan},
01267 {"+h", (IntFunc) share_pls_host},
01268 {"+i", (IntFunc) share_pls_ignore},
01269 {"+inv", (IntFunc) share_pls_invite},
01270 {"+invc", (IntFunc) share_pls_invitechan},
01271 {"-b", (IntFunc) share_mns_ban},
01272 {"-bc", (IntFunc) share_mns_banchan},
01273 {"-cr", (IntFunc) share_mns_chrec},
01274 {"-e", (IntFunc) share_mns_exempt},
01275 {"-ec", (IntFunc) share_mns_exemptchan},
01276 {"-h", (IntFunc) share_mns_host},
01277 {"-i", (IntFunc) share_mns_ignore},
01278 {"-inv", (IntFunc) share_mns_invite},
01279 {"-invc", (IntFunc) share_mns_invitechan},
01280 {"a", (IntFunc) share_chattr},
01281 {"c", (IntFunc) share_change},
01282 {"chchinfo", (IntFunc) share_chchinfo},
01283 {"e", (IntFunc) share_end},
01284 {"feats", (IntFunc) share_feats},
01285 {"h", (IntFunc) share_chhand},
01286 {"k", (IntFunc) share_killuser},
01287 {"n", (IntFunc) share_newuser},
01288 {"r!", (IntFunc) share_resync},
01289 {"r?", (IntFunc) share_resyncq},
01290 {"rn", (IntFunc) share_resync_no},
01291 {"s", (IntFunc) share_stick_ban},
01292 {"se", (IntFunc) share_stick_exempt},
01293 {"sInv", (IntFunc) share_stick_invite},
01294 {"u?", (IntFunc) share_userfileq},
01295 {"un", (IntFunc) share_ufno},
01296 {"us", (IntFunc) share_ufsend},
01297 {"uy", (IntFunc) share_ufyes},
01298 {"v", (IntFunc) share_version},
01299 {NULL, NULL}
01300 };
01301
01302
01303 static void sharein_mod(int idx, char *msg)
01304 {
01305 char *code;
01306 int f, i;
01307
01308 code = newsplit(&msg);
01309 for (f = 0, i = 0; C_share[i].name && !f; i++) {
01310 int y = egg_strcasecmp(code, C_share[i].name);
01311
01312 if (!y)
01313
01314 (C_share[i].func) (idx, msg);
01315 if (y < 0)
01316 f = 1;
01317 }
01318 }
01319
01320 static void shareout_mod EGG_VARARGS_DEF(struct chanset_t *, arg1)
01321 {
01322 int i, l;
01323 char *format;
01324 char s[601];
01325 struct chanset_t *chan;
01326 va_list va;
01327
01328 chan = EGG_VARARGS_START(struct chanset_t *, arg1, va);
01329
01330 if (!chan || channel_shared(chan)) {
01331 format = va_arg(va, char *);
01332
01333 strcpy(s, "s ");
01334 if ((l = egg_vsnprintf(s + 2, 509, format, va)) < 0)
01335 s[2 + (l = 509)] = 0;
01336 for (i = 0; i < dcc_total; i++)
01337 if ((dcc[i].type->flags & DCT_BOT) &&
01338 (dcc[i].status & STAT_SHARE) &&
01339 !(dcc[i].status & (STAT_GETTING | STAT_SENDING))) {
01340 if (chan) {
01341 fr.match = (FR_CHAN | FR_BOT);
01342 get_user_flagrec(dcc[i].user, &fr, chan->dname);
01343 }
01344 if (!chan || bot_chan(fr) || bot_global(fr))
01345 tputs(dcc[i].sock, s, l + 2);
01346 }
01347 q_resync(s, chan);
01348 }
01349 va_end(va);
01350 }
01351
01352 static void shareout_but EGG_VARARGS_DEF(struct chanset_t *, arg1)
01353 {
01354 int i, x, l;
01355 char *format;
01356 char s[601];
01357 struct chanset_t *chan;
01358 va_list va;
01359
01360 chan = EGG_VARARGS_START(struct chanset_t *, arg1, va);
01361 x = va_arg(va, int);
01362 format = va_arg(va, char *);
01363
01364 strcpy(s, "s ");
01365 if ((l = egg_vsnprintf(s + 2, 509, format, va)) < 0)
01366 s[2 + (l = 509)] = 0;
01367 for (i = 0; i < dcc_total; i++)
01368 if ((dcc[i].type->flags & DCT_BOT) && (i != x) &&
01369 (dcc[i].status & STAT_SHARE) &&
01370 (!(dcc[i].status & STAT_GETTING)) &&
01371 (!(dcc[i].status & STAT_SENDING))) {
01372 if (chan) {
01373 fr.match = (FR_CHAN | FR_BOT);
01374 get_user_flagrec(dcc[i].user, &fr, chan->dname);
01375 }
01376 if (!chan || bot_chan(fr) || bot_global(fr))
01377 tputs(dcc[i].sock, s, l + 2);
01378 }
01379 q_resync(s, chan);
01380 va_end(va);
01381 }
01382
01383
01384
01385
01386
01387
01388
01389
01390 static void new_tbuf(char *bot)
01391 {
01392 tandbuf **old = &tbuf, *new;
01393
01394 new = nmalloc(sizeof(tandbuf));
01395 strcpy(new->bot, bot);
01396 new->q = NULL;
01397 new->timer = now;
01398 new->next = *old;
01399 *old = new;
01400 putlog(LOG_BOTS, "*", "Creating resync buffer for %s", bot);
01401 }
01402
01403 static void del_tbuf(tandbuf *goner)
01404 {
01405 struct share_msgq *q, *r;
01406 tandbuf *t = NULL, *old = NULL;
01407
01408 for (t = tbuf; t; old = t, t = t->next) {
01409 if (t == goner) {
01410 if (old)
01411 old->next = t->next;
01412 else
01413 tbuf = t->next;
01414 for (q = t->q; q && q->msg[0]; q = r) {
01415 r = q->next;
01416 nfree(q->msg);
01417 nfree(q);
01418 }
01419 nfree(t);
01420 break;
01421 }
01422 }
01423 }
01424
01425
01426
01427 static int flush_tbuf(char *bot)
01428 {
01429 tandbuf *t, *tnext = NULL;
01430
01431 for (t = tbuf; t; t = tnext) {
01432 tnext = t->next;
01433 if (!egg_strcasecmp(t->bot, bot)) {
01434 del_tbuf(t);
01435 return 1;
01436 }
01437 }
01438 return 0;
01439 }
01440
01441
01442
01443 static void check_expired_tbufs()
01444 {
01445 int i;
01446 tandbuf *t, *tnext = NULL;
01447
01448 for (t = tbuf; t; t = tnext) {
01449 tnext = t->next;
01450 if ((now - t->timer) > resync_time) {
01451 putlog(LOG_BOTS, "*", "Flushing resync buffer for clonebot %s.", t->bot);
01452 del_tbuf(t);
01453 }
01454 }
01455
01456 for (i = 0; i < dcc_total; i++)
01457 if (dcc[i].type->flags & DCT_BOT) {
01458 if (dcc[i].status & STAT_OFFERED) {
01459 if ((now - dcc[i].timeval > 120) && (dcc[i].user &&
01460 (bot_flags(dcc[i].user) & BOT_AGGRESSIVE)))
01461 dprintf(i, "s u?\n");
01462
01463
01464 } else if (!(dcc[i].status & STAT_SHARE)) {
01465
01466 if (dcc[i].user && (bot_flags(dcc[i].user) & BOT_AGGRESSIVE)) {
01467 dprintf(i, "s u?\n");
01468 dcc[i].status |= STAT_OFFERED;
01469 }
01470 }
01471 }
01472 }
01473
01474 static struct share_msgq *q_addmsg(struct share_msgq *qq,
01475 struct chanset_t *chan, char *s)
01476 {
01477 struct share_msgq *q;
01478 int cnt;
01479
01480 if (!qq) {
01481 q = nmalloc(sizeof *q);
01482
01483 q->chan = chan;
01484 q->next = NULL;
01485 q->msg = nmalloc(strlen(s) + 1);
01486 strcpy(q->msg, s);
01487 return q;
01488 }
01489 cnt = 0;
01490 for (q = qq; q->next; q = q->next)
01491 cnt++;
01492 if (cnt > 1000)
01493 return NULL;
01494 q->next = nmalloc(sizeof *q->next);
01495
01496 q = q->next;
01497 q->chan = chan;
01498 q->next = NULL;
01499 q->msg = nmalloc(strlen(s) + 1);
01500 strcpy(q->msg, s);
01501 return qq;
01502 }
01503
01504
01505
01506 static void q_tbuf(char *bot, char *s, struct chanset_t *chan)
01507 {
01508 struct share_msgq *q;
01509 tandbuf *t;
01510
01511 for (t = tbuf; t && t->bot[0]; t = t->next)
01512 if (!egg_strcasecmp(t->bot, bot)) {
01513 if (chan) {
01514 fr.match = (FR_CHAN | FR_BOT);
01515 get_user_flagrec(get_user_by_handle(userlist, bot), &fr, chan->dname);
01516 }
01517 if ((!chan || bot_chan(fr) || bot_global(fr)) &&
01518 (q = q_addmsg(t->q, chan, s)))
01519 t->q = q;
01520 break;
01521 }
01522 }
01523
01524
01525
01526 static void q_resync(char *s, struct chanset_t *chan)
01527 {
01528 struct share_msgq *q;
01529 tandbuf *t;
01530
01531 for (t = tbuf; t && t->bot[0]; t = t->next) {
01532 if (chan) {
01533 fr.match = (FR_CHAN | FR_BOT);
01534 get_user_flagrec(get_user_by_handle(userlist, t->bot), &fr, chan->dname);
01535 }
01536 if ((!chan || bot_chan(fr) || bot_global(fr)) &&
01537 (q = q_addmsg(t->q, chan, s)))
01538 t->q = q;
01539 }
01540 }
01541
01542
01543
01544 static int can_resync(char *bot)
01545 {
01546 tandbuf *t;
01547
01548 for (t = tbuf; t && t->bot[0]; t = t->next)
01549 if (!egg_strcasecmp(bot, t->bot))
01550 return 1;
01551 return 0;
01552 }
01553
01554
01555
01556 static void dump_resync(int idx)
01557 {
01558 struct share_msgq *q;
01559 tandbuf *t;
01560
01561 for (t = tbuf; t && t->bot[0]; t = t->next)
01562 if (!egg_strcasecmp(dcc[idx].nick, t->bot)) {
01563 for (q = t->q; q && q->msg[0]; q = q->next) {
01564 dprintf(idx, "%s", q->msg);
01565 }
01566 flush_tbuf(dcc[idx].nick);
01567 break;
01568 }
01569 }
01570
01571
01572
01573 static void status_tbufs(int idx)
01574 {
01575 int count, off = 0;
01576 struct share_msgq *q;
01577 char s[121];
01578 tandbuf *t;
01579
01580 off = 0;
01581 for (t = tbuf; t && t->bot[0]; t = t->next)
01582 if (off < (110 - HANDLEN)) {
01583 off += my_strcpy(s + off, t->bot);
01584 count = 0;
01585 for (q = t->q; q; q = q->next)
01586 count++;
01587 off += simple_sprintf(s + off, " (%d), ", count);
01588 }
01589 if (off) {
01590 s[off - 2] = 0;
01591 dprintf(idx, " Pending sharebot buffers: %s\n", s);
01592 }
01593 }
01594
01595 static int write_tmp_userfile(char *fn, struct userrec *bu, int idx)
01596 {
01597 FILE *f;
01598 struct userrec *u;
01599 int ok = 0;
01600
01601 if ((f = fopen(fn, "wb"))) {
01602 chmod(fn, 0600);
01603 fprintf(f, "#4v: %s -- %s -- transmit\n", ver, botnetnick);
01604 ok = 1;
01605 for (u = bu; u && ok; u = u->next)
01606 if (!write_user(u, f, idx))
01607 ok = 0;
01608 if (!write_ignores(f, idx))
01609 ok = 0;
01610 if (!write_bans(f, idx))
01611 ok = 0;
01612
01613
01614
01615
01616
01617 if (dcc[idx].u.bot->numver >= min_exemptinvite) {
01618 if ((dcc[idx].u.bot->uff_flags & UFF_EXEMPT) ||
01619 (dcc[idx].u.bot->numver < min_uffeature)) {
01620 if (!write_exempts(f, idx))
01621 ok = 0;
01622 }
01623 if ((dcc[idx].u.bot->uff_flags & UFF_INVITE) ||
01624 (dcc[idx].u.bot->numver < min_uffeature)) {
01625 if (!write_invites(f, idx))
01626 ok = 0;
01627 }
01628 } else
01629 putlog(LOG_BOTS, "*", "%s is too old: not sharing exempts and invites.",
01630 dcc[idx].nick);
01631 fclose(f);
01632 }
01633 if (!ok)
01634 putlog(LOG_MISC, "*", USERF_ERRWRITE2);
01635 return ok;
01636 }
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647 static struct userrec *dup_userlist(int t)
01648 {
01649 struct userrec *u, *u1, *retu, *nu;
01650 struct chanuserrec *ch;
01651 struct user_entry *ue;
01652 char *p;
01653
01654 nu = retu = NULL;
01655 noshare = 1;
01656 for (u = userlist; u; u = u->next)
01657
01658 if (((t == 0) && !(u->flags & (USER_BOT | USER_UNSHARED))) ||
01659 ((t == 1) && (u->flags & (USER_BOT | USER_UNSHARED))) || (t == 2)) {
01660 p = get_user(&USERENTRY_PASS, u);
01661 u1 = adduser(NULL, u->handle, 0, p, u->flags);
01662 u1->flags_udef = u->flags_udef;
01663 if (!nu)
01664 nu = retu = u1;
01665 else {
01666 nu->next = u1;
01667 nu = nu->next;
01668 }
01669 for (ch = u->chanrec; ch; ch = ch->next) {
01670 struct chanuserrec *z = add_chanrec(nu, ch->channel);
01671
01672 if (z) {
01673 z->flags = ch->flags;
01674 z->flags_udef = ch->flags_udef;
01675 z->laston = ch->laston;
01676 set_handle_chaninfo(nu, nu->handle, ch->channel, ch->info);
01677 }
01678 }
01679 for (ue = u->entries; ue; ue = ue->next) {
01680 if (ue->name) {
01681 struct list_type *lt;
01682 struct user_entry *nue;
01683
01684 nue = user_malloc(sizeof(struct user_entry));
01685 nue->name = user_malloc(strlen(ue->name) + 1);
01686 nue->type = NULL;
01687 nue->u.list = NULL;
01688 strcpy(nue->name, ue->name);
01689 list_insert((&nu->entries), nue);
01690 for (lt = ue->u.list; lt; lt = lt->next) {
01691 struct list_type *list;
01692
01693 list = user_malloc(sizeof(struct list_type));
01694 list->next = NULL;
01695 list->extra = user_malloc(strlen(lt->extra) + 1);
01696 strcpy(list->extra, lt->extra);
01697 egg_list_append((&nue->u.list), list);
01698 }
01699 } else {
01700 if (ue->type->dup_user && (t || ue->type->got_share))
01701 ue->type->dup_user(nu, u, ue);
01702 }
01703 }
01704 }
01705 noshare = 0;
01706 return retu;
01707 }
01708
01709
01710
01711 static void finish_share(int idx)
01712 {
01713 struct userrec *u = NULL, *ou = NULL;
01714 struct chanset_t *chan;
01715 int i, j = -1;
01716
01717 for (i = 0; i < dcc_total; i++)
01718 if (!egg_strcasecmp(dcc[i].nick, dcc[idx].host) &&
01719 (dcc[i].type->flags & DCT_BOT))
01720 j = i;
01721 if (j == -1)
01722 return;
01723
01724 if (!uff_call_receiving(j, dcc[idx].u.xfer->filename)) {
01725 putlog(LOG_BOTS, "*", "A uff parsing function failed for the userfile!");
01726 unlink(dcc[idx].u.xfer->filename);
01727 return;
01728 }
01729
01730 if (dcc[j].u.bot->uff_flags & UFF_OVERRIDE)
01731 debug1("NOTE: Sharing passively with %s, overriding local bots.",
01732 dcc[j].nick);
01733 else
01734
01735 u = dup_userlist(1);
01736
01737
01738
01739
01740
01741
01742 noshare = 1;
01743 fr.match = (FR_CHAN | FR_BOT);
01744 while (global_bans)
01745 u_delban(NULL, global_bans->mask, 1);
01746 while (global_ign)
01747 delignore(global_ign->igmask);
01748 while (global_invites)
01749 u_delinvite(NULL, global_invites->mask, 1);
01750 while (global_exempts)
01751 u_delexempt(NULL, global_exempts->mask, 1);
01752 for (chan = chanset; chan; chan = chan->next)
01753 if (channel_shared(chan)) {
01754 get_user_flagrec(dcc[j].user, &fr, chan->dname);
01755 if (bot_chan(fr) || bot_global(fr)) {
01756 while (chan->bans)
01757 u_delban(chan, chan->bans->mask, 1);
01758 while (chan->exempts)
01759 u_delexempt(chan, chan->exempts->mask, 1);
01760 while (chan->invites)
01761 u_delinvite(chan, chan->invites->mask, 1);
01762 }
01763 }
01764 noshare = 0;
01765 ou = userlist;
01766 userlist = (void *) -1;
01767
01768
01769
01770
01771
01772 if (u == NULL)
01773 for (i = 0; i < dcc_total; i++)
01774 dcc[i].user = NULL;
01775 else
01776 for (i = 0; i < dcc_total; i++)
01777 dcc[i].user = get_user_by_handle(u, dcc[i].nick);
01778
01779
01780
01781
01782 if (!readuserfile(dcc[idx].u.xfer->filename, &u)) {
01783 putlog(LOG_MISC, "*", "%s", USERF_CANTREAD);
01784 clear_userlist(u);
01785 clear_chanlist();
01786
01787 for (i = 0; i < dcc_total; i++)
01788 dcc[i].user = get_user_by_handle(ou, dcc[i].nick);
01789 userlist = ou;
01790 lastuser = NULL;
01791 return;
01792 }
01793 putlog(LOG_BOTS, "*", "%s.", USERF_XFERDONE);
01794
01795 clear_chanlist();
01796
01797 userlist = u;
01798 lastuser = NULL;
01799
01800
01801
01802
01803
01804
01805
01806 fr.match = (FR_CHAN | FR_BOT);
01807 for (u = userlist; u; u = u->next) {
01808 struct userrec *u2 = get_user_by_handle(ou, u->handle);
01809
01810 if ((dcc[j].u.bot->uff_flags & UFF_OVERRIDE) &&
01811 u2 && (u2->flags & USER_BOT)) {
01812
01813 set_user(&USERENTRY_BOTFL, u, get_user(&USERENTRY_BOTFL, u2));
01814 set_user(&USERENTRY_PASS, u, get_user(&USERENTRY_PASS, u2));
01815 } else if ((dcc[j].u.bot->uff_flags & UFF_OVERRIDE) &&
01816 (u->flags & USER_BOT)) {
01817
01818 set_user(&USERENTRY_BOTFL, u, NULL);
01819 set_user(&USERENTRY_PASS, u, NULL);
01820 } else if (u2 && !(u2->flags & (USER_BOT | USER_UNSHARED))) {
01821 struct chanuserrec *cr, *cr_next, *cr_old = NULL;
01822 struct user_entry *ue;
01823
01824 if (private_global) {
01825 u->flags = u2->flags;
01826 u->flags_udef = u2->flags_udef;
01827 } else {
01828 int pgbm = private_globals_bitmask();
01829
01830 u->flags = (u2->flags & pgbm) | (u->flags & ~pgbm);
01831 }
01832 noshare = 1;
01833 for (cr = u2->chanrec; cr; cr = cr_next) {
01834 struct chanset_t *chan = findchan_by_dname(cr->channel);
01835
01836 cr_next = cr->next;
01837 if (chan) {
01838 int not_shared = 0;
01839
01840 if (!channel_shared(chan))
01841 not_shared = 1;
01842 else {
01843 get_user_flagrec(dcc[j].user, &fr, chan->dname);
01844 if (!bot_chan(fr) && !bot_global(fr))
01845 not_shared = 1;
01846 }
01847 if (not_shared) {
01848 del_chanrec(u, cr->channel);
01849 if (cr_old)
01850 cr_old->next = cr_next;
01851 else
01852 u2->chanrec = cr_next;
01853 cr->next = u->chanrec;
01854 u->chanrec = cr;
01855 } else {
01856
01857 for (cr_old = u->chanrec; cr_old; cr_old = cr_old->next)
01858 if (!rfc_casecmp(cr_old->channel, cr->channel)) {
01859 cr_old->laston = cr->laston;
01860 break;
01861 }
01862 cr_old = cr;
01863 }
01864 }
01865 }
01866 noshare = 0;
01867
01868 for (ue = u2->entries; ue; ue = ue->next)
01869 if (ue->type && !ue->type->got_share && ue->type->dup_user)
01870 ue->type->dup_user(u, u2, ue);
01871 } else if (!u2 && private_global) {
01872 u->flags = 0;
01873 u->flags_udef = 0;
01874 } else
01875 u->flags = (u->flags & ~private_globals_bitmask());
01876 }
01877 clear_userlist(ou);
01878 unlink(dcc[idx].u.xfer->filename);
01879 reaffirm_owners();
01880 check_tcl_event("userfile-loaded");
01881 updatebot(-1, dcc[j].nick, '+', 0);
01882 }
01883
01884
01885
01886 static void start_sending_users(int idx)
01887 {
01888 struct userrec *u;
01889 char share_file[1024], s1[64];
01890 int i = 1;
01891 struct chanuserrec *ch;
01892 struct chanset_t *cst;
01893
01894 egg_snprintf(share_file, sizeof share_file, ".share.%s.%lu", dcc[idx].nick,
01895 now);
01896 if (dcc[idx].u.bot->uff_flags & UFF_OVERRIDE) {
01897 debug1("NOTE: Sharing aggressively with %s, overriding its local bots.",
01898 dcc[idx].nick);
01899 u = dup_userlist(2);
01900 } else
01901 u = dup_userlist(0);
01902 write_tmp_userfile(share_file, u, idx);
01903 clear_userlist(u);
01904
01905 if (!uff_call_sending(idx, share_file)) {
01906 unlink(share_file);
01907 dprintf(idx, "s e %s\n", "uff parsing failed");
01908 putlog(LOG_BOTS, "*", "uff parsing failed");
01909 dcc[idx].status &= ~(STAT_SHARE | STAT_SENDING | STAT_AGGRESSIVE);
01910 return;
01911 }
01912
01913 if ((i = raw_dcc_send(share_file, "*users", "(users)", share_file)) > 0) {
01914 unlink(share_file);
01915 dprintf(idx, "s e %s\n", USERF_CANTSEND);
01916 putlog(LOG_BOTS, "*", "%s -- can't send userfile",
01917 i == DCCSEND_FULL ? "NO MORE DCC CONNECTIONS" :
01918 i == DCCSEND_NOSOCK ? "CAN'T OPEN A LISTENING SOCKET" :
01919 i == DCCSEND_BADFN ? "BAD FILE" :
01920 i == DCCSEND_FEMPTY ? "EMPTY FILE" : "UNKNOWN REASON!");
01921 dcc[idx].status &= ~(STAT_SHARE | STAT_SENDING | STAT_AGGRESSIVE);
01922 } else {
01923 updatebot(-1, dcc[idx].nick, '+', 0);
01924 dcc[idx].status |= STAT_SENDING;
01925 i = dcc_total - 1;
01926 strcpy(dcc[i].host, dcc[idx].nick);
01927 dprintf(idx, "s us %lu %d %lu\n",
01928 iptolong(natip[0] ? (IP) inet_addr(natip) : getmyip()),
01929 dcc[i].port, dcc[i].u.xfer->length);
01930
01931
01932
01933 new_tbuf(dcc[idx].nick);
01934
01935
01936
01937 if (!(dcc[idx].u.bot->uff_flags & UFF_OVERRIDE)) {
01938 for (u = userlist; u; u = u->next) {
01939 if ((u->flags & USER_BOT) && !(u->flags & USER_UNSHARED)) {
01940 struct bot_addr *bi = get_user(&USERENTRY_BOTADDR, u);
01941 struct list_type *t;
01942 char s2[1024];
01943
01944
01945 for (t = get_user(&USERENTRY_HOSTS, u); t; t = t->next) {
01946 egg_snprintf(s2, sizeof s2, "s +bh %s %s\n", u->handle, t->extra);
01947 q_tbuf(dcc[idx].nick, s2, NULL);
01948 }
01949
01950 if (bi) {
01951 egg_snprintf(s2, sizeof s2, "s c BOTADDR %s %s %d %d\n", u->handle,
01952 bi->address, bi->telnet_port, bi->relay_port);
01953 q_tbuf(dcc[idx].nick, s2, NULL);
01954 }
01955 fr.match = FR_GLOBAL;
01956 fr.global = u->flags;
01957
01958 fr.udef_global = u->flags_udef;
01959 build_flags(s1, &fr, NULL);
01960 egg_snprintf(s2, sizeof s2, "s a %s %s\n", u->handle, s1);
01961 q_tbuf(dcc[idx].nick, s2, NULL);
01962 for (ch = u->chanrec; ch; ch = ch->next) {
01963 if ((ch->flags & ~BOT_SHARE) &&
01964 ((cst = findchan_by_dname(ch->channel)) &&
01965 channel_shared(cst))) {
01966 fr.match = (FR_CHAN | FR_BOT);
01967 get_user_flagrec(dcc[idx].user, &fr, ch->channel);
01968 if (bot_chan(fr) || bot_global(fr)) {
01969 fr.match = FR_CHAN;
01970 fr.chan = ch->flags & ~BOT_SHARE;
01971 fr.udef_chan = ch->flags_udef;
01972 build_flags(s1, &fr, NULL);
01973 egg_snprintf(s2, sizeof s2, "s a %s %s %s\n", u->handle, s1,
01974 ch->channel);
01975 q_tbuf(dcc[idx].nick, s2, cst);
01976 }
01977 }
01978 }
01979 }
01980 }
01981 }
01982 q_tbuf(dcc[idx].nick, "s !\n", NULL);
01983
01984
01985
01986 unlink(share_file);
01987 }
01988 }
01989
01990 static void (*def_dcc_bot_kill) (int, void *) = 0;
01991
01992 static void cancel_user_xfer(int idx, void *x)
01993 {
01994 int i, j, k = 0;
01995
01996 if (idx < 0) {
01997 idx = -idx;
01998 k = 1;
01999 updatebot(-1, dcc[idx].nick, '-', 0);
02000 }
02001 flush_tbuf(dcc[idx].nick);
02002 if (dcc[idx].status & STAT_SHARE) {
02003 if (dcc[idx].status & STAT_GETTING) {
02004 j = 0;
02005 for (i = 0; i < dcc_total; i++)
02006 if (!egg_strcasecmp(dcc[i].host, dcc[idx].nick) &&
02007 ((dcc[i].type->flags & (DCT_FILETRAN | DCT_FILESEND)) ==
02008 (DCT_FILETRAN | DCT_FILESEND)))
02009 j = i;
02010 if (j != 0) {
02011 killsock(dcc[j].sock);
02012 unlink(dcc[j].u.xfer->filename);
02013 lostdcc(j);
02014 }
02015 putlog(LOG_BOTS, "*", "(Userlist download aborted.)");
02016 }
02017 if (dcc[idx].status & STAT_SENDING) {
02018 j = 0;
02019 for (i = 0; i < dcc_total; i++)
02020 if ((!egg_strcasecmp(dcc[i].host, dcc[idx].nick)) &&
02021 ((dcc[i].type->flags & (DCT_FILETRAN | DCT_FILESEND)) ==
02022 DCT_FILETRAN))
02023 j = i;
02024 if (j != 0) {
02025 killsock(dcc[j].sock);
02026 unlink(dcc[j].u.xfer->filename);
02027 lostdcc(j);
02028 }
02029 putlog(LOG_BOTS, "*", "(Userlist transmit aborted.)");
02030 }
02031 if (allow_resync && (!(dcc[idx].status & STAT_GETTING)) &&
02032 (!(dcc[idx].status & STAT_SENDING)))
02033 new_tbuf(dcc[idx].nick);
02034 }
02035 if (!k)
02036 def_dcc_bot_kill(idx, x);
02037 }
02038
02039 static tcl_ints my_ints[] = {
02040 {"allow-resync", &allow_resync},
02041 {"resync-time", &resync_time},
02042 {"private-global", &private_global},
02043 {"private-user", &private_user},
02044 {"override-bots", &overr_local_bots},
02045 {NULL, NULL}
02046 };
02047
02048 static tcl_strings my_strings[] = {
02049 {"private-globals", private_globals, 50, 0},
02050 {NULL, NULL, 0, 0}
02051 };
02052
02053 static void cmd_flush(struct userrec *u, int idx, char *par)
02054 {
02055 if (!par[0])
02056 dprintf(idx, "Usage: flush <botname>\n");
02057 else if (flush_tbuf(par))
02058 dprintf(idx, "Flushed resync buffer for %s\n", par);
02059 else
02060 dprintf(idx, "There is no resync buffer for that bot.\n");
02061 }
02062
02063 static cmd_t my_cmds[] = {
02064 {"flush", "n", (IntFunc) cmd_flush, NULL},
02065 {NULL, NULL, NULL, NULL}
02066 };
02067
02068 static char *share_close()
02069 {
02070 int i;
02071 tandbuf *t, *tnext = NULL;
02072
02073 module_undepend(MODULE_NAME);
02074 putlog(LOG_MISC | LOG_BOTS, "*", "Sending 'share end' to all sharebots...");
02075 for (i = 0; i < dcc_total; i++)
02076 if ((dcc[i].type->flags & DCT_BOT) && (dcc[i].status & STAT_SHARE)) {
02077 dprintf(i, "s e Unload module\n");
02078 cancel_user_xfer(-i, 0);
02079 updatebot(-1, dcc[i].nick, '-', 0);
02080 dcc[i].status &= ~(STAT_SHARE | STAT_GETTING | STAT_SENDING |
02081 STAT_OFFERED | STAT_AGGRESSIVE);
02082 dcc[i].u.bot->uff_flags = 0;
02083 }
02084 putlog(LOG_MISC | LOG_BOTS, "*",
02085 "Unloaded sharing module, flushing tbuf's...");
02086 for (t = tbuf; t; t = tnext) {
02087 tnext = t->next;
02088 del_tbuf(t);
02089 }
02090 del_hook(HOOK_SHAREOUT, (Function) shareout_mod);
02091 del_hook(HOOK_SHAREIN, (Function) sharein_mod);
02092 del_hook(HOOK_MINUTELY, (Function) check_expired_tbufs);
02093 del_hook(HOOK_READ_USERFILE, (Function) hook_read_userfile);
02094 del_hook(HOOK_SECONDLY, (Function) check_delay);
02095 DCC_BOT.kill = def_dcc_bot_kill;
02096 uff_deltable(internal_uff_table);
02097 delay_free_mem();
02098 rem_tcl_ints(my_ints);
02099 rem_tcl_strings(my_strings);
02100 rem_builtins(H_dcc, my_cmds);
02101 rem_help_reference("share.help");
02102 return NULL;
02103 }
02104
02105 static int share_expmem()
02106 {
02107 int tot = 0;
02108 struct share_msgq *q;
02109 tandbuf *t;
02110
02111 for (t = tbuf; t && t->bot[0]; t = t->next) {
02112 tot += sizeof(tandbuf);
02113 for (q = t->q; q; q = q->next) {
02114 tot += sizeof(struct share_msgq);
02115 tot += strlen(q->msg) + 1;
02116 }
02117 }
02118 tot += uff_expmem();
02119 tot += delay_expmem();
02120 return tot;
02121 }
02122
02123 static void share_report(int idx, int details)
02124 {
02125 if (details) {
02126 int i, j, size = share_expmem();
02127
02128 dprintf(idx, " Private owners: %s\n", (private_global ||
02129 (private_globals_bitmask() & USER_OWNER)) ? "yes" : "no");
02130 dprintf(idx, " Allow resync: %s\n", allow_resync ? "yes" : "no");
02131
02132 for (i = 0; i < dcc_total; i++) {
02133 if (dcc[i].type == &DCC_BOT) {
02134 if (dcc[i].status & STAT_GETTING) {
02135 int ok = 0;
02136
02137 for (j = 0; j < dcc_total; j++)
02138 if (((dcc[j].type->flags & (DCT_FILETRAN | DCT_FILESEND)) ==
02139 (DCT_FILETRAN | DCT_FILESEND)) &&
02140 !egg_strcasecmp(dcc[j].host, dcc[i].nick)) {
02141 dprintf(idx, " Downloading userlist from %s (%d%% done)\n",
02142 dcc[i].nick, (int) (100.0 * ((float) dcc[j].status) /
02143 ((float) dcc[j].u.xfer->length)));
02144 ok = 1;
02145 break;
02146 }
02147 if (!ok)
02148 dprintf(idx, " Download userlist from %s (negotiating "
02149 "botentries)\n", dcc[i].nick);
02150 } else if (dcc[i].status & STAT_SENDING) {
02151 for (j = 0; j < dcc_total; j++) {
02152 if (((dcc[j].type->flags & (DCT_FILETRAN | DCT_FILESEND)) ==
02153 DCT_FILETRAN) && !egg_strcasecmp(dcc[j].host, dcc[i].nick)) {
02154 if (dcc[j].type == &DCC_GET)
02155 dprintf(idx, " Sending userlist to %s (%d%% done)\n",
02156 dcc[i].nick, (int) (100.0 * ((float) dcc[j].status) /
02157 ((float) dcc[j].u.xfer->length)));
02158 else
02159 dprintf(idx, " Sending userlist to %s (waiting for connect)\n",
02160 dcc[i].nick);
02161 }
02162 }
02163 } else if (dcc[i].status & STAT_AGGRESSIVE) {
02164 dprintf(idx, " Passively sharing with %s.\n", dcc[i].nick);
02165 } else if (dcc[i].status & STAT_SHARE) {
02166 dprintf(idx, " Aggressively sharing with %s.\n", dcc[i].nick);
02167 }
02168 }
02169 }
02170 status_tbufs(idx);
02171 dprintf(idx, " Using %d byte%s of memory\n", size,
02172 (size != 1) ? "s" : "");
02173 }
02174 }
02175
02176 EXPORT_SCOPE char *share_start();
02177
02178 static Function share_table[] = {
02179
02180 (Function) share_start,
02181 (Function) share_close,
02182 (Function) share_expmem,
02183 (Function) share_report,
02184
02185 (Function) finish_share,
02186 (Function) dump_resync,
02187 (Function) uff_addtable,
02188 (Function) uff_deltable
02189 };
02190
02191 char *share_start(Function *global_funcs)
02192 {
02193
02194 global = global_funcs;
02195
02196 module_register(MODULE_NAME, share_table, 2, 3);
02197 if (!module_depend(MODULE_NAME, "eggdrop", 106, 0)) {
02198 module_undepend(MODULE_NAME);
02199 return "This module requires Eggdrop 1.6.0 or later.";
02200 }
02201 if (!(transfer_funcs = module_depend(MODULE_NAME, "transfer", 2, 0))) {
02202 module_undepend(MODULE_NAME);
02203 return "This module requires transfer module 2.0 or later.";
02204 }
02205 if (!(channels_funcs = module_depend(MODULE_NAME, "channels", 1, 0))) {
02206 module_undepend(MODULE_NAME);
02207 return "This module requires channels module 1.0 or later.";
02208 }
02209 add_hook(HOOK_SHAREOUT, (Function) shareout_mod);
02210 add_hook(HOOK_SHAREIN, (Function) sharein_mod);
02211 add_hook(HOOK_MINUTELY, (Function) check_expired_tbufs);
02212 add_hook(HOOK_READ_USERFILE, (Function) hook_read_userfile);
02213 add_hook(HOOK_SECONDLY, (Function) check_delay);
02214 add_help_reference("share.help");
02215 def_dcc_bot_kill = DCC_BOT.kill;
02216 DCC_BOT.kill = cancel_user_xfer;
02217 add_tcl_ints(my_ints);
02218 add_tcl_strings(my_strings);
02219 add_builtins(H_dcc, my_cmds);
02220 uff_init();
02221 uff_addtable(internal_uff_table);
02222 return NULL;
02223 }
02224
02225 int private_globals_bitmask()
02226 {
02227 struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0, 0 };
02228
02229 break_down_flags(private_globals, &fr, 0);
02230 return fr.global;
02231 }