4 * Server functions which handle file transfers and room directories.
23 #include "sysdep_decls.h"
29 #include "citserver.h"
31 void cmd_delf(char *filename)
36 if (CtdlAccessCheck(ac_room_aide)) return;
38 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
39 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
43 if (strlen(filename)==0) {
44 cprintf("%d You must specify a file name.\n",
45 ERROR+FILE_NOT_FOUND);
48 for (a=0; a<strlen(filename); ++a)
49 if (filename[a]=='/') filename[a] = '_';
50 snprintf(pathname,sizeof pathname,"./files/%s/%s",
51 CC->quickroom.QRdirname,filename);
53 if (a==0) cprintf("%d File '%s' deleted.\n",OK,pathname);
54 else cprintf("%d File '%s' not found.\n",ERROR+FILE_NOT_FOUND,pathname);
61 * move a file from one room directory to another
63 void cmd_movf(char *cmdbuf)
71 struct quickroom qrbuf;
73 extract(filename,cmdbuf,0);
74 extract(newroom,cmdbuf,1);
76 if (CtdlAccessCheck(ac_room_aide)) return;
78 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
79 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
83 if (strlen(filename)==0) {
84 cprintf("%d You must specify a file name.\n",
85 ERROR+FILE_NOT_FOUND);
89 for (a=0; a<strlen(filename); ++a)
90 if (filename[a]=='/') filename[a] = '_';
91 snprintf(pathname,sizeof pathname,"./files/%s/%s",
92 CC->quickroom.QRdirname,filename);
93 if (access(pathname,0)!=0) {
94 cprintf("%d File '%s' not found.\n",
95 ERROR+FILE_NOT_FOUND,pathname);
99 if (getroom(&qrbuf, newroom)!=0) {
100 cprintf("%d '%s' does not exist.\n",
104 if ((qrbuf.QRflags & QR_DIRECTORY) == 0) {
105 cprintf("%d '%s' is not a directory room.\n",
106 ERROR+NOT_HERE,qrbuf.QRname);
109 snprintf(newpath,sizeof newpath,"./files/%s/%s",qrbuf.QRdirname,
111 if (link(pathname,newpath)!=0) {
112 cprintf("%d Couldn't move file: %s\n",ERROR,strerror(errno));
117 /* this is a crude method of copying the file description */
118 snprintf(buf, sizeof buf,
119 "cat ./files/%s/filedir |grep %s >>./files/%s/filedir",
120 CC->quickroom.QRdirname,
124 cprintf("%d File '%s' has been moved.\n",OK,filename);
129 * send a file over the net
131 void cmd_netf(char *cmdbuf)
133 char pathname[SIZ],filename[SIZ],destsys[SIZ],buf[SIZ],outfile[SIZ];
139 extract(filename,cmdbuf,0);
140 extract(destsys,cmdbuf,1);
142 if (CtdlAccessCheck(ac_room_aide)) return;
144 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
145 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
149 if (strlen(filename)==0) {
150 cprintf("%d You must specify a file name.\n",
151 ERROR+FILE_NOT_FOUND);
155 for (a=0; a<strlen(filename); ++a)
156 if (filename[a]=='/') filename[a] = '_';
157 snprintf(pathname,sizeof pathname,"./files/%s/%s",
158 CC->quickroom.QRdirname,filename);
159 if (access(pathname,0)!=0) {
160 cprintf("%d File '%s' not found.\n",
161 ERROR+FILE_NOT_FOUND,pathname);
164 snprintf(buf,sizeof buf,"sysop@%s",destsys);
167 cprintf("%d No such system: '%s'\n",
168 ERROR+NO_SUCH_SYSTEM,destsys);
171 snprintf(outfile, sizeof outfile,
172 "%s/network/spoolin/nsf.%04x.%04x",
173 BBSDIR, getpid(), ++seq);
174 ofp=fopen(outfile,"a");
176 cprintf("%d internal error\n",ERROR);
181 putc(MES_NORMAL,ofp);
183 fprintf(ofp,"Pcit%ld",CC->usersupp.usernum); putc(0,ofp);
185 fprintf(ofp,"T%ld",(long)now); putc(0,ofp);
186 fprintf(ofp,"A%s",CC->usersupp.fullname); putc(0,ofp);
187 fprintf(ofp,"O%s",CC->quickroom.QRname); putc(0,ofp);
188 fprintf(ofp,"N%s",NODENAME); putc(0,ofp);
189 fprintf(ofp,"D%s",destsys); putc(0,ofp);
190 fprintf(ofp,"SFILE"); putc(0,ofp);
194 snprintf(buf,sizeof buf,
195 "cd ./files/%s; uuencode %s <%s 2>/dev/null >>%s",
196 CC->quickroom.QRdirname,filename,filename,outfile);
199 ofp = fopen(outfile,"a");
203 cprintf("%d File '%s' has been sent to %s.\n",OK,filename,destsys);
204 system("nohup ./netproc -i >/dev/null 2>&1 &");
209 * This code is common to all commands which open a file for downloading.
210 * It examines the file and displays the OK result code and some information
211 * about the file. NOTE: this stuff is Unix dependent.
213 void OpenCmdResult(char *filename, char *mime_type) {
218 fstat(fileno(CC->download_fp), &statbuf);
219 filesize = (long) statbuf.st_size;
220 modtime = (time_t) statbuf.st_mtime;
222 cprintf("%d %ld|%ld|%s|%s\n",
223 OK, filesize, modtime, filename, mime_type);
228 * open a file for downloading
230 void cmd_open(char *cmdbuf)
236 extract(filename,cmdbuf,0);
238 if (CtdlAccessCheck(ac_logged_in)) return;
240 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
241 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
245 if (strlen(filename)==0) {
246 cprintf("%d You must specify a file name.\n",
247 ERROR+FILE_NOT_FOUND);
251 if (CC->download_fp != NULL) {
252 cprintf("%d You already have a download file open.\n",ERROR);
256 for (a=0; a<strlen(filename); ++a)
257 if (filename[a]=='/') filename[a] = '_';
259 snprintf(pathname,sizeof pathname,
260 "./files/%s/%s",CC->quickroom.QRdirname,filename);
261 CC->download_fp = fopen(pathname,"r");
263 if (CC->download_fp==NULL) {
264 cprintf("%d cannot open %s: %s\n",
265 ERROR,pathname,strerror(errno));
269 OpenCmdResult(filename, "application/octet-stream");
275 void cmd_oimg(char *cmdbuf)
279 struct usersupp usbuf;
284 extract(filename,cmdbuf,0);
286 if (strlen(filename)==0) {
287 cprintf("%d You must specify a file name.\n",
288 ERROR+FILE_NOT_FOUND);
292 if (CC->download_fp != NULL) {
293 cprintf("%d You already have a download file open.\n",ERROR);
297 if (!strcasecmp(filename, "_userpic_")) {
298 extract(which_user, cmdbuf, 1);
299 if (getuser(&usbuf, which_user) != 0) {
300 cprintf("%d No such user.\n", ERROR+NO_SUCH_USER);
303 snprintf(pathname, sizeof pathname, "./userpics/%ld.gif",
306 else if (!strcasecmp(filename, "_floorpic_")) {
307 which_floor = extract_int(cmdbuf, 1);
308 snprintf(pathname, sizeof pathname, "./images/floor.%d.gif",
311 else if (!strcasecmp(filename, "_roompic_")) {
312 assoc_file_name(pathname, &CC->quickroom, "images");
315 for (a=0; a<strlen(filename); ++a) {
316 filename[a] = tolower(filename[a]);
317 if (filename[a]=='/') filename[a] = '_';
319 snprintf(pathname,sizeof pathname,"./images/%s.gif",filename);
322 CC->download_fp = fopen(pathname,"r");
323 if (CC->download_fp == NULL) {
324 cprintf("%d Cannot open %s: %s\n",
325 ERROR+FILE_NOT_FOUND,pathname,strerror(errno));
329 OpenCmdResult(pathname, "image/gif");
333 * open a file for uploading
335 void cmd_uopn(char *cmdbuf)
339 extract(CC->upl_file,cmdbuf,0);
340 extract(CC->upl_comment,cmdbuf,1);
342 if (CtdlAccessCheck(ac_logged_in)) return;
344 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
345 cprintf("%d No directory in this room.\n",ERROR+NOT_HERE);
349 if (strlen(CC->upl_file)==0) {
350 cprintf("%d You must specify a file name.\n",
351 ERROR+FILE_NOT_FOUND);
355 if (CC->upload_fp != NULL) {
356 cprintf("%d You already have a upload file open.\n",ERROR);
360 for (a=0; a<strlen(CC->upl_file); ++a)
361 if (CC->upl_file[a]=='/') CC->upl_file[a] = '_';
362 snprintf(CC->upl_path,sizeof CC->upl_path,"./files/%s/%s",
363 CC->quickroom.QRdirname,CC->upl_file);
364 snprintf(CC->upl_filedir,sizeof CC->upl_filedir,"./files/%s/filedir",
365 CC->quickroom.QRdirname);
367 CC->upload_fp = fopen(CC->upl_path,"r");
368 if (CC->upload_fp != NULL) {
369 fclose(CC->upload_fp);
370 CC->upload_fp = NULL;
371 cprintf("%d '%s' already exists\n",
372 ERROR+ALREADY_EXISTS,CC->upl_path);
376 CC->upload_fp = fopen(CC->upl_path,"wb");
377 if (CC->upload_fp == NULL) {
378 cprintf("%d Cannot open %s: %s\n",
379 ERROR,CC->upl_path,strerror(errno));
382 cprintf("%d Ok\n",OK);
388 * open an image file for uploading
390 void cmd_uimg(char *cmdbuf)
392 int is_this_for_real;
397 if (num_parms(cmdbuf) < 2) {
398 cprintf("%d Usage error.\n", ERROR);
402 is_this_for_real = extract_int(cmdbuf,0);
403 extract(basenm, cmdbuf, 1);
404 if (CC->upload_fp != NULL) {
405 cprintf("%d You already have an upload file open.\n", ERROR);
409 strcpy(CC->upl_path, "");
411 for (a=0; a<strlen(basenm); ++a) {
412 basenm[a] = tolower(basenm[a]);
413 if (basenm[a]=='/') basenm[a] = '_';
416 if (CC->usersupp.axlevel >= 6) {
417 snprintf(CC->upl_path, sizeof CC->upl_path, "./images/%s",
421 if (!strcasecmp(basenm, "_userpic_")) {
422 snprintf(CC->upl_path, sizeof CC->upl_path,
423 "./userpics/%ld.gif", CC->usersupp.usernum);
426 if ( (!strcasecmp(basenm, "_floorpic_")) && (CC->usersupp.axlevel >= 6) ) {
427 which_floor = extract_int(cmdbuf, 2);
428 snprintf(CC->upl_path, sizeof CC->upl_path,
429 "./images/floor.%d.gif", which_floor);
432 if ( (!strcasecmp(basenm, "_roompic_")) && (is_room_aide()) ) {
433 assoc_file_name(CC->upl_path, &CC->quickroom, "images");
436 if (strlen(CC->upl_path) == 0) {
437 cprintf("%d Higher access required.\n",
438 ERROR+HIGHER_ACCESS_REQUIRED);
442 if (is_this_for_real == 0) {
443 cprintf("%d Ok to send image\n", OK);
447 CC->upload_fp = fopen(CC->upl_path,"wb");
448 if (CC->upload_fp == NULL) {
449 cprintf("%d Cannot open %s: %s\n",
450 ERROR,CC->upl_path,strerror(errno));
453 cprintf("%d Ok\n",OK);
454 CC->upload_type = UPL_IMAGE;
459 * close the download file
461 void cmd_clos(void) {
464 if (CC->download_fp == NULL) {
465 cprintf("%d You don't have a download file open.\n",ERROR);
469 fclose(CC->download_fp);
470 CC->download_fp = NULL;
472 if (CC->dl_is_net == 1) {
474 snprintf(buf,sizeof buf,"%s/network/spoolout/%s",BBSDIR,
479 cprintf("%d Ok\n",OK);
486 void abort_upl(struct CitContext *who)
488 if (who->upload_fp != NULL) {
489 fclose(who->upload_fp);
490 who->upload_fp = NULL;
491 unlink(CC->upl_path);
498 * close the upload file
500 void cmd_ucls(char *cmd)
503 char upload_notice[512];
505 if (CC->upload_fp == NULL) {
506 cprintf("%d You don't have an upload file open.\n",ERROR);
510 fclose(CC->upload_fp);
511 CC->upload_fp = NULL;
513 if ((!strcasecmp(cmd,"1")) && (CC->upload_type != UPL_FILE)) {
514 CC->upload_type = UPL_FILE;
515 cprintf("%d Upload completed.\n", OK);
517 if (CC->upload_type == UPL_NET) {
519 execlp("./netproc", "netproc", "-i", NULL);
527 if (!strcasecmp(cmd,"1")) {
528 cprintf("%d File '%s' saved.\n",OK,CC->upl_path);
529 fp = fopen(CC->upl_filedir,"a");
530 if (fp==NULL) fp=fopen(CC->upl_filedir,"w");
532 fprintf(fp,"%s %s\n",CC->upl_file,CC->upl_comment);
536 /* put together an upload notice */
537 sprintf(upload_notice,
538 "NEW UPLOAD: '%s'\n %s\n",
539 CC->upl_file,CC->upl_comment);
540 quickie_message(CC->curr_user, NULL, CC->quickroom.QRname,
545 cprintf("%d File '%s' aborted.\n",OK,CC->upl_path);
552 * read from the download file
554 void cmd_read(char *cmdbuf)
560 start_pos = extract_long(cmdbuf,0);
561 bytes = extract_int(cmdbuf,1);
563 if (CC->download_fp == NULL) {
564 cprintf("%d You don't have a download file open.\n",ERROR);
569 cprintf("%d You may not read more than 4096 bytes.\n",ERROR);
573 fseek(CC->download_fp,start_pos,0);
574 fread(buf,bytes,1,CC->download_fp);
575 cprintf("%d %d\n",BINARY_FOLLOWS,bytes);
576 client_write(buf, bytes);
582 * write to the upload file
584 void cmd_writ(char *cmdbuf)
589 bytes = extract_int(cmdbuf,0);
591 if (CC->upload_fp == NULL) {
592 cprintf("%d You don't have an upload file open.\n",ERROR);
597 cprintf("%d You may not write more than 4096 bytes.\n",ERROR);
601 cprintf("%d %d\n",SEND_BINARY,bytes);
602 client_read(buf, bytes);
603 fwrite(buf,bytes,1,CC->upload_fp);
609 * cmd_netp() - identify as network poll session
611 void cmd_netp(char *cmdbuf)
615 extract(buf,cmdbuf,1);
616 if (strcasecmp(buf,config.c_net_password)) {
617 cprintf("%d authentication failed\n",ERROR);
620 extract(CC->net_node,cmdbuf,0);
621 cprintf("%d authenticated as network node '%s'\n",OK,CC->net_node);
625 * cmd_ndop() - open a network spool file for downloading
627 void cmd_ndop(char *cmdbuf)
632 if (strlen(CC->net_node)==0) {
633 cprintf("%d Not authenticated as a network node.\n",
634 ERROR+NOT_LOGGED_IN);
638 if (CC->download_fp != NULL) {
639 cprintf("%d You already have a download file open.\n",ERROR);
643 snprintf(pathname,sizeof pathname,"%s/network/spoolout/%s",BBSDIR,
646 /* first open the file in append mode in order to create a
647 * zero-length file if it doesn't already exist
649 CC->download_fp = fopen(pathname,"a");
650 if (CC->download_fp != NULL) fclose(CC->download_fp);
653 CC->download_fp = fopen(pathname,"r");
654 if (CC->download_fp==NULL) {
655 cprintf("%d cannot open %s: %s\n",
656 ERROR,pathname,strerror(errno));
661 /* set this flag so other routines know that the download file
662 * currently open is a network spool file
666 stat(pathname,&statbuf);
667 cprintf("%d %ld\n",OK,statbuf.st_size);
671 * cmd_nuop() - open a network spool file for uploading
673 void cmd_nuop(char *cmdbuf)
677 if (strlen(CC->net_node)==0) {
678 cprintf("%d Not authenticated as a network node.\n",
679 ERROR+NOT_LOGGED_IN);
683 if (CC->upload_fp != NULL) {
684 cprintf("%d You already have an upload file open.\n",ERROR);
688 snprintf(CC->upl_path, sizeof CC->upl_path,
689 "%s/network/spoolin/%s.%04x.%04x",
690 BBSDIR, CC->net_node, getpid(), ++seq);
692 CC->upload_fp = fopen(CC->upl_path,"r");
693 if (CC->upload_fp != NULL) {
694 fclose(CC->upload_fp);
695 CC->upload_fp = NULL;
696 cprintf("%d '%s' already exists\n",
697 ERROR+ALREADY_EXISTS,CC->upl_path);
701 CC->upload_fp = fopen(CC->upl_path,"w");
702 if (CC->upload_fp == NULL) {
703 cprintf("%d Cannot open %s: %s\n",
704 ERROR,CC->upl_path,strerror(errno));
708 CC->upload_type = UPL_NET;
709 cprintf("%d Ok\n",OK);