1424e33e18aec2b64572befe4cf276502d6b9dcf
[citadel.git] / citadel / file_ops.c
1 /* 
2  * $Id$
3  *
4  * Server functions which handle file transfers and room directories.
5  *
6  */
7
8 #include "sysdep.h"
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <stdio.h>
12 #include <fcntl.h>
13 #include <sys/stat.h>
14 #include <errno.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <sys/stat.h>
18
19 #if TIME_WITH_SYS_TIME
20 # include <sys/time.h>
21 # include <time.h>
22 #else
23 # if HAVE_SYS_TIME_H
24 #  include <sys/time.h>
25 # else
26 #  include <time.h>
27 # endif
28 #endif
29
30 #include <limits.h>
31 #include <libcitadel.h>
32 #include "citadel.h"
33 #include "server.h"
34 #include "config.h"
35 #include "file_ops.h"
36 #include "sysdep_decls.h"
37 #include "user_ops.h"
38 #include "support.h"
39 #include "room_ops.h"
40 #include "msgbase.h"
41 #include "citserver.h"
42 #include "threads.h"
43
44 #ifndef HAVE_SNPRINTF
45 #include "snprintf.h"
46 #endif
47
48 /*
49  * network_talking_to()  --  concurrency checker
50  */
51 int network_talking_to(char *nodename, int operation) {
52
53         static char *nttlist = NULL;
54         char *ptr = NULL;
55         int i;
56         char buf[SIZ];
57         int retval = 0;
58
59         begin_critical_section(S_NTTLIST);
60
61         switch(operation) {
62
63                 case NTT_ADD:
64                         if (nttlist == NULL) nttlist = strdup("");
65                         if (nttlist == NULL) break;
66                         nttlist = (char *)realloc(nttlist,
67                                 (strlen(nttlist) + strlen(nodename) + 3) );
68                         strcat(nttlist, "|");
69                         strcat(nttlist, nodename);
70                         break;
71
72                 case NTT_REMOVE:
73                         if (nttlist == NULL) break;
74                         if (IsEmptyStr(nttlist)) break;
75                         ptr = malloc(strlen(nttlist));
76                         if (ptr == NULL) break;
77                         strcpy(ptr, "");
78                         for (i = 0; i < num_tokens(nttlist, '|'); ++i) {
79                                 extract_token(buf, nttlist, i, '|', sizeof buf);
80                                 if ( (!IsEmptyStr(buf))
81                                      && (strcasecmp(buf, nodename)) ) {
82                                                 strcat(ptr, buf);
83                                                 strcat(ptr, "|");
84                                 }
85                         }
86                         free(nttlist);
87                         nttlist = ptr;
88                         break;
89
90                 case NTT_CHECK:
91                         if (nttlist == NULL) break;
92                         if (IsEmptyStr(nttlist)) break;
93                         for (i = 0; i < num_tokens(nttlist, '|'); ++i) {
94                                 extract_token(buf, nttlist, i, '|', sizeof buf);
95                                 if (!strcasecmp(buf, nodename)) ++retval;
96                         }
97                         break;
98         }
99
100         if (nttlist != NULL) CtdlLogPrintf(CTDL_DEBUG, "nttlist=<%s>\n", nttlist);
101         end_critical_section(S_NTTLIST);
102         return(retval);
103 }
104
105
106
107
108 /*
109  * Server command to delete a file from a room's directory
110  */
111 void cmd_delf(char *filename)
112 {
113         char pathname[64];
114         int a;
115
116         if (CtdlAccessCheck(ac_room_aide))
117                 return;
118
119         if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
120                 cprintf("%d No directory in this room.\n",
121                         ERROR + NOT_HERE);
122                 return;
123         }
124
125         if (IsEmptyStr(filename)) {
126                 cprintf("%d You must specify a file name.\n",
127                         ERROR + FILE_NOT_FOUND);
128                 return;
129         }
130         for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
131                 if ( (filename[a] == '/') || (filename[a] == '\\') ) {
132                         filename[a] = '_';
133                 }
134         }
135         snprintf(pathname, sizeof pathname,
136                          "%s/%s/%s",
137                          ctdl_file_dir,
138                          CC->room.QRdirname, filename);
139         a = unlink(pathname);
140         if (a == 0) {
141                 cprintf("%d File '%s' deleted.\n", CIT_OK, pathname);
142         }
143         else {
144                 cprintf("%d File '%s' not found.\n",
145                         ERROR + FILE_NOT_FOUND, pathname);
146         }
147 }
148
149
150
151
152 /*
153  * move a file from one room directory to another
154  */
155 void cmd_movf(char *cmdbuf)
156 {
157         char filename[PATH_MAX];
158         char pathname[PATH_MAX];
159         char newpath[PATH_MAX];
160         char newroom[ROOMNAMELEN];
161         char buf[PATH_MAX];
162         int a;
163         struct ctdlroom qrbuf;
164
165         extract_token(filename, cmdbuf, 0, '|', sizeof filename);
166         extract_token(newroom, cmdbuf, 1, '|', sizeof newroom);
167
168         if (CtdlAccessCheck(ac_room_aide)) return;
169
170         if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
171                 cprintf("%d No directory in this room.\n",
172                         ERROR + NOT_HERE);
173                 return;
174         }
175
176         if (IsEmptyStr(filename)) {
177                 cprintf("%d You must specify a file name.\n",
178                         ERROR + FILE_NOT_FOUND);
179                 return;
180         }
181
182         for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
183                 if ( (filename[a] == '/') || (filename[a] == '\\') ) {
184                         filename[a] = '_';
185                 }
186         }
187         snprintf(pathname, sizeof pathname, "./files/%s/%s",
188                  CC->room.QRdirname, filename);
189         if (access(pathname, 0) != 0) {
190                 cprintf("%d File '%s' not found.\n",
191                         ERROR + FILE_NOT_FOUND, pathname);
192                 return;
193         }
194
195         if (getroom(&qrbuf, newroom) != 0) {
196                 cprintf("%d '%s' does not exist.\n", ERROR + ROOM_NOT_FOUND, newroom);
197                 return;
198         }
199         if ((qrbuf.QRflags & QR_DIRECTORY) == 0) {
200                 cprintf("%d '%s' is not a directory room.\n",
201                         ERROR + NOT_HERE, qrbuf.QRname);
202                 return;
203         }
204         snprintf(newpath, sizeof newpath, "./files/%s/%s", qrbuf.QRdirname,
205                  filename);
206         if (link(pathname, newpath) != 0) {
207                 cprintf("%d Couldn't move file: %s\n", ERROR + INTERNAL_ERROR,
208                         strerror(errno));
209                 return;
210         }
211         unlink(pathname);
212
213         /* this is a crude method of copying the file description */
214         snprintf(buf, sizeof buf,
215                  "cat ./files/%s/filedir |grep \"%s\" >>./files/%s/filedir",
216                  CC->room.QRdirname, filename, qrbuf.QRdirname);
217         system(buf);
218         cprintf("%d File '%s' has been moved.\n", CIT_OK, filename);
219 }
220
221
222 /*
223  * This code is common to all commands which open a file for downloading,
224  * regardless of whether it's a file from the directory, an image, a network
225  * spool file, a MIME attachment, etc.
226  * It examines the file and displays the OK result code and some information
227  * about the file.  NOTE: this stuff is Unix dependent.
228  */
229 void OpenCmdResult(char *filename, const char *mime_type)
230 {
231         struct stat statbuf;
232         time_t modtime;
233         long filesize;
234
235         fstat(fileno(CC->download_fp), &statbuf);
236         filesize = (long) statbuf.st_size;
237         modtime = (time_t) statbuf.st_mtime;
238
239         cprintf("%d %ld|%ld|%s|%s\n",
240                 CIT_OK, filesize, (long)modtime, filename, mime_type);
241 }
242
243
244 /*
245  * open a file for downloading
246  */
247 void cmd_open(char *cmdbuf)
248 {
249         char filename[256];
250         char pathname[PATH_MAX];
251         int a;
252
253         extract_token(filename, cmdbuf, 0, '|', sizeof filename);
254
255         if (CtdlAccessCheck(ac_logged_in)) return;
256
257         if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
258                 cprintf("%d No directory in this room.\n",
259                         ERROR + NOT_HERE);
260                 return;
261         }
262
263         if (IsEmptyStr(filename)) {
264                 cprintf("%d You must specify a file name.\n",
265                         ERROR + FILE_NOT_FOUND);
266                 return;
267         }
268
269         if (CC->download_fp != NULL) {
270                 cprintf("%d You already have a download file open.\n",
271                         ERROR + RESOURCE_BUSY);
272                 return;
273         }
274
275         for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
276                 if ( (filename[a] == '/') || (filename[a] == '\\') ) {
277                         filename[a] = '_';
278                 }
279         }
280
281         snprintf(pathname, sizeof pathname,
282                          "%s/%s/%s",
283                          ctdl_file_dir,
284                          CC->room.QRdirname, filename);
285         CC->download_fp = fopen(pathname, "r");
286
287         if (CC->download_fp == NULL) {
288                 cprintf("%d cannot open %s: %s\n",
289                         ERROR + INTERNAL_ERROR, pathname, strerror(errno));
290                 return;
291         }
292
293         OpenCmdResult(filename, "application/octet-stream");
294 }
295
296 /*
297  * open an image file
298  */
299 void cmd_oimg(char *cmdbuf)
300 {
301         char filename[256];
302         char pathname[PATH_MAX];
303         char MimeTestBuf[32];
304         struct ctdluser usbuf;
305         char which_user[USERNAME_SIZE];
306         int which_floor;
307         int a;
308
309         extract_token(filename, cmdbuf, 0, '|', sizeof filename);
310
311         if (IsEmptyStr(filename)) {
312                 cprintf("%d You must specify a file name.\n",
313                         ERROR + FILE_NOT_FOUND);
314                 return;
315         }
316
317         if (CC->download_fp != NULL) {
318                 cprintf("%d You already have a download file open.\n",
319                         ERROR + RESOURCE_BUSY);
320                 return;
321         }
322
323         if (!strcasecmp(filename, "_userpic_")) {
324                 extract_token(which_user, cmdbuf, 1, '|', sizeof which_user);
325                 if (getuser(&usbuf, which_user) != 0) {
326                         cprintf("%d No such user.\n",
327                                 ERROR + NO_SUCH_USER);
328                         return;
329                 }
330                 snprintf(pathname, sizeof pathname, 
331                                  "%s/%ld",
332                                  ctdl_usrpic_dir,
333                                  usbuf.usernum);
334         } else if (!strcasecmp(filename, "_floorpic_")) {
335                 which_floor = extract_int(cmdbuf, 1);
336                 snprintf(pathname, sizeof pathname,
337                                  "%s/floor.%d",
338                                  ctdl_image_dir, which_floor);
339         } else if (!strcasecmp(filename, "_roompic_")) {
340                 assoc_file_name(pathname, sizeof pathname, &CC->room, ctdl_image_dir);
341         } else {
342                 for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
343                         filename[a] = tolower(filename[a]);
344                         if ( (filename[a] == '/') || (filename[a] == '\\') ) {
345                                 filename[a] = '_';
346                         }
347                 }
348                 snprintf(pathname, sizeof pathname,
349                                  "%s/%s",
350                                  ctdl_image_dir,
351                                  filename);
352         }
353
354         CC->download_fp = fopen(pathname, "rb");
355         if (CC->download_fp == NULL) {
356                 strcat(pathname, ".gif");
357                 CC->download_fp = fopen(pathname, "rb");
358         }
359         if (CC->download_fp == NULL) {
360                 cprintf("%d Cannot open %s: %s\n",
361                         ERROR + FILE_NOT_FOUND, pathname, strerror(errno));
362                 return;
363         }
364         fread(&MimeTestBuf[0], 1, 32, CC->download_fp);
365         rewind (CC->download_fp);
366         OpenCmdResult(pathname, GuessMimeType(&MimeTestBuf[0], 32));
367 }
368
369 /*
370  * open a file for uploading
371  */
372 void cmd_uopn(char *cmdbuf)
373 {
374         int a;
375
376         extract_token(CC->upl_file, cmdbuf, 0, '|', sizeof CC->upl_file);
377         extract_token(CC->upl_mimetype, cmdbuf, 1, '|', sizeof CC->upl_mimetype);
378         extract_token(CC->upl_comment, cmdbuf, 2, '|', sizeof CC->upl_comment);
379
380         if (CtdlAccessCheck(ac_logged_in)) return;
381
382         if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
383                 cprintf("%d No directory in this room.\n",
384                         ERROR + NOT_HERE);
385                 return;
386         }
387
388         if (IsEmptyStr(CC->upl_file)) {
389                 cprintf("%d You must specify a file name.\n",
390                         ERROR + FILE_NOT_FOUND);
391                 return;
392         }
393
394         if (CC->upload_fp != NULL) {
395                 cprintf("%d You already have a upload file open.\n",
396                         ERROR + RESOURCE_BUSY);
397                 return;
398         }
399
400         for (a = 0; !IsEmptyStr(&CC->upl_file[a]); ++a) {
401                 if ( (CC->upl_file[a] == '/') || (CC->upl_file[a] == '\\') ) {
402                         CC->upl_file[a] = '_';
403                 }
404         }
405         snprintf(CC->upl_path, sizeof CC->upl_path, 
406                          "%s/%s/%s",
407                          ctdl_file_dir,
408                          CC->room.QRdirname, CC->upl_file);
409         snprintf(CC->upl_filedir, sizeof CC->upl_filedir,
410                          "%s/%s/filedir", 
411                          ctdl_file_dir,
412                          CC->room.QRdirname);
413
414         CC->upload_fp = fopen(CC->upl_path, "r");
415         if (CC->upload_fp != NULL) {
416                 fclose(CC->upload_fp);
417                 CC->upload_fp = NULL;
418                 cprintf("%d '%s' already exists\n",
419                         ERROR + ALREADY_EXISTS, CC->upl_path);
420                 return;
421         }
422
423         CC->upload_fp = fopen(CC->upl_path, "wb");
424         if (CC->upload_fp == NULL) {
425                 cprintf("%d Cannot open %s: %s\n",
426                         ERROR + INTERNAL_ERROR, CC->upl_path, strerror(errno));
427                 return;
428         }
429         cprintf("%d Ok\n", CIT_OK);
430 }
431
432
433
434 /*
435  * open an image file for uploading
436  */
437 void cmd_uimg(char *cmdbuf)
438 {
439         int is_this_for_real;
440         char basenm[256];
441         int which_floor;
442         int a;
443
444         if (num_parms(cmdbuf) < 2) {
445                 cprintf("%d Usage error.\n", ERROR + ILLEGAL_VALUE);
446                 return;
447         }
448
449         is_this_for_real = extract_int(cmdbuf, 0);
450         extract_token(CC->upl_mimetype, cmdbuf, 1, '|', sizeof CC->upl_mimetype);
451         extract_token(basenm, cmdbuf, 2, '|', sizeof basenm);
452         if (CC->upload_fp != NULL) {
453                 cprintf("%d You already have an upload file open.\n",
454                         ERROR + RESOURCE_BUSY);
455                 return;
456         }
457
458         strcpy(CC->upl_path, "");
459
460         for (a = 0; !IsEmptyStr(&basenm[a]); ++a) {
461                 basenm[a] = tolower(basenm[a]);
462                 if ( (basenm[a] == '/') || (basenm[a] == '\\') ) {
463                         basenm[a] = '_';
464                 }
465         }
466
467         if (CC->user.axlevel >= 6) {
468                 snprintf(CC->upl_path, sizeof CC->upl_path, 
469                                  "%s/%s",
470                                  ctdl_image_dir,
471                                  basenm);
472         }
473
474         if (!strcasecmp(basenm, "_userpic_")) {
475                 snprintf(CC->upl_path, sizeof CC->upl_path,
476                                  "%s/%ld.gif",
477                                  ctdl_usrpic_dir,
478                                  CC->user.usernum);
479         }
480
481         if ((!strcasecmp(basenm, "_floorpic_"))
482             && (CC->user.axlevel >= 6)) {
483                 which_floor = extract_int(cmdbuf, 2);
484                 snprintf(CC->upl_path, sizeof CC->upl_path,
485                                  "%s/floor.%d.gif",
486                                  ctdl_image_dir,
487                                  which_floor);
488         }
489
490         if ((!strcasecmp(basenm, "_roompic_")) && (is_room_aide())) {
491                 assoc_file_name(CC->upl_path, sizeof CC->upl_path, &CC->room, ctdl_image_dir);
492         }
493
494         if (IsEmptyStr(CC->upl_path)) {
495                 cprintf("%d Higher access required.\n",
496                         ERROR + HIGHER_ACCESS_REQUIRED);
497                 return;
498         }
499
500         if (is_this_for_real == 0) {
501                 cprintf("%d Ok to send image\n", CIT_OK);
502                 return;
503         }
504
505         CC->upload_fp = fopen(CC->upl_path, "wb");
506         if (CC->upload_fp == NULL) {
507                 cprintf("%d Cannot open %s: %s\n",
508                         ERROR + INTERNAL_ERROR, CC->upl_path, strerror(errno));
509                 return;
510         }
511         cprintf("%d Ok\n", CIT_OK);
512         CC->upload_type = UPL_IMAGE;
513 }
514
515
516 /*
517  * close the download file
518  */
519 void cmd_clos(void)
520 {
521         char buf[256];
522
523         if (CC->download_fp == NULL) {
524                 cprintf("%d You don't have a download file open.\n",
525                         ERROR + RESOURCE_NOT_OPEN);
526                 return;
527         }
528
529         fclose(CC->download_fp);
530         CC->download_fp = NULL;
531
532         if (CC->dl_is_net == 1) {
533                 CC->dl_is_net = 0;
534                 snprintf(buf, sizeof buf, 
535                                  "%s/%s",
536                                  ctdl_netout_dir,
537                                  CC->net_node);
538                 unlink(buf);
539         }
540
541         cprintf("%d Ok\n", CIT_OK);
542 }
543
544
545 /*
546  * abort an upload
547  */
548 void abort_upl(struct CitContext *who)
549 {
550         if (who->upload_fp != NULL) {
551                 fclose(who->upload_fp);
552                 who->upload_fp = NULL;
553                 unlink(CC->upl_path);
554         }
555 }
556
557
558
559 /*
560  * close the upload file
561  */
562 void cmd_ucls(char *cmd)
563 {
564         FILE *fp;
565         char upload_notice[512];
566
567         if (CC->upload_fp == NULL) {
568                 cprintf("%d You don't have an upload file open.\n", ERROR + RESOURCE_NOT_OPEN);
569                 return;
570         }
571
572         fclose(CC->upload_fp);
573         CC->upload_fp = NULL;
574
575         if ((!strcasecmp(cmd, "1")) && (CC->upload_type != UPL_FILE)) {
576                 CC->upload_type = UPL_FILE;
577                 cprintf("%d Upload completed.\n", CIT_OK);
578
579                 /* FIXME ... here we need to trigger a network run */
580
581                 return;
582         }
583
584         if (!strcasecmp(cmd, "1")) {
585                 cprintf("%d File '%s' saved.\n", CIT_OK, CC->upl_path);
586                 fp = fopen(CC->upl_filedir, "a");
587                 if (fp == NULL) {
588                         fp = fopen(CC->upl_filedir, "w");
589                 }
590                 if (fp != NULL) {
591                         fprintf(fp, "%s %s %s\n", CC->upl_file,
592                                 CC->upl_mimetype,
593                                 CC->upl_comment);
594                         fclose(fp);
595                 }
596
597                 /* put together an upload notice */
598                 snprintf(upload_notice, sizeof upload_notice,
599                         "NEW UPLOAD: '%s'\n %s\n%s\n",
600                          CC->upl_file, 
601                          CC->upl_comment, 
602                          CC->upl_mimetype);
603                 quickie_message(CC->curr_user, NULL, NULL, CC->room.QRname,
604                                 upload_notice, 0, NULL);
605         } else {
606                 abort_upl(CC);
607                 cprintf("%d File '%s' aborted.\n", CIT_OK, CC->upl_path);
608         }
609 }
610
611
612
613 /*
614  * read from the download file
615  */
616 void cmd_read(char *cmdbuf)
617 {
618         long start_pos;
619         size_t bytes;
620         size_t actual_bytes;
621         char *buf = NULL;
622
623         start_pos = extract_long(cmdbuf, 0);
624         bytes = extract_int(cmdbuf, 1);
625
626         if (CC->download_fp == NULL) {
627                 cprintf("%d You don't have a download file open.\n",
628                         ERROR + RESOURCE_NOT_OPEN);
629                 return;
630         }
631
632         if (bytes > 100000) bytes = 100000;
633         buf = malloc(bytes + 1);
634
635         fseek(CC->download_fp, start_pos, 0);
636         actual_bytes = fread(buf, 1, bytes, CC->download_fp);
637         cprintf("%d %d\n", BINARY_FOLLOWS, (int)actual_bytes);
638         client_write(buf, actual_bytes);
639         free(buf);
640 }
641
642
643
644 /*
645  * write to the upload file
646  */
647 void cmd_writ(char *cmdbuf)
648 {
649         int bytes;
650         char *buf;
651
652         unbuffer_output();
653
654         bytes = extract_int(cmdbuf, 0);
655
656         if (CC->upload_fp == NULL) {
657                 cprintf("%d You don't have an upload file open.\n", ERROR + RESOURCE_NOT_OPEN);
658                 return;
659         }
660
661         if (bytes > 100000) {
662                 cprintf("%d You may not write more than 100000 bytes.\n",
663                         ERROR + TOO_BIG);
664                 return;
665         }
666
667         cprintf("%d %d\n", SEND_BINARY, bytes);
668         buf = malloc(bytes + 1);
669         client_read(buf, bytes);
670         fwrite(buf, bytes, 1, CC->upload_fp);
671         free(buf);
672 }
673
674
675
676
677 /*
678  * cmd_ndop() - open a network spool file for downloading
679  */
680 void cmd_ndop(char *cmdbuf)
681 {
682         char pathname[256];
683         struct stat statbuf;
684
685         if (IsEmptyStr(CC->net_node)) {
686                 cprintf("%d Not authenticated as a network node.\n",
687                         ERROR + NOT_LOGGED_IN);
688                 return;
689         }
690
691         if (CC->download_fp != NULL) {
692                 cprintf("%d You already have a download file open.\n",
693                         ERROR + RESOURCE_BUSY);
694                 return;
695         }
696
697         snprintf(pathname, sizeof pathname, 
698                          "%s/%s",
699                          ctdl_netout_dir,
700                          CC->net_node);
701
702         /* first open the file in append mode in order to create a
703          * zero-length file if it doesn't already exist 
704          */
705         CC->download_fp = fopen(pathname, "a");
706         if (CC->download_fp != NULL)
707                 fclose(CC->download_fp);
708
709         /* now open it */
710         CC->download_fp = fopen(pathname, "r");
711         if (CC->download_fp == NULL) {
712                 cprintf("%d cannot open %s: %s\n",
713                         ERROR + INTERNAL_ERROR, pathname, strerror(errno));
714                 return;
715         }
716
717
718         /* set this flag so other routines know that the download file
719          * currently open is a network spool file 
720          */
721         CC->dl_is_net = 1;
722
723         stat(pathname, &statbuf);
724         cprintf("%d %ld\n", CIT_OK, (long)statbuf.st_size);
725 }
726
727 /*
728  * cmd_nuop() - open a network spool file for uploading
729  */
730 void cmd_nuop(char *cmdbuf)
731 {
732         static int seq = 1;
733
734         if (IsEmptyStr(CC->net_node)) {
735                 cprintf("%d Not authenticated as a network node.\n",
736                         ERROR + NOT_LOGGED_IN);
737                 return;
738         }
739
740         if (CC->upload_fp != NULL) {
741                 cprintf("%d You already have an upload file open.\n",
742                         ERROR + RESOURCE_BUSY);
743                 return;
744         }
745
746         snprintf(CC->upl_path, sizeof CC->upl_path,
747                          "%s/%s.%04lx.%04x",
748                          ctdl_netin_dir,
749                          CC->net_node, 
750                          (long)getpid(), 
751                          ++seq);
752
753         CC->upload_fp = fopen(CC->upl_path, "r");
754         if (CC->upload_fp != NULL) {
755                 fclose(CC->upload_fp);
756                 CC->upload_fp = NULL;
757                 cprintf("%d '%s' already exists\n",
758                         ERROR + ALREADY_EXISTS, CC->upl_path);
759                 return;
760         }
761
762         CC->upload_fp = fopen(CC->upl_path, "w");
763         if (CC->upload_fp == NULL) {
764                 cprintf("%d Cannot open %s: %s\n",
765                         ERROR + INTERNAL_ERROR, CC->upl_path, strerror(errno));
766                 return;
767         }
768
769         CC->upload_type = UPL_NET;
770         cprintf("%d Ok\n", CIT_OK);
771 }