4 * Server functions which handle file transfers and room directories.
18 #if TIME_WITH_SYS_TIME
19 # include <sys/time.h>
23 # include <sys/time.h>
34 #include "sysdep_decls.h"
40 #include "citserver.h"
42 void cmd_delf(char *filename)
47 if (CtdlAccessCheck(ac_room_aide)) return;
49 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
50 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
54 if (strlen(filename)==0) {
55 cprintf("%d You must specify a file name.\n",
56 ERROR+FILE_NOT_FOUND);
59 for (a=0; a<strlen(filename); ++a)
60 if (filename[a]=='/') filename[a] = '_';
61 snprintf(pathname,sizeof pathname,"./files/%s/%s",
62 CC->quickroom.QRdirname,filename);
64 if (a==0) cprintf("%d File '%s' deleted.\n",OK,pathname);
65 else cprintf("%d File '%s' not found.\n",ERROR+FILE_NOT_FOUND,pathname);
72 * move a file from one room directory to another
74 void cmd_movf(char *cmdbuf)
82 struct quickroom qrbuf;
84 extract(filename,cmdbuf,0);
85 extract(newroom,cmdbuf,1);
87 if (CtdlAccessCheck(ac_room_aide)) return;
89 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
90 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
94 if (strlen(filename)==0) {
95 cprintf("%d You must specify a file name.\n",
96 ERROR+FILE_NOT_FOUND);
100 for (a=0; a<strlen(filename); ++a)
101 if (filename[a]=='/') filename[a] = '_';
102 snprintf(pathname,sizeof pathname,"./files/%s/%s",
103 CC->quickroom.QRdirname,filename);
104 if (access(pathname,0)!=0) {
105 cprintf("%d File '%s' not found.\n",
106 ERROR+FILE_NOT_FOUND,pathname);
110 if (getroom(&qrbuf, newroom)!=0) {
111 cprintf("%d '%s' does not exist.\n",
115 if ((qrbuf.QRflags & QR_DIRECTORY) == 0) {
116 cprintf("%d '%s' is not a directory room.\n",
117 ERROR+NOT_HERE,qrbuf.QRname);
120 snprintf(newpath,sizeof newpath,"./files/%s/%s",qrbuf.QRdirname,
122 if (link(pathname,newpath)!=0) {
123 cprintf("%d Couldn't move file: %s\n",ERROR,strerror(errno));
128 /* this is a crude method of copying the file description */
129 snprintf(buf, sizeof buf,
130 "cat ./files/%s/filedir |grep %s >>./files/%s/filedir",
131 CC->quickroom.QRdirname,
135 cprintf("%d File '%s' has been moved.\n",OK,filename);
140 * send a file over the net
142 void cmd_netf(char *cmdbuf)
144 char pathname[SIZ],filename[SIZ],destsys[SIZ],buf[SIZ],outfile[SIZ];
150 extract(filename,cmdbuf,0);
151 extract(destsys,cmdbuf,1);
153 if (CtdlAccessCheck(ac_room_aide)) return;
155 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
156 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
160 if (strlen(filename)==0) {
161 cprintf("%d You must specify a file name.\n",
162 ERROR+FILE_NOT_FOUND);
166 for (a=0; a<strlen(filename); ++a)
167 if (filename[a]=='/') filename[a] = '_';
168 snprintf(pathname,sizeof pathname,"./files/%s/%s",
169 CC->quickroom.QRdirname,filename);
170 if (access(pathname,0)!=0) {
171 cprintf("%d File '%s' not found.\n",
172 ERROR+FILE_NOT_FOUND,pathname);
175 snprintf(buf,sizeof buf,"sysop@%s",destsys);
178 cprintf("%d No such system: '%s'\n",
179 ERROR+NO_SUCH_SYSTEM,destsys);
182 snprintf(outfile, sizeof outfile,
183 "%s/network/spoolin/nsf.%04x.%04x",
184 BBSDIR, getpid(), ++seq);
185 ofp=fopen(outfile,"a");
187 cprintf("%d internal error\n",ERROR);
192 putc(MES_NORMAL,ofp);
194 fprintf(ofp,"Pcit%ld",CC->usersupp.usernum); putc(0,ofp);
196 fprintf(ofp,"T%ld",(long)now); putc(0,ofp);
197 fprintf(ofp,"A%s",CC->usersupp.fullname); putc(0,ofp);
198 fprintf(ofp,"O%s",CC->quickroom.QRname); putc(0,ofp);
199 fprintf(ofp,"N%s",NODENAME); putc(0,ofp);
200 fprintf(ofp,"D%s",destsys); putc(0,ofp);
201 fprintf(ofp,"SFILE"); putc(0,ofp);
205 snprintf(buf,sizeof buf,
206 "cd ./files/%s; uuencode %s <%s 2>/dev/null >>%s",
207 CC->quickroom.QRdirname,filename,filename,outfile);
210 ofp = fopen(outfile,"a");
214 cprintf("%d File '%s' has been sent to %s.\n",OK,filename,destsys);
215 system("nohup ./netproc -i >/dev/null 2>&1 &");
220 * This code is common to all commands which open a file for downloading.
221 * It examines the file and displays the OK result code and some information
222 * about the file. NOTE: this stuff is Unix dependent.
224 void OpenCmdResult(char *filename, char *mime_type) {
229 fstat(fileno(CC->download_fp), &statbuf);
230 filesize = (long) statbuf.st_size;
231 modtime = (time_t) statbuf.st_mtime;
233 cprintf("%d %ld|%ld|%s|%s\n",
234 OK, filesize, modtime, filename, mime_type);
239 * open a file for downloading
241 void cmd_open(char *cmdbuf)
247 extract(filename,cmdbuf,0);
249 if (CtdlAccessCheck(ac_logged_in)) return;
251 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
252 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
256 if (strlen(filename)==0) {
257 cprintf("%d You must specify a file name.\n",
258 ERROR+FILE_NOT_FOUND);
262 if (CC->download_fp != NULL) {
263 cprintf("%d You already have a download file open.\n",ERROR);
267 for (a=0; a<strlen(filename); ++a)
268 if (filename[a]=='/') filename[a] = '_';
270 snprintf(pathname,sizeof pathname,
271 "./files/%s/%s",CC->quickroom.QRdirname,filename);
272 CC->download_fp = fopen(pathname,"r");
274 if (CC->download_fp==NULL) {
275 cprintf("%d cannot open %s: %s\n",
276 ERROR,pathname,strerror(errno));
280 OpenCmdResult(filename, "application/octet-stream");
286 void cmd_oimg(char *cmdbuf)
290 struct usersupp usbuf;
295 extract(filename,cmdbuf,0);
297 if (strlen(filename)==0) {
298 cprintf("%d You must specify a file name.\n",
299 ERROR+FILE_NOT_FOUND);
303 if (CC->download_fp != NULL) {
304 cprintf("%d You already have a download file open.\n",ERROR);
308 if (!strcasecmp(filename, "_userpic_")) {
309 extract(which_user, cmdbuf, 1);
310 if (getuser(&usbuf, which_user) != 0) {
311 cprintf("%d No such user.\n", ERROR+NO_SUCH_USER);
314 snprintf(pathname, sizeof pathname, "./userpics/%ld.gif",
317 else if (!strcasecmp(filename, "_floorpic_")) {
318 which_floor = extract_int(cmdbuf, 1);
319 snprintf(pathname, sizeof pathname, "./images/floor.%d.gif",
322 else if (!strcasecmp(filename, "_roompic_")) {
323 assoc_file_name(pathname, &CC->quickroom, "images");
326 for (a=0; a<strlen(filename); ++a) {
327 filename[a] = tolower(filename[a]);
328 if (filename[a]=='/') filename[a] = '_';
330 snprintf(pathname,sizeof pathname,"./images/%s.gif",filename);
333 CC->download_fp = fopen(pathname,"r");
334 if (CC->download_fp == NULL) {
335 cprintf("%d Cannot open %s: %s\n",
336 ERROR+FILE_NOT_FOUND,pathname,strerror(errno));
340 OpenCmdResult(pathname, "image/gif");
344 * open a file for uploading
346 void cmd_uopn(char *cmdbuf)
350 extract(CC->upl_file,cmdbuf,0);
351 extract(CC->upl_comment,cmdbuf,1);
353 if (CtdlAccessCheck(ac_logged_in)) return;
355 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
356 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
360 if (strlen(CC->upl_file)==0) {
361 cprintf("%d You must specify a file name.\n",
362 ERROR+FILE_NOT_FOUND);
366 if (CC->upload_fp != NULL) {
367 cprintf("%d You already have a upload file open.\n",ERROR);
371 for (a=0; a<strlen(CC->upl_file); ++a)
372 if (CC->upl_file[a]=='/') CC->upl_file[a] = '_';
373 snprintf(CC->upl_path,sizeof CC->upl_path,"./files/%s/%s",
374 CC->quickroom.QRdirname,CC->upl_file);
375 snprintf(CC->upl_filedir,sizeof CC->upl_filedir,"./files/%s/filedir",
376 CC->quickroom.QRdirname);
378 CC->upload_fp = fopen(CC->upl_path,"r");
379 if (CC->upload_fp != NULL) {
380 fclose(CC->upload_fp);
381 CC->upload_fp = NULL;
382 cprintf("%d '%s' already exists\n",
383 ERROR+ALREADY_EXISTS,CC->upl_path);
387 CC->upload_fp = fopen(CC->upl_path,"wb");
388 if (CC->upload_fp == NULL) {
389 cprintf("%d Cannot open %s: %s\n",
390 ERROR,CC->upl_path,strerror(errno));
393 cprintf("%d Ok\n",OK);
399 * open an image file for uploading
401 void cmd_uimg(char *cmdbuf)
403 int is_this_for_real;
408 if (num_parms(cmdbuf) < 2) {
409 cprintf("%d Usage error.\n", ERROR);
413 is_this_for_real = extract_int(cmdbuf,0);
414 extract(basenm, cmdbuf, 1);
415 if (CC->upload_fp != NULL) {
416 cprintf("%d You already have an upload file open.\n", ERROR);
420 strcpy(CC->upl_path, "");
422 for (a=0; a<strlen(basenm); ++a) {
423 basenm[a] = tolower(basenm[a]);
424 if (basenm[a]=='/') basenm[a] = '_';
427 if (CC->usersupp.axlevel >= 6) {
428 snprintf(CC->upl_path, sizeof CC->upl_path, "./images/%s",
432 if (!strcasecmp(basenm, "_userpic_")) {
433 snprintf(CC->upl_path, sizeof CC->upl_path,
434 "./userpics/%ld.gif", CC->usersupp.usernum);
437 if ( (!strcasecmp(basenm, "_floorpic_")) && (CC->usersupp.axlevel >= 6) ) {
438 which_floor = extract_int(cmdbuf, 2);
439 snprintf(CC->upl_path, sizeof CC->upl_path,
440 "./images/floor.%d.gif", which_floor);
443 if ( (!strcasecmp(basenm, "_roompic_")) && (is_room_aide()) ) {
444 assoc_file_name(CC->upl_path, &CC->quickroom, "images");
447 if (strlen(CC->upl_path) == 0) {
448 cprintf("%d Higher access required.\n",
449 ERROR+HIGHER_ACCESS_REQUIRED);
453 if (is_this_for_real == 0) {
454 cprintf("%d Ok to send image\n", OK);
458 CC->upload_fp = fopen(CC->upl_path,"wb");
459 if (CC->upload_fp == NULL) {
460 cprintf("%d Cannot open %s: %s\n",
461 ERROR,CC->upl_path,strerror(errno));
464 cprintf("%d Ok\n",OK);
465 CC->upload_type = UPL_IMAGE;
470 * close the download file
472 void cmd_clos(void) {
475 if (CC->download_fp == NULL) {
476 cprintf("%d You don't have a download file open.\n",ERROR);
480 fclose(CC->download_fp);
481 CC->download_fp = NULL;
483 if (CC->dl_is_net == 1) {
485 snprintf(buf,sizeof buf,"%s/network/spoolout/%s",BBSDIR,
490 cprintf("%d Ok\n",OK);
497 void abort_upl(struct CitContext *who)
499 if (who->upload_fp != NULL) {
500 fclose(who->upload_fp);
501 who->upload_fp = NULL;
502 unlink(CC->upl_path);
509 * close the upload file
511 void cmd_ucls(char *cmd)
514 char upload_notice[512];
516 if (CC->upload_fp == NULL) {
517 cprintf("%d You don't have an upload file open.\n",ERROR);
521 fclose(CC->upload_fp);
522 CC->upload_fp = NULL;
524 if ((!strcasecmp(cmd,"1")) && (CC->upload_type != UPL_FILE)) {
525 CC->upload_type = UPL_FILE;
526 cprintf("%d Upload completed.\n", OK);
528 if (CC->upload_type == UPL_NET) {
530 execlp("./netproc", "netproc", "-i", NULL);
538 if (!strcasecmp(cmd,"1")) {
539 cprintf("%d File '%s' saved.\n",OK,CC->upl_path);
540 fp = fopen(CC->upl_filedir,"a");
541 if (fp==NULL) fp=fopen(CC->upl_filedir,"w");
543 fprintf(fp,"%s %s\n",CC->upl_file,CC->upl_comment);
547 /* put together an upload notice */
548 sprintf(upload_notice,
549 "NEW UPLOAD: '%s'\n %s\n",
550 CC->upl_file,CC->upl_comment);
551 quickie_message(CC->curr_user, NULL, CC->quickroom.QRname,
556 cprintf("%d File '%s' aborted.\n",OK,CC->upl_path);
563 * read from the download file
565 void cmd_read(char *cmdbuf)
571 start_pos = extract_long(cmdbuf,0);
572 bytes = extract_int(cmdbuf,1);
574 if (CC->download_fp == NULL) {
575 cprintf("%d You don't have a download file open.\n",ERROR);
580 cprintf("%d You may not read more than 4096 bytes.\n",ERROR);
584 fseek(CC->download_fp,start_pos,0);
585 fread(buf,bytes,1,CC->download_fp);
586 cprintf("%d %d\n",BINARY_FOLLOWS,bytes);
587 client_write(buf, bytes);
593 * write to the upload file
595 void cmd_writ(char *cmdbuf)
600 bytes = extract_int(cmdbuf,0);
602 if (CC->upload_fp == NULL) {
603 cprintf("%d You don't have an upload file open.\n",ERROR);
608 cprintf("%d You may not write more than 4096 bytes.\n",ERROR);
612 cprintf("%d %d\n",SEND_BINARY,bytes);
613 client_read(buf, bytes);
614 fwrite(buf,bytes,1,CC->upload_fp);
620 * cmd_netp() - identify as network poll session
622 void cmd_netp(char *cmdbuf)
626 extract(buf,cmdbuf,1);
627 if (strcasecmp(buf,config.c_net_password)) {
628 cprintf("%d authentication failed\n",ERROR);
631 extract(CC->net_node,cmdbuf,0);
632 cprintf("%d authenticated as network node '%s'\n",OK,CC->net_node);
636 * cmd_ndop() - open a network spool file for downloading
638 void cmd_ndop(char *cmdbuf)
643 if (strlen(CC->net_node)==0) {
644 cprintf("%d Not authenticated as a network node.\n",
645 ERROR+NOT_LOGGED_IN);
649 if (CC->download_fp != NULL) {
650 cprintf("%d You already have a download file open.\n",ERROR);
654 snprintf(pathname,sizeof pathname,"%s/network/spoolout/%s",BBSDIR,
657 /* first open the file in append mode in order to create a
658 * zero-length file if it doesn't already exist
660 CC->download_fp = fopen(pathname,"a");
661 if (CC->download_fp != NULL) fclose(CC->download_fp);
664 CC->download_fp = fopen(pathname,"r");
665 if (CC->download_fp==NULL) {
666 cprintf("%d cannot open %s: %s\n",
667 ERROR,pathname,strerror(errno));
672 /* set this flag so other routines know that the download file
673 * currently open is a network spool file
677 stat(pathname,&statbuf);
678 cprintf("%d %ld\n",OK,statbuf.st_size);
682 * cmd_nuop() - open a network spool file for uploading
684 void cmd_nuop(char *cmdbuf)
688 if (strlen(CC->net_node)==0) {
689 cprintf("%d Not authenticated as a network node.\n",
690 ERROR+NOT_LOGGED_IN);
694 if (CC->upload_fp != NULL) {
695 cprintf("%d You already have an upload file open.\n",ERROR);
699 snprintf(CC->upl_path, sizeof CC->upl_path,
700 "%s/network/spoolin/%s.%04x.%04x",
701 BBSDIR, CC->net_node, getpid(), ++seq);
703 CC->upload_fp = fopen(CC->upl_path,"r");
704 if (CC->upload_fp != NULL) {
705 fclose(CC->upload_fp);
706 CC->upload_fp = NULL;
707 cprintf("%d '%s' already exists\n",
708 ERROR+ALREADY_EXISTS,CC->upl_path);
712 CC->upload_fp = fopen(CC->upl_path,"w");
713 if (CC->upload_fp == NULL) {
714 cprintf("%d Cannot open %s: %s\n",
715 ERROR,CC->upl_path,strerror(errno));
719 CC->upload_type = UPL_NET;
720 cprintf("%d Ok\n",OK);