Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/dll/fserv/fserv.c
1069 views
1
#define AUTO_VERSION "1.00"
2
3
/*
4
*
5
* Written by Colten Edwards. (C) Nov 11/99
6
*
7
*/
8
9
#include "irc.h"
10
#include "struct.h"
11
#include "dcc.h"
12
#include "ircaux.h"
13
#include "ctcp.h"
14
#include "cdcc.h"
15
#include "input.h"
16
#include "status.h"
17
#include "lastlog.h"
18
#include "screen.h"
19
#include "vars.h"
20
#include "misc.h"
21
#include "output.h"
22
#include "module.h"
23
#include "hook.h"
24
#include "hash2.h"
25
#include "bsdglob.h"
26
#define INIT_MODULE
27
#include "modval.h"
28
29
#include <sys/time.h>
30
#include <sys/stat.h>
31
32
#define cparse convert_output_format
33
#define FS "%PFS%w:%n"
34
35
#define DEFAULT_IMPRESS_TIME 30
36
#define DEFAULT_FSERV 1
37
#define DEFAULT_IMPRESS 0
38
#define DEFAULT_MAX_MATCH 4
39
#define DEFAULT_RECURSE 1
40
#define DEFAULT_FILEMASK "*.mp3"
41
42
43
char fserv_version[] = "Fserv 1.000";
44
char *fserv_filename = NULL;
45
char FSstr[80] = "FS:";
46
47
typedef struct _Stats {
48
unsigned long total_files;
49
unsigned long total_filesize;
50
unsigned long files_served;
51
unsigned long filesize_served;
52
double max_speed;
53
time_t starttime;
54
} Stats;
55
56
Stats statistics = { 0, };
57
58
/*
59
* ideas.
60
* make it notice instead of msg the nick.
61
* make it allow /msg nick !filename
62
*/
63
64
#if 0
65
<Lena-:#mp3jukebox> <><>< For My List(1069 files: 4307MB) and DCC Status Type
66
@Lena- and @Lena--stats [(1/10) Slots Taken (0/10) Ques
67
Taken] [Open Slot Ready] [Bandwidth in Use: 3081cps]
68
[Highest Cps Record: 56.3kb/s by Grey13] [Total Files
69
Served: 6045] ><><>
70
<Gaff> [ !Gaff Is It Too Late Now.mp3 ] [2.6MB 128Kbps 44.1Khz Joint Stereo
71
(2m44s)]-SpR-@Gaff -> request my list-@Gaff-que -> check
72
que-@Gaff-stats -> check DCC stats-@Gaff-remove -> cancel
73
song request
74
#endif
75
76
typedef struct _AUDIO_HEADER {
77
int IDex;
78
int ID;
79
int layer;
80
int protection_bit;
81
int bitrate_index;
82
int sampling_frequency;
83
int padding_bit;
84
int private_bit;
85
int mode; /* 0 = STEREO 1 = Joint 2 = DUAL 3 = Mono */
86
int mode_extension;
87
int copyright;
88
int original;
89
int emphasis;
90
int stereo;
91
int jsbound;
92
int sblimit;
93
int true_layer;
94
int framesize;
95
} AUDIO_HEADER;
96
97
98
static unsigned char _buffer[32];
99
static int _bptr = 0;
100
101
102
typedef struct _files {
103
struct _files *next;
104
char *filename;
105
unsigned long filesize;
106
time_t time;
107
int bitrate;
108
int freq;
109
int stereo;
110
int id3;
111
} Files;
112
113
Files *fserv_files = NULL;
114
115
116
char *mode_str(int mode)
117
{
118
switch(mode)
119
{
120
case 0:
121
return "Stereo";
122
case 1:
123
return "Joint-Stereo";
124
case 2:
125
return "Dual-Channel";
126
case 3:
127
return "Mono";
128
}
129
return empty_string;
130
}
131
132
char *print_time(time_t input)
133
{
134
static char buff[40];
135
time_t seconds,
136
minutes;
137
seconds = input;
138
minutes = seconds / 60;
139
seconds = seconds % 60;
140
sprintf(buff, "%02u:%02u", (unsigned int)minutes, (unsigned int)seconds);
141
return buff;
142
}
143
144
char *make_mp3_string(FILE *fp, Files *f, char *fs, char *dirbuff)
145
{
146
static char buffer[BIG_BUFFER_SIZE+1];
147
char *s,
148
*loc,
149
*p,
150
*fn;
151
152
if (!fs || !*fs)
153
return empty_string;
154
memset(buffer, 0, sizeof(buffer));
155
156
loc = LOCAL_COPY(f->filename);
157
fn = strrchr(loc, '/');
158
*fn++ = 0;
159
if ((p = strrchr(loc, '/')))
160
*p++ = 0;
161
/* fn should point to the filename and p to the dir */
162
/*
163
* init the dir keeper
164
* or cmp the old dir with the new
165
*/
166
if (dirbuff && (!*dirbuff || strcmp(dirbuff, p)))
167
{
168
strcpy(dirbuff, p);
169
if (fp)
170
fprintf(fp, "\nDirectory [ %s ]\n", dirbuff);
171
else
172
return NULL;
173
}
174
/* size bitrate [time] filename */
175
s = buffer;
176
while (*fs)
177
{
178
if (*fs == '%')
179
{
180
int prec = 0, fl = 0;
181
fs++;
182
if (isdigit(*fs))
183
{
184
prec = strtol(fs, &fs, 0);
185
if (*fs == '.')
186
fl = strtoul(fs+1, &fs, 0);
187
}
188
switch(*fs)
189
{
190
case '%':
191
*s++ = *fs;
192
break;
193
case 'b':
194
sprintf(s, "%*u", prec, f->bitrate);
195
break;
196
case 's':
197
if (!prec) prec = 3;
198
sprintf(s, "%*.*f%s", prec, fl, _GMKv(f->filesize), _GMKs(f->filesize));
199
break;
200
case 't':
201
strcpy(s, print_time(f->time));
202
break;
203
case 'T':
204
strcpy(s, ltoa(f->time));
205
break;
206
case 'f':
207
strcpy(s, fn);
208
break;
209
case 'F':
210
strcpy(s, f->filename);
211
break;
212
case 'S':
213
strcpy(s, mode_str(f->stereo));
214
break;
215
case 'H':
216
sprintf(s, "%*.*f", prec, fl, ((double)f->freq) / ((double)1000.0));
217
break;
218
case 'h':
219
sprintf(s, "%*u", prec, f->freq);
220
break;
221
default:
222
*s++ = *fs;
223
break;
224
}
225
}
226
else if (*fs == '\\')
227
{
228
fs++;
229
switch(*fs)
230
{
231
case 'n':
232
strcpy(s, "\n");
233
break;
234
case 't':
235
strcpy(s, "\t");
236
break;
237
default:
238
*s++ = *fs++;
239
}
240
}
241
else
242
*s++ = *fs;
243
while (*s) s++;
244
fs++;
245
}
246
if (fp && *buffer)
247
fprintf(fp, buffer);
248
return buffer;
249
}
250
251
252
int read_glob_dir(char *path, int globflags, glob_t *globpat, int recurse)
253
{
254
char buffer[BIG_BUFFER_SIZE+1];
255
256
sprintf(buffer, "%s/*", path);
257
bsd_glob(buffer, globflags, NULL, globpat);
258
if (recurse)
259
{
260
int i = 0;
261
int old_glpathc = globpat->gl_pathc;
262
for (i = 0; i < old_glpathc; i++)
263
{
264
char *fn;
265
fn = globpat->gl_pathv[i];
266
if (fn[strlen(fn)-1] != '/')
267
continue;
268
sprintf(buffer, "%s*", fn);
269
bsd_glob(buffer, globflags|GLOB_APPEND, NULL, globpat);
270
}
271
while (i < globpat->gl_pathc)
272
{
273
for (i = old_glpathc, old_glpathc = globpat->gl_pathc; i < old_glpathc; i++)
274
{
275
char *fn;
276
fn = globpat->gl_pathv[i];
277
if (fn[strlen(fn)-1] != '/')
278
continue;
279
sprintf(buffer, "%s*", fn);
280
bsd_glob(buffer, globflags|GLOB_APPEND, NULL, globpat);
281
}
282
}
283
}
284
return 0;
285
}
286
287
unsigned int print_mp3(char *pattern, char *format, int freq, int number, int bitrate)
288
{
289
unsigned int count = 0;
290
Files *new;
291
char dir[BIG_BUFFER_SIZE];
292
char *fs = NULL;
293
*dir = 0;
294
for (new = fserv_files; new; new = new->next)
295
{
296
if (!pattern || (pattern && wild_match(pattern, new->filename)))
297
{
298
char *p;
299
p = LOCAL_COPY(new->filename);
300
p = strrchr(new->filename, '/');
301
p++;
302
if (do_hook(MODULE_LIST, "FS: File \"%s\" %s %u %lu %lu %u", p, mode_str(new->stereo), new->bitrate, new->time, new->filesize, new->freq))
303
{
304
if ((bitrate != -1) && (new->bitrate != bitrate))
305
continue;
306
if ((freq != -1) && (new->freq != freq))
307
continue;
308
if (!format || !*format)
309
put_it("%s \"%s\" %s %dk [%s]", FSstr, p, mode_str(new->stereo), new->bitrate, print_time(new->time));
310
else
311
{
312
if ((fs = make_mp3_string(NULL, new, format, dir)))
313
put_it("%s %s", FSstr, fs);
314
else
315
put_it("%s %s", FSstr, make_mp3_string(NULL, new, format, dir));
316
}
317
}
318
if ((number > 0) && (count == number))
319
break;
320
count++;
321
}
322
}
323
return count;
324
}
325
326
BUILT_IN_DLL(print_fserv)
327
{
328
int count = 0;
329
int bitrate = -1;
330
int number = -1;
331
int freq = -1;
332
char *fs_output = NULL;
333
char *tmp_pat = NULL;
334
335
if ((get_dllstring_var("fserv_format")))
336
fs_output = m_strdup(get_dllstring_var("fserv_format"));
337
if (args && *args)
338
{
339
char *tmp;
340
while ((tmp = next_arg(args, &args)) && *tmp)
341
{
342
int len;
343
len = strlen(tmp);
344
if (!my_strnicmp(tmp, "-BITRATE", len))
345
{
346
if ((tmp = next_arg(args, &args)))
347
bitrate = (unsigned int) my_atol(tmp);
348
}
349
else if (!my_strnicmp(tmp, "-COUNT", len))
350
{
351
if ((tmp = next_arg(args, &args)))
352
number = (unsigned int) my_atol(tmp);
353
}
354
else if (!my_strnicmp(tmp, "-FREQ", 3))
355
{
356
if ((tmp = next_arg(args, &args)))
357
freq = (unsigned int)my_atol(tmp);
358
}
359
else if (!my_strnicmp(tmp, "-FORMAT", 3))
360
{
361
if ((tmp = new_next_arg(args, &args)))
362
malloc_strcpy(&fs_output, tmp);
363
}
364
else
365
{
366
count += print_mp3(tmp, fs_output, freq, number, bitrate);
367
m_s3cat(&tmp_pat, " ", tmp);
368
}
369
}
370
}
371
else
372
count += print_mp3(NULL, fs_output, freq, number, bitrate);
373
374
if (do_hook(MODULE_LIST, "FS: Found %d %s", count, tmp_pat ? tmp_pat : "*"))
375
put_it("%s found %d files matching \"%s\"", FSstr, count, tmp_pat ? tmp_pat : "*");
376
new_free(&tmp_pat);
377
new_free(&fs_output);
378
}
379
380
int _get_input(int file, unsigned char *bp, int size)
381
{
382
if (read(file, bp, size) != size)
383
return -1;
384
return 0;
385
}
386
387
static inline int readsync(int file)
388
{
389
_bptr=0;
390
_buffer[0]=_buffer[1];
391
_buffer[1]=_buffer[2];
392
_buffer[2]=_buffer[3];
393
return _get_input(file, &_buffer[3], 1);
394
}
395
396
397
static inline int _fillbfr(int file, unsigned int size)
398
{
399
_bptr=0;
400
return _get_input(file, _buffer, size);
401
}
402
403
404
static inline unsigned int _getbits(int n)
405
{
406
unsigned int pos,
407
ret_value;
408
409
pos = _bptr >> 3;
410
ret_value = _buffer[pos] << 24 |
411
_buffer[pos+1] << 16 |
412
_buffer[pos+2] << 8 |
413
_buffer[pos+3];
414
ret_value <<= _bptr & 7;
415
ret_value >>= 32 - n;
416
_bptr += n;
417
return ret_value;
418
}
419
420
421
/*
422
* header and side info parsing stuff ******************************************
423
*/
424
static inline void parse_header(AUDIO_HEADER *header)
425
{
426
header->IDex=_getbits(1);
427
header->ID=_getbits(1);
428
header->layer=_getbits(2);
429
header->protection_bit=_getbits(1);
430
header->bitrate_index=_getbits(4);
431
header->sampling_frequency=_getbits(2);
432
header->padding_bit=_getbits(1);
433
header->private_bit=_getbits(1);
434
header->mode=_getbits(2);
435
header->mode_extension=_getbits(2);
436
if (!header->mode)
437
header->mode_extension=0;
438
header->copyright=_getbits(1);
439
header->original=_getbits(1);
440
header->emphasis=_getbits(2);
441
442
header->stereo = (header->mode == 3) ? 1 : 2;
443
header->true_layer = 4 - header->layer;
444
}
445
446
int gethdr(int file, AUDIO_HEADER *header)
447
{
448
int retval;
449
450
if ((retval=_fillbfr(file, 4)))
451
return retval;
452
453
while (_getbits(11) != 0x7ff)
454
{
455
if ((retval=readsync(file))!=0)
456
return retval;
457
}
458
parse_header(header);
459
return 0;
460
}
461
462
long get_bitrate(char *filename, time_t *mp3_time, unsigned int *freq_rate, int *id3, unsigned long *filesize, int *stereo)
463
{
464
short t_bitrate[2][3][15] = {{
465
{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256},
466
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160},
467
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}
468
},{
469
{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
470
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384},
471
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}
472
}};
473
474
int t_sampling_frequency[2][2][3] = {
475
{ /* MPEG 2.5 samplerates */
476
{ 11025, 12000, 8000},
477
{ 0,0,0 }
478
},{ /* MPEG 2.0/1.0 samplerates */
479
{ 22050 , 24000 , 16000},
480
{ 44100 , 48000 , 32000}
481
}
482
};
483
484
AUDIO_HEADER header;
485
unsigned long btr = 0;
486
int l = -1;
487
struct stat st;
488
unsigned long framesize = 0,
489
totalframes = 0;
490
491
if (freq_rate)
492
*freq_rate =0;
493
if (id3)
494
*id3 = 0;
495
if ((l = open(filename, O_RDONLY)) == -1)
496
return 0;
497
gethdr(l, &header);
498
if (header.ID > 1 || header.layer > 2 || header.bitrate_index > 14)
499
{
500
close(l);
501
return 0;
502
}
503
btr = t_bitrate[header.ID][3-header.layer][header.bitrate_index];
504
505
fstat(l, &st);
506
if (t_sampling_frequency[header.IDex][header.ID][header.sampling_frequency] > 0)
507
framesize = (header.ID ? 144000 : 72000) * btr / t_sampling_frequency[header.IDex][header.ID][header.sampling_frequency];
508
totalframes = (st.st_size / (framesize + 1)) - 1;
509
if (t_sampling_frequency[header.IDex][header.ID][header.sampling_frequency] > 0)
510
*mp3_time = (time_t) (totalframes * (header.ID==0?576:1152)/t_sampling_frequency[header.IDex][header.ID][header.sampling_frequency]);
511
*filesize = st.st_size;
512
513
if (freq_rate)
514
*freq_rate = t_sampling_frequency[header.IDex][header.ID][header.sampling_frequency];
515
if (id3)
516
{
517
char buffer[200];
518
lseek(l, SEEK_END, -128);
519
if (read(l, buffer, 128) > 0)
520
if (!strncmp(buffer, "TAG", 3))
521
*id3 = 1;
522
}
523
*stereo = header.mode;
524
close(l);
525
return btr;
526
}
527
528
529
530
BUILT_IN_DLL(unload_fserv)
531
{
532
Files *new, *tmp;
533
int count = 0;
534
if (!args || !*args)
535
{
536
while ((new = fserv_files))
537
{
538
tmp = fserv_files->next;
539
new_free(&new->filename);
540
statistics.total_filesize -= new->filesize;
541
new_free(&new);
542
fserv_files = tmp;
543
count++;
544
}
545
}
546
else
547
{
548
char *pat;
549
550
while ((pat = new_next_arg(args, &args)))
551
{
552
if (!pat || !*pat)
553
break;
554
if ((new = (Files *)remove_from_list((List **)&fserv_files, pat)))
555
{
556
new_free(&new->filename);
557
statistics.total_filesize -= new->filesize;
558
new_free(&new);
559
count++;
560
}
561
}
562
}
563
if (do_hook(MODULE_LIST, "FS: Clear %d", count))
564
put_it("%s cleared %d entries", FSstr, count);
565
statistics.total_files -= count;
566
}
567
568
off_t file_size (char *filename)
569
{
570
struct stat statbuf;
571
572
if (!stat(filename, &statbuf))
573
return (off_t)(statbuf.st_size);
574
else
575
return -1;
576
}
577
578
unsigned int scan_mp3_dir(char *path, int recurse, int reload)
579
{
580
int mt = 0;
581
glob_t globpat;
582
int i = 0;
583
Files *new;
584
int count = 0;
585
memset(&globpat, 0, sizeof(glob_t));
586
read_glob_dir(path, GLOB_MARK|GLOB_NOSORT, &globpat, recurse);
587
for (i = 0; i < globpat.gl_pathc; i++)
588
{
589
char *fn;
590
fn = globpat.gl_pathv[i];
591
if (fn[strlen(fn)-1] == '/')
592
continue;
593
if (!(mt = wild_match(DEFAULT_FILEMASK, fn)))
594
continue;
595
if (reload && find_in_list((List **)&fserv_files, globpat.gl_pathv[i], 0))
596
continue;
597
new = (Files *) new_malloc(sizeof(Files));
598
new->filename = m_strdup(fn);
599
new->bitrate = get_bitrate(fn, &new->time, &new->freq, &new->id3, &new->filesize, &new->stereo);
600
if (new->filesize)
601
{
602
add_to_list((List **)&fserv_files, (List *)new);
603
statistics.total_files++;
604
statistics.total_filesize += new->filesize;
605
count++;
606
}
607
else
608
{
609
new_free(&new->filename);
610
new_free(&new);
611
}
612
}
613
bsd_globfree(&globpat);
614
return count;
615
}
616
617
BUILT_IN_DLL(load_fserv)
618
{
619
char *path = NULL;
620
int recurse = DEFAULT_RECURSE;
621
char *pch;
622
int count = 0;
623
int reload = 0;
624
625
if (command && !my_stricmp(command, "FSRELOAD"))
626
reload = 1;
627
if (args && *args)
628
{
629
while ((path = next_arg(args, &args)) && *path)
630
{
631
int len = strlen(path);
632
if (!my_strnicmp(path, "-recurse", len))
633
{
634
recurse ^= 1;
635
continue;
636
}
637
count += scan_mp3_dir(path, recurse, reload);
638
}
639
goto fs_print_out;
640
}
641
642
path = get_dllstring_var("fserv_dir");
643
644
if (!path || !*path)
645
{
646
if (do_hook(MODULE_LIST, "FS: Error no fserv_dir path"))
647
put_it("%s No path. /set fserv_dir first.", FSstr);
648
return;
649
}
650
651
pch = LOCAL_COPY(path);
652
while ((path = next_arg(pch, &pch)))
653
count += scan_mp3_dir(path, recurse, reload);
654
fs_print_out:
655
if (do_hook(MODULE_LIST, "FS: Load %d", count))
656
{
657
if (!fserv_files || !count)
658
put_it("%s Could not read dir", FSstr);
659
else
660
put_it("%s found %d files", FSstr, count);
661
}
662
return;
663
}
664
665
Files *search_list(char *nick, char *pat, int wild)
666
{
667
Files *new;
668
int dcc_send_num = 0;
669
int dcc_queue_num = 0;
670
char *p;
671
char buffer[BIG_BUFFER_SIZE+1];
672
int num_to_match;
673
674
num_to_match = get_dllint_var("fserv_max_match");
675
if (wild)
676
{
677
int count = 0;
678
679
sprintf(buffer, "*%s*", pat);
680
while ((p = strchr(buffer, ' ')))
681
*p = '*';
682
dcc_send_num = get_active_count();
683
dcc_queue_num = get_num_queue();
684
for (new = fserv_files; new; new = new->next)
685
{
686
p = strrchr(new->filename, '/');
687
p++;
688
if (!wild_match(buffer, p))
689
continue;
690
691
if (!count)
692
if (do_hook(MODULE_LIST, "FS: SearchHeader %s %s %d %d %d %d", nick, buffer, dcc_send_num, get_int_var(DCC_SEND_LIMIT_VAR), dcc_queue_num, get_int_var(DCC_QUEUE_LIMIT_VAR)))
693
queue_send_to_server(from_server, "PRIVMSG %s :Matches for %s. Copy and Paste in channel to request. (Slots:%d/%d), (Queue:%d/%d)", nick, buffer, dcc_send_num, get_int_var(DCC_SEND_LIMIT_VAR), dcc_queue_num, get_int_var(DCC_QUEUE_LIMIT_VAR));
694
count++;
695
if (!num_to_match || (count < num_to_match))
696
{
697
if (do_hook(MODULE_LIST, "FS: SearchList %s \"%s\" %u %u %lu %lu", nick, p, new->bitrate, new->freq, new->filesize, new->time))
698
queue_send_to_server(from_server, "PRIVMSG %s :!%s %s %dk [%s]", nick, get_server_nickname(from_server), p, new->bitrate, print_time(new->time));
699
}
700
}
701
if (num_to_match && (count > num_to_match))
702
{
703
if (do_hook(MODULE_LIST, "FS: SearchTooMany %s %d", nick, count))
704
queue_send_to_server(from_server, "PRIVMSG %s :Too Many Matches[%d]", nick, count);
705
}
706
else if (count)
707
{
708
if (do_hook(MODULE_LIST, "FS: SearchResults %s %d", nick, count))
709
queue_send_to_server(from_server, "PRIVMSG %s :..... Total %d files found", nick, count);
710
}
711
return NULL;
712
}
713
for (new = fserv_files; new; new = new->next)
714
{
715
p = strrchr(new->filename, '/');
716
p++;
717
if (my_stricmp(pat, p))
718
continue;
719
return new;
720
}
721
return NULL;
722
}
723
724
725
char *make_temp_list(char *nick)
726
{
727
char *nam;
728
char *real_nam;
729
FILE *fp;
730
731
if (!(nam = get_dllstring_var("fserv_filename")) || !*nam)
732
nam = tmpnam(NULL);
733
real_nam = expand_twiddle(nam);
734
if (!fserv_files || !real_nam || !*real_nam)
735
{
736
new_free(&real_nam);
737
return NULL;
738
}
739
if ((fp = fopen(real_nam, "w")))
740
{
741
char buffer2[BIG_BUFFER_SIZE+1];
742
char *fs;
743
int count = 0;
744
745
time_t t = now;
746
Files *new;
747
strftime(buffer2, 200, "%X %d/%m/%Y", localtime(&t));
748
for (new = fserv_files; new; new = new->next)
749
count++;
750
fprintf(fp, "Temporary mp3 list created for %s by %s on %s with %d mp3's\n\n", nick, get_server_nickname(from_server), buffer2, count);
751
*buffer2 = 0;
752
if (!(fs = get_dllstring_var("fserv_format")) || !*fs)
753
fs = " %6.3s %3b [%t]\t %f\n";
754
for (new = fserv_files; new; new = new->next)
755
make_mp3_string(fp, new, fs, buffer2);
756
fclose(fp);
757
new_free(&real_nam);
758
return nam;
759
}
760
new_free(&real_nam);
761
return NULL;
762
}
763
764
BUILT_IN_DLL(list_fserv)
765
{
766
char *nam;
767
if (!get_dllstring_var("fserv_filename"))
768
{
769
put_it("%s /set fserv_filename first", FSstr);
770
return;
771
}
772
if ((nam = make_temp_list(get_server_nickname(from_server))))
773
malloc_strcpy(&fserv_filename, nam);
774
return;
775
}
776
777
int search_proc(char *which, char *str, char **unused)
778
{
779
char *loc,
780
*chan = NULL,
781
*nick,
782
*command,
783
*chan_list;
784
char buffer[BIG_BUFFER_SIZE+1];
785
786
loc = LOCAL_COPY(str);
787
chan_list = get_dllstring_var("fserv_chan");
788
nick = next_arg(loc, &loc);
789
790
if (my_stricmp(which, "MSG"))
791
{
792
chan = next_arg(loc, &loc);
793
command = next_arg(loc, &loc);
794
}
795
else
796
command = next_arg(loc, &loc);
797
798
if (!get_dllint_var("fserv"))
799
return 1;
800
if (chan_list && *chan_list && chan)
801
{
802
char *t,
803
*ch;
804
int got_it = 0;
805
ch = LOCAL_COPY(chan_list);
806
if (*ch == '*')
807
got_it = 1;
808
else
809
{
810
while ((t = next_in_comma_list(ch, &ch)) && *t)
811
if (!my_stricmp(t, chan))
812
got_it = 1;
813
}
814
if (!got_it)
815
return 1;
816
}
817
if (command && *command == '@')
818
{
819
char *p;
820
command++;
821
if (!*command)
822
return 1;
823
if (loc && *loc && (!my_stricmp(command, "locate") || !my_stricmp(command, "find")))
824
{
825
search_list(nick, loc, 1);
826
if (do_hook(MODULE_LIST, "FS: Search %s %s \"%s\"", nick, chan ? chan : "*", loc))
827
put_it("%s got nick %s in %s searching for \"%s\"" , FSstr, nick, chan ? chan : "*", loc);
828
return 1;
829
}
830
if ((p = strchr(command, '-')))
831
{
832
*p++ = 0;
833
if (!*p || my_stricmp(command, get_server_nickname(from_server)))
834
return 1;
835
if (!my_stricmp("que", command))
836
{
837
/* check queue */
838
return 1;
839
}
840
if (!my_stricmp("stats", command))
841
{
842
/* print stats */
843
return 1;
844
}
845
if (!my_stricmp("remove", command))
846
{
847
/* remove from queue */
848
return 1;
849
}
850
}
851
}
852
if (command && *command == '!')
853
{
854
command++;
855
if (!*command) return 1;
856
if (!my_stricmp(get_server_nickname(from_server), command) && loc && *loc)
857
{
858
Files *fn = NULL;
859
if ((fn = search_list(nick, loc, 0)))
860
{
861
int send_num,
862
queue_num;
863
send_num = get_active_count();
864
queue_num = get_num_queue();
865
if (do_hook(MODULE_LIST, "FS: Sending %s \"%s\" $lu", nick, fn->filename, fn->filesize))
866
put_it("%s sending %s \"%s\" %lu", FSstr, nick, fn->filename, fn->filesize);
867
sprintf(buffer, "%s \"%s\"", nick, fn->filename);
868
if (send_num > get_int_var(DCC_SEND_LIMIT_VAR))
869
{
870
pack *ptr = NULL;
871
if (queue_num < get_int_var(DCC_QUEUE_LIMIT_VAR))
872
{
873
sprintf(buffer, "\"%s\"", fn->filename);
874
ptr = (pack *)alloca(sizeof(pack));
875
memset(ptr, 0, sizeof(pack));
876
ptr->file = LOCAL_COPY(buffer);
877
ptr->desc = LOCAL_COPY(buffer);
878
ptr->numfiles = 1;
879
ptr->size = fn->filesize;
880
ptr->server = from_server;
881
do_hook(MODULE_LIST, "FS: Queue Add %s %s", nick, buffer);
882
883
if (add_to_queue(nick, "SEND", ptr))
884
{
885
statistics.files_served++;
886
statistics.filesize_served += fn->filesize;
887
}
888
else if (do_hook(MODULE_LIST, "FS: QueueFile %s %s", nick, buffer))
889
queue_send_to_server(from_server, "PRIVMSG %s :Queued File %s", nick, buffer);
890
} else if (do_hook(MODULE_LIST, "FS: Queue Full %s", nick))
891
queue_send_to_server(from_server, "PRIVMSG %s :Queue is full, try again later.", nick);
892
}
893
else
894
{
895
dcc_filesend("SEND", buffer);
896
statistics.files_served++;
897
statistics.filesize_served += fn->filesize;
898
}
899
}
900
}
901
else if (!my_stricmp(get_server_nickname(from_server), command))
902
{
903
char *name = NULL;
904
if (fserv_filename || (name = make_temp_list(nick)))
905
{
906
sprintf(buffer, "%s %s", nick, fserv_filename ? fserv_filename : name);
907
dcc_filesend("SEND", buffer);
908
}
909
}
910
}
911
return 1;
912
}
913
914
void impress_me(void *args)
915
{
916
int timer;
917
char *ch = NULL;
918
ChannelList *chan= NULL;
919
920
timer = get_dllint_var("fserv_time");
921
if (timer < DEFAULT_IMPRESS_TIME)
922
timer = DEFAULT_IMPRESS_TIME;
923
if (!(ch = get_dllstring_var("fserv_chan")) || !*ch)
924
ch = NULL;
925
else
926
ch = m_strdup(ch);
927
chan = get_server_channels(from_server);
928
if (!ch)
929
ch = m_strdup(get_current_channel_by_refnum(0));
930
else
931
{
932
char *c,
933
*p;
934
935
c = LOCAL_COPY(ch);
936
ch = NULL;
937
if (*c == '*')
938
{
939
ChannelList *chan;
940
for (chan = get_server_channels(from_server); chan; chan=chan->next)
941
m_s3cat(&ch, ",", chan->channel);
942
}
943
else
944
{
945
ChannelList *tmpchan;
946
while ((p = next_in_comma_list(c, &c)) && *p)
947
{
948
if ((tmpchan = (ChannelList *)find_in_list((List **)&chan, p, 0)))
949
m_s3cat(&ch, ",", p);
950
}
951
}
952
}
953
if (fserv_files && get_dllint_var("fserv_impress"))
954
{
955
unsigned long l;
956
Files *new;
957
958
l = random_number(0L) % statistics.total_files;
959
for (new = fserv_files; new && l; new = new->next, l--)
960
;
961
if (new && new->bitrate)
962
{
963
char frq[30],
964
size[40],
965
*p;
966
p = strrchr(new->filename, '/');
967
p++;
968
if (do_hook(MODULE_LIST, "FS: Impress %s \"%s\" %lu %u %u %s %lu",ch, p, new->filesize, new->bitrate, new->freq, mode_str(new->stereo), new->time))
969
{
970
sprintf(frq, "%3.1f", ((double)new->freq)/1000.0);
971
sprintf(size, "%4.3f%s", _GMKv(new->filesize), _GMKs(new->filesize));
972
queue_send_to_server(from_server, "PRIVMSG %s :[ !%s %s ] [%s %uKbps %sKhz %s]-[%s]",
973
ch, get_server_nickname(from_server), p,
974
size, new->bitrate, frq,
975
mode_str(new->stereo),
976
print_time(new->time));
977
}
978
}
979
}
980
add_timer(0, empty_string, timer * 1000, 1, impress_me, NULL, NULL, -1, "fserv");
981
new_free(&ch);
982
}
983
984
BUILT_IN_FUNCTION(func_convert_mp3time)
985
{
986
int hours,
987
minutes,
988
seconds;
989
if (!input)
990
return m_strdup(empty_string);
991
seconds = my_atol(input);
992
hours = seconds / ( 60 * 60 );
993
minutes = seconds / 60;
994
seconds = seconds % 60;
995
return m_sprintf("[%02d:%02d:%02d]", hours, minutes, seconds);
996
}
997
998
BUILT_IN_DLL(stats_fserv)
999
{
1000
put_it("%s\t File Server Statistics From %s", FSstr, my_ctime(statistics.starttime));
1001
put_it("%s\t Fserv is [%s] Impress is [%s] %d seconds with %d matches allowed", FSstr, on_off(get_dllint_var("fserv")), on_off(get_dllint_var("fserv_impress")), get_dllint_var("fserv_time"), get_dllint_var("fserv_max_match"));
1002
put_it("%s\t Files available %lu for %4.3f%s",FSstr, statistics.total_files, _GMKv(statistics.total_filesize), _GMKs(statistics.total_filesize));
1003
put_it("%s\t Files served %lu for %4.3f%s", FSstr, statistics.files_served, _GMKv(statistics.filesize_served), _GMKs(statistics.filesize_served));
1004
}
1005
1006
1007
1008
BUILT_IN_DLL(save_fserv)
1009
{
1010
char bogus[] = "fserv";
1011
FILE *fp;
1012
char buffer[BIG_BUFFER_SIZE];
1013
char *p;
1014
char *fserv_savname = NULL;
1015
sprintf(buffer, "%s/fserv.sav", get_string_var(CTOOLZ_DIR_VAR));
1016
fserv_savname = expand_twiddle(buffer);
1017
if (!(fp = fopen(fserv_savname, "w")))
1018
{
1019
new_free(&fserv_savname);
1020
return;
1021
}
1022
fprintf(fp, "%s %s\n", bogus, on_off(get_dllint_var("fserv")));
1023
if ((p = get_dllstring_var("fserv_dir")))
1024
fprintf(fp, "%s%s %s\n", bogus, "_dir", p);
1025
if ((p = get_dllstring_var("fserv_chan")))
1026
fprintf(fp, "%s%s %s\n", bogus, "_chan", p);
1027
if ((p = get_dllstring_var("fserv_filename")))
1028
fprintf(fp, "%s%s %s\n", bogus, "_filename", p);
1029
if ((p = get_dllstring_var("fserv_format")))
1030
fprintf(fp, "%s%s %s\n", bogus, "_format", p);
1031
fprintf(fp, "%s%s %u\n", bogus, "_time", get_dllint_var("fserv_time"));
1032
fprintf(fp, "%s%s %u\n", bogus, "_max_match", get_dllint_var("fserv_max_match"));
1033
fprintf(fp, "%s%s %s\n", bogus, "_impress", on_off(get_dllint_var("fserv_impress")));
1034
if (statistics.files_served)
1035
{
1036
fprintf(fp, "%s%s %lu\n", bogus, "_totalserved", statistics.files_served);
1037
fprintf(fp, "%s%s %lu\n", bogus, "_totalstart", statistics.starttime);
1038
fprintf(fp, "%s%s %lu\n", bogus, "_totalsizeserved", statistics.filesize_served);
1039
}
1040
fclose(fp);
1041
if ((do_hook(MODULE_LIST, "FS: Save")))
1042
put_it("%s Done Saving.", FSstr);
1043
new_free(&fserv_savname);
1044
}
1045
1046
void fserv_read(char *filename)
1047
{
1048
FILE *fp;
1049
char buff[IRCD_BUFFER_SIZE+1];
1050
char *fserv_savname = NULL;
1051
fserv_savname = expand_twiddle(filename);
1052
if (!(fp = fopen(fserv_savname, "r")))
1053
{
1054
new_free(&fserv_savname);
1055
return;
1056
}
1057
fgets(buff, IRCD_BUFFER_SIZE, fp);
1058
while (!feof(fp))
1059
{
1060
char *p;
1061
chop(buff, 1);
1062
if ((p = strchr(buff, ' ')))
1063
{
1064
*p++ = 0;
1065
1066
if (!my_strnicmp(buff, "fserv_totalserved", 17))
1067
statistics.files_served = strtoul(p, NULL, 0);
1068
else if (!my_strnicmp(buff, "fserv_totalsizeserved", 17))
1069
statistics.filesize_served = strtoul(p, NULL, 0);
1070
else if (!my_strnicmp(buff, "fserv_totalserved", 17))
1071
statistics.starttime = strtoul(p, NULL, 0);
1072
else
1073
{
1074
if (*p > '0' && *p < '9')
1075
{
1076
int val;
1077
val = my_atol(p);
1078
set_dllint_var(buff, val);
1079
}
1080
else if (!my_stricmp(p, "ON"))
1081
set_dllint_var(buff, 1);
1082
else if (!my_stricmp(p, "OFF"))
1083
set_dllint_var(buff, 0);
1084
else
1085
set_dllstring_var(buff, p);
1086
}
1087
}
1088
fgets(buff, IRCD_BUFFER_SIZE, fp);
1089
}
1090
fclose(fp);
1091
}
1092
1093
BUILT_IN_DLL(help_fserv)
1094
{
1095
put_it("%s FServ %s by Colten Edwards aka panasync", FSstr, AUTO_VERSION);
1096
put_it("%s [Sets]", FSstr);
1097
put_it("%s fserv on/off fserv functions. Default is %s", FSstr, on_off(DEFAULT_FSERV));
1098
put_it("%s fserv_dir path [path]", FSstr);
1099
put_it("%s fserv_chan #chan[,#chan2]", FSstr);
1100
put_it("%s fserv_time seconds between displays of random mp3. Default is %d", FSstr, DEFAULT_IMPRESS_TIME);
1101
put_it("%s fserv_max_match defines how many matches allowed. Default is %d", FSstr, DEFAULT_MAX_MATCH);
1102
put_it("%s fserv_impress on/off public display of random mp3. Default is %s", FSstr, on_off(DEFAULT_IMPRESS));
1103
put_it("%s", FSstr);
1104
put_it("%s channel commands are @find pattern or @locate pattern", FSstr);
1105
put_it("%s !nick filename to send a file to nick requesting", FSstr);
1106
put_it("%s a /msg to the nick can be used instead of a public", FSstr);
1107
put_it("%s a $mp3time() function as well as a hook are provided. /on module \"FS:*\"", FSstr);
1108
put_it("%s more help available with /help", FSstr);
1109
}
1110
1111
int Fserv_Lock(IrcCommandDll **intp, Function_ptr *global_table)
1112
{
1113
return 1;
1114
}
1115
1116
char *Fserv_Version(IrcCommandDll **intp)
1117
{
1118
return AUTO_VERSION;
1119
}
1120
1121
1122
int Fserv_Init(IrcCommandDll **intp, Function_ptr *global_table)
1123
{
1124
char buffer[BIG_BUFFER_SIZE+1];
1125
initialize_module("Fserv");
1126
add_module_proc(VAR_PROC, "Fserv", "fserv", NULL, BOOL_TYPE_VAR, DEFAULT_FSERV, NULL, NULL);
1127
add_module_proc(VAR_PROC, "Fserv", "fserv_dir", NULL, STR_TYPE_VAR, 0, NULL, NULL);
1128
add_module_proc(VAR_PROC, "Fserv", "fserv_chan", NULL, STR_TYPE_VAR, 0, NULL, NULL);
1129
add_module_proc(VAR_PROC, "Fserv", "fserv_filename", NULL, STR_TYPE_VAR, 0, NULL, NULL);
1130
add_module_proc(VAR_PROC, "Fserv", "fserv_format", NULL, STR_TYPE_VAR, 0, NULL, NULL);
1131
add_module_proc(VAR_PROC, "Fserv", "fserv_time", NULL, INT_TYPE_VAR, DEFAULT_IMPRESS_TIME, NULL, NULL);
1132
add_module_proc(VAR_PROC, "Fserv", "fserv_max_match", NULL, INT_TYPE_VAR, DEFAULT_MAX_MATCH, NULL, NULL);
1133
add_module_proc(VAR_PROC, "Fserv", "fserv_impress", NULL, BOOL_TYPE_VAR, DEFAULT_IMPRESS, NULL, NULL);
1134
1135
sprintf(buffer, " [-recurse] [path [path]] to load all files -recurse is a \ntoggle and can appear anywhere. Default is [%s]", on_off(DEFAULT_RECURSE));
1136
add_module_proc(COMMAND_PROC, "Fserv", "fsload", NULL, 0, 0, load_fserv, buffer);
1137
1138
sprintf(buffer, " [-count #] [-freq #] [-bitrate #] [pattern] to search database locally");
1139
add_module_proc(COMMAND_PROC, "Fserv", "fsprint", NULL, 0, 0, print_fserv, buffer);
1140
1141
sprintf(buffer, " to remove all files or [pat [pat]] to remove specific");
1142
add_module_proc(COMMAND_PROC, "Fserv", "fsunload", NULL, 0, 0, unload_fserv, buffer);
1143
1144
add_module_proc(COMMAND_PROC, "Fserv", "fshelp", NULL, 0, 0, help_fserv, " to provide help for fserv plugin");
1145
1146
sprintf(buffer, " [-recurse] [path [path]] to reload all files");
1147
add_module_proc(COMMAND_PROC, "Fserv", "fsreload", NULL, 0, 0, load_fserv, buffer);
1148
1149
add_module_proc(COMMAND_PROC, "Fserv", "fsstats", NULL, 0, 0, stats_fserv, " provides fserv statistics");
1150
1151
sprintf(buffer, " Creates list of mp3");
1152
add_module_proc(COMMAND_PROC, "Fserv", "fslist", NULL, 0, 0, list_fserv, buffer);
1153
1154
sprintf(buffer, " to save your stats and settings to %s/fserv.sav", get_string_var(CTOOLZ_DIR_VAR));
1155
add_module_proc(COMMAND_PROC, "Fserv", "fssave", NULL, 0, 0, save_fserv, buffer);
1156
1157
1158
add_module_proc(ALIAS_PROC, "Fserv", "mp3time", NULL, 0, 0, func_convert_mp3time, NULL);
1159
add_module_proc(HOOK_PROC, "Fserv", NULL, "*", PUBLIC_LIST, 1, NULL, search_proc);
1160
add_module_proc(HOOK_PROC, "Fserv", NULL, "*", MSG_LIST, 1, NULL, search_proc);
1161
add_module_proc(HOOK_PROC, "Fserv", NULL, "*", PUBLIC_OTHER_LIST, 1, NULL, search_proc);
1162
1163
add_completion_type("fsload", 3, FILE_COMPLETION);
1164
1165
add_timer(0, empty_string, get_dllint_var("fserv_time"), 1, impress_me, NULL, NULL, -1, "fserv");
1166
strcpy(FSstr, cparse(FS, NULL, NULL));
1167
put_it("%s %s", FSstr, convert_output_format("$0 v$1 by panasync.", "%s %s", fserv_version, AUTO_VERSION));
1168
sprintf(buffer, "$0+%s by panasync - $2 $3", fserv_version);
1169
fset_string_var(FORMAT_VERSION_FSET, buffer);
1170
statistics.starttime = time(NULL);
1171
1172
sprintf(buffer, "%s/fserv.sav", get_string_var(CTOOLZ_DIR_VAR));
1173
fserv_read(buffer);
1174
1175
put_it("%s for help with this fserv, /fshelp", FSstr);
1176
return 0;
1177
}
1178
1179
1180