* give all commands their own function
[citadel.git] / citadel / file_ops.c
index f6b3c90fcb3a83629e92492299eb9121f523d03a..8fcc068bfd88bf2e1a555c839a6e9de920995603 100644 (file)
@@ -5,10 +5,6 @@
  *
  */
 
-#ifdef DLL_EXPORT
-#define IN_LIBCIT
-#endif
-
 #include "sysdep.h"
 #include <stdlib.h>
 #include <unistd.h>
@@ -16,6 +12,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <ctype.h>
 #include <string.h>
 #include <sys/stat.h>
 
@@ -31,9 +28,9 @@
 #endif
 
 #include <limits.h>
+#include <libcitadel.h>
 #include "citadel.h"
 #include "server.h"
-#include "dynloader.h"
 #include "config.h"
 #include "file_ops.h"
 #include "sysdep_decls.h"
 #include "support.h"
 #include "room_ops.h"
 #include "msgbase.h"
-#include "tools.h"
 #include "citserver.h"
+#include "threads.h"
 
 #ifndef HAVE_SNPRINTF
 #include "snprintf.h"
 #endif
 
+#include "ctdl_module.h"
+
 /*
  * network_talking_to()  --  concurrency checker
  */
@@ -64,9 +63,9 @@ int network_talking_to(char *nodename, int operation) {
        switch(operation) {
 
                case NTT_ADD:
-                       if (nttlist == NULL) nttlist = strdoop("");
+                       if (nttlist == NULL) nttlist = strdup("");
                        if (nttlist == NULL) break;
-                       nttlist = (char *)reallok(nttlist,
+                       nttlist = (char *)realloc(nttlist,
                                (strlen(nttlist) + strlen(nodename) + 3) );
                        strcat(nttlist, "|");
                        strcat(nttlist, nodename);
@@ -74,33 +73,33 @@ int network_talking_to(char *nodename, int operation) {
 
                case NTT_REMOVE:
                        if (nttlist == NULL) break;
-                       if (strlen(nttlist) == 0) break;
-                       ptr = mallok(strlen(nttlist));
+                       if (IsEmptyStr(nttlist)) break;
+                       ptr = malloc(strlen(nttlist));
                        if (ptr == NULL) break;
                        strcpy(ptr, "");
                        for (i = 0; i < num_tokens(nttlist, '|'); ++i) {
-                               extract(buf, nttlist, i);
-                               if ( (strlen(buf) > 0)
+                               extract_token(buf, nttlist, i, '|', sizeof buf);
+                               if ( (!IsEmptyStr(buf))
                                     && (strcasecmp(buf, nodename)) ) {
                                                strcat(ptr, buf);
                                                strcat(ptr, "|");
                                }
                        }
-                       phree(nttlist);
+                       free(nttlist);
                        nttlist = ptr;
                        break;
 
                case NTT_CHECK:
                        if (nttlist == NULL) break;
-                       if (strlen(nttlist) == 0) break;
+                       if (IsEmptyStr(nttlist)) break;
                        for (i = 0; i < num_tokens(nttlist, '|'); ++i) {
-                               extract(buf, nttlist, i);
+                               extract_token(buf, nttlist, i, '|', sizeof buf);
                                if (!strcasecmp(buf, nodename)) ++retval;
                        }
                        break;
        }
 
-       if (nttlist != NULL) lprintf(9, "nttlist=<%s>\n", nttlist);
+       if (nttlist != NULL) CtdlLogPrintf(CTDL_DEBUG, "nttlist=<%s>\n", nttlist);
        end_critical_section(S_NTTLIST);
        return(retval);
 }
@@ -119,27 +118,29 @@ void cmd_delf(char *filename)
        if (CtdlAccessCheck(ac_room_aide))
                return;
 
-       if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
+       if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
                cprintf("%d No directory in this room.\n",
                        ERROR + NOT_HERE);
                return;
        }
 
-       if (strlen(filename) == 0) {
+       if (IsEmptyStr(filename)) {
                cprintf("%d You must specify a file name.\n",
                        ERROR + FILE_NOT_FOUND);
                return;
        }
-       for (a = 0; a < strlen(filename); ++a) {
-               if (filename[a] == '/') {
+       for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
+               if ( (filename[a] == '/') || (filename[a] == '\\') ) {
                        filename[a] = '_';
                }
        }
-       snprintf(pathname, sizeof pathname, "./files/%s/%s",
-                CC->quickroom.QRdirname, filename);
+       snprintf(pathname, sizeof pathname,
+                        "%s/%s/%s",
+                        ctdl_file_dir,
+                        CC->room.QRdirname, filename);
        a = unlink(pathname);
        if (a == 0) {
-               cprintf("%d File '%s' deleted.\n", OK, pathname);
+               cprintf("%d File '%s' deleted.\n", CIT_OK, pathname);
        }
        else {
                cprintf("%d File '%s' not found.\n",
@@ -155,38 +156,38 @@ void cmd_delf(char *filename)
  */
 void cmd_movf(char *cmdbuf)
 {
-       char filename[SIZ];
-       char pathname[SIZ];
-       char newpath[SIZ];
-       char newroom[SIZ];
-       char buf[SIZ];
+       char filename[PATH_MAX];
+       char pathname[PATH_MAX];
+       char newpath[PATH_MAX];
+       char newroom[ROOMNAMELEN];
+       char buf[PATH_MAX];
        int a;
-       struct quickroom qrbuf;
+       struct ctdlroom qrbuf;
 
-       extract(filename, cmdbuf, 0);
-       extract(newroom, cmdbuf, 1);
+       extract_token(filename, cmdbuf, 0, '|', sizeof filename);
+       extract_token(newroom, cmdbuf, 1, '|', sizeof newroom);
 
        if (CtdlAccessCheck(ac_room_aide)) return;
 
-       if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
+       if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
                cprintf("%d No directory in this room.\n",
                        ERROR + NOT_HERE);
                return;
        }
 
-       if (strlen(filename) == 0) {
+       if (IsEmptyStr(filename)) {
                cprintf("%d You must specify a file name.\n",
                        ERROR + FILE_NOT_FOUND);
                return;
        }
 
-       for (a = 0; a < strlen(filename); ++a) {
-               if (filename[a] == '/') {
+       for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
+               if ( (filename[a] == '/') || (filename[a] == '\\') ) {
                        filename[a] = '_';
                }
        }
        snprintf(pathname, sizeof pathname, "./files/%s/%s",
-                CC->quickroom.QRdirname, filename);
+                CC->room.QRdirname, filename);
        if (access(pathname, 0) != 0) {
                cprintf("%d File '%s' not found.\n",
                        ERROR + FILE_NOT_FOUND, pathname);
@@ -194,7 +195,7 @@ void cmd_movf(char *cmdbuf)
        }
 
        if (getroom(&qrbuf, newroom) != 0) {
-               cprintf("%d '%s' does not exist.\n", ERROR, newroom);
+               cprintf("%d '%s' does not exist.\n", ERROR + ROOM_NOT_FOUND, newroom);
                return;
        }
        if ((qrbuf.QRflags & QR_DIRECTORY) == 0) {
@@ -205,7 +206,7 @@ void cmd_movf(char *cmdbuf)
        snprintf(newpath, sizeof newpath, "./files/%s/%s", qrbuf.QRdirname,
                 filename);
        if (link(pathname, newpath) != 0) {
-               cprintf("%d Couldn't move file: %s\n", ERROR,
+               cprintf("%d Couldn't move file: %s\n", ERROR + INTERNAL_ERROR,
                        strerror(errno));
                return;
        }
@@ -213,106 +214,13 @@ void cmd_movf(char *cmdbuf)
 
        /* this is a crude method of copying the file description */
        snprintf(buf, sizeof buf,
-                "cat ./files/%s/filedir |grep %s >>./files/%s/filedir",
-                CC->quickroom.QRdirname, filename, qrbuf.QRdirname);
+                "cat ./files/%s/filedir |grep \"%s\" >>./files/%s/filedir",
+                CC->room.QRdirname, filename, qrbuf.QRdirname);
        system(buf);
-       cprintf("%d File '%s' has been moved.\n", OK, filename);
+       cprintf("%d File '%s' has been moved.\n", CIT_OK, filename);
 }
 
 
-/*
- * send a file over the net
- */
-void cmd_netf(char *cmdbuf)
-{
-       char pathname[SIZ], filename[SIZ], destsys[SIZ], buf[SIZ];
-       char outfile[SIZ];
-       int a, e;
-       time_t now;
-       FILE *ofp;
-       static int seq = 1;
-
-       extract(filename, cmdbuf, 0);
-       extract(destsys, cmdbuf, 1);
-
-       if (CtdlAccessCheck(ac_room_aide)) return;
-
-       if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
-               cprintf("%d No directory in this room.\n",
-                       ERROR + NOT_HERE);
-               return;
-       }
-
-       if (strlen(filename) == 0) {
-               cprintf("%d You must specify a file name.\n",
-                       ERROR + FILE_NOT_FOUND);
-               return;
-       }
-
-       for (a = 0; a < strlen(filename); ++a) {
-               if (filename[a] == '/') {
-                       filename[a] = '_';
-               }
-       }
-       snprintf(pathname, sizeof pathname, "./files/%s/%s",
-                CC->quickroom.QRdirname, filename);
-       if (access(pathname, 0) != 0) {
-               cprintf("%d File '%s' not found.\n",
-                       ERROR + FILE_NOT_FOUND, pathname);
-               return;
-       }
-       snprintf(buf, sizeof buf, "sysop@%s", destsys);
-       e = alias(buf);
-       if (e != MES_IGNET) {
-               cprintf("%d No such system: '%s'\n",
-                       ERROR + NO_SUCH_SYSTEM, destsys);
-               return;
-       }
-       snprintf(outfile, sizeof outfile,
-                "%s/network/spoolin/nsf.%04x.%04x",
-                BBSDIR, getpid(), ++seq);
-       ofp = fopen(outfile, "a");
-       if (ofp == NULL) {
-               cprintf("%d internal error\n", ERROR);
-               return;
-       }
-
-       putc(255, ofp);
-       putc(MES_NORMAL, ofp);
-       putc(0, ofp);
-       fprintf(ofp, "Pcit%ld", CC->usersupp.usernum);
-       putc(0, ofp);
-       time(&now);
-       fprintf(ofp, "T%ld", (long) now);
-       putc(0, ofp);
-       fprintf(ofp, "A%s", CC->usersupp.fullname);
-       putc(0, ofp);
-       fprintf(ofp, "O%s", CC->quickroom.QRname);
-       putc(0, ofp);
-       fprintf(ofp, "N%s", NODENAME);
-       putc(0, ofp);
-       fprintf(ofp, "D%s", destsys);
-       putc(0, ofp);
-       fprintf(ofp, "SFILE");
-       putc(0, ofp);
-       putc('M', ofp);
-       fclose(ofp);
-
-       snprintf(buf, sizeof buf,
-                "cd ./files/%s; uuencode %s <%s 2>/dev/null >>%s",
-                CC->quickroom.QRdirname, filename, filename, outfile);
-       system(buf);
-
-       ofp = fopen(outfile, "a");
-       putc(0, ofp);
-       fclose(ofp);
-
-       cprintf("%d File '%s' has been sent to %s.\n", OK, filename,
-               destsys);
-       /* FIXME start a network run here. */
-       return;
-}
-
 /*
  * This code is common to all commands which open a file for downloading,
  * regardless of whether it's a file from the directory, an image, a network
@@ -320,7 +228,7 @@ void cmd_netf(char *cmdbuf)
  * It examines the file and displays the OK result code and some information
  * about the file.  NOTE: this stuff is Unix dependent.
  */
-void OpenCmdResult(char *filename, char *mime_type)
+void OpenCmdResult(char *filename, const char *mime_type)
 {
        struct stat statbuf;
        time_t modtime;
@@ -331,7 +239,7 @@ void OpenCmdResult(char *filename, char *mime_type)
        modtime = (time_t) statbuf.st_mtime;
 
        cprintf("%d %ld|%ld|%s|%s\n",
-               OK, filesize, (long)modtime, filename, mime_type);
+               CIT_OK, filesize, (long)modtime, filename, mime_type);
 }
 
 
@@ -340,21 +248,21 @@ void OpenCmdResult(char *filename, char *mime_type)
  */
 void cmd_open(char *cmdbuf)
 {
-       char filename[SIZ];
-       char pathname[SIZ];
+       char filename[256];
+       char pathname[PATH_MAX];
        int a;
 
-       extract(filename, cmdbuf, 0);
+       extract_token(filename, cmdbuf, 0, '|', sizeof filename);
 
        if (CtdlAccessCheck(ac_logged_in)) return;
 
-       if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
+       if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
                cprintf("%d No directory in this room.\n",
                        ERROR + NOT_HERE);
                return;
        }
 
-       if (strlen(filename) == 0) {
+       if (IsEmptyStr(filename)) {
                cprintf("%d You must specify a file name.\n",
                        ERROR + FILE_NOT_FOUND);
                return;
@@ -362,23 +270,25 @@ void cmd_open(char *cmdbuf)
 
        if (CC->download_fp != NULL) {
                cprintf("%d You already have a download file open.\n",
-                       ERROR);
+                       ERROR + RESOURCE_BUSY);
                return;
        }
 
-       for (a = 0; a < strlen(filename); ++a) {
-               if (filename[a] == '/') {
+       for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
+               if ( (filename[a] == '/') || (filename[a] == '\\') ) {
                        filename[a] = '_';
                }
        }
 
        snprintf(pathname, sizeof pathname,
-                "./files/%s/%s", CC->quickroom.QRdirname, filename);
+                        "%s/%s/%s",
+                        ctdl_file_dir,
+                        CC->room.QRdirname, filename);
        CC->download_fp = fopen(pathname, "r");
 
        if (CC->download_fp == NULL) {
                cprintf("%d cannot open %s: %s\n",
-                       ERROR, pathname, strerror(errno));
+                       ERROR + INTERNAL_ERROR, pathname, strerror(errno));
                return;
        }
 
@@ -390,16 +300,17 @@ void cmd_open(char *cmdbuf)
  */
 void cmd_oimg(char *cmdbuf)
 {
-       char filename[SIZ];
-       char pathname[SIZ];
-       struct usersupp usbuf;
-       char which_user[32];
+       char filename[256];
+       char pathname[PATH_MAX];
+       char MimeTestBuf[32];
+       struct ctdluser usbuf;
+       char which_user[USERNAME_SIZE];
        int which_floor;
        int a;
 
-       extract(filename, cmdbuf, 0);
+       extract_token(filename, cmdbuf, 0, '|', sizeof filename);
 
-       if (strlen(filename) == 0) {
+       if (IsEmptyStr(filename)) {
                cprintf("%d You must specify a file name.\n",
                        ERROR + FILE_NOT_FOUND);
                return;
@@ -407,44 +318,54 @@ void cmd_oimg(char *cmdbuf)
 
        if (CC->download_fp != NULL) {
                cprintf("%d You already have a download file open.\n",
-                       ERROR);
+                       ERROR + RESOURCE_BUSY);
                return;
        }
 
        if (!strcasecmp(filename, "_userpic_")) {
-               extract(which_user, cmdbuf, 1);
+               extract_token(which_user, cmdbuf, 1, '|', sizeof which_user);
                if (getuser(&usbuf, which_user) != 0) {
                        cprintf("%d No such user.\n",
                                ERROR + NO_SUCH_USER);
                        return;
                }
-               snprintf(pathname, sizeof pathname, "./userpics/%ld.gif",
-                        usbuf.usernum);
+               snprintf(pathname, sizeof pathname, 
+                                "%s/%ld",
+                                ctdl_usrpic_dir,
+                                usbuf.usernum);
        } else if (!strcasecmp(filename, "_floorpic_")) {
                which_floor = extract_int(cmdbuf, 1);
                snprintf(pathname, sizeof pathname,
-                        "./images/floor.%d.gif", which_floor);
+                                "%s/floor.%d",
+                                ctdl_image_dir, which_floor);
        } else if (!strcasecmp(filename, "_roompic_")) {
-               assoc_file_name(pathname, sizeof pathname, &CC->quickroom, "images");
+               assoc_file_name(pathname, sizeof pathname, &CC->room, ctdl_image_dir);
        } else {
-               for (a = 0; a < strlen(filename); ++a) {
+               for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
                        filename[a] = tolower(filename[a]);
-                       if (filename[a] == '/') {
+                       if ( (filename[a] == '/') || (filename[a] == '\\') ) {
                                filename[a] = '_';
                        }
                }
-               snprintf(pathname, sizeof pathname, "./images/%s.gif",
-                        filename);
+               snprintf(pathname, sizeof pathname,
+                                "%s/%s",
+                                ctdl_image_dir,
+                                filename);
        }
 
        CC->download_fp = fopen(pathname, "rb");
+       if (CC->download_fp == NULL) {
+               strcat(pathname, ".gif");
+               CC->download_fp = fopen(pathname, "rb");
+       }
        if (CC->download_fp == NULL) {
                cprintf("%d Cannot open %s: %s\n",
                        ERROR + FILE_NOT_FOUND, pathname, strerror(errno));
                return;
        }
-
-       OpenCmdResult(pathname, "image/gif");
+       fread(&MimeTestBuf[0], 1, 32, CC->download_fp);
+       rewind (CC->download_fp);
+       OpenCmdResult(pathname, GuessMimeType(&MimeTestBuf[0], 32));
 }
 
 /*
@@ -454,18 +375,19 @@ void cmd_uopn(char *cmdbuf)
 {
        int a;
 
-       extract(CC->upl_file, cmdbuf, 0);
-       extract(CC->upl_comment, cmdbuf, 1);
+       extract_token(CC->upl_file, cmdbuf, 0, '|', sizeof CC->upl_file);
+       extract_token(CC->upl_mimetype, cmdbuf, 1, '|', sizeof CC->upl_mimetype);
+       extract_token(CC->upl_comment, cmdbuf, 2, '|', sizeof CC->upl_comment);
 
        if (CtdlAccessCheck(ac_logged_in)) return;
 
-       if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
+       if ((CC->room.QRflags & QR_DIRECTORY) == 0) {
                cprintf("%d No directory in this room.\n",
                        ERROR + NOT_HERE);
                return;
        }
 
-       if (strlen(CC->upl_file) == 0) {
+       if (IsEmptyStr(CC->upl_file)) {
                cprintf("%d You must specify a file name.\n",
                        ERROR + FILE_NOT_FOUND);
                return;
@@ -473,19 +395,23 @@ void cmd_uopn(char *cmdbuf)
 
        if (CC->upload_fp != NULL) {
                cprintf("%d You already have a upload file open.\n",
-                       ERROR);
+                       ERROR + RESOURCE_BUSY);
                return;
        }
 
-       for (a = 0; a < strlen(CC->upl_file); ++a) {
-               if (CC->upl_file[a] == '/') {
+       for (a = 0; !IsEmptyStr(&CC->upl_file[a]); ++a) {
+               if ( (CC->upl_file[a] == '/') || (CC->upl_file[a] == '\\') ) {
                        CC->upl_file[a] = '_';
                }
        }
-       snprintf(CC->upl_path, sizeof CC->upl_path, "./files/%s/%s",
-                CC->quickroom.QRdirname, CC->upl_file);
+       snprintf(CC->upl_path, sizeof CC->upl_path, 
+                        "%s/%s/%s",
+                        ctdl_file_dir,
+                        CC->room.QRdirname, CC->upl_file);
        snprintf(CC->upl_filedir, sizeof CC->upl_filedir,
-                "./files/%s/filedir", CC->quickroom.QRdirname);
+                        "%s/%s/filedir", 
+                        ctdl_file_dir,
+                        CC->room.QRdirname);
 
        CC->upload_fp = fopen(CC->upl_path, "r");
        if (CC->upload_fp != NULL) {
@@ -499,10 +425,10 @@ void cmd_uopn(char *cmdbuf)
        CC->upload_fp = fopen(CC->upl_path, "wb");
        if (CC->upload_fp == NULL) {
                cprintf("%d Cannot open %s: %s\n",
-                       ERROR, CC->upl_path, strerror(errno));
+                       ERROR + INTERNAL_ERROR, CC->upl_path, strerror(errno));
                return;
        }
-       cprintf("%d Ok\n", OK);
+       cprintf("%d Ok\n", CIT_OK);
 }
 
 
@@ -513,71 +439,78 @@ void cmd_uopn(char *cmdbuf)
 void cmd_uimg(char *cmdbuf)
 {
        int is_this_for_real;
-       char basenm[SIZ];
+       char basenm[256];
        int which_floor;
        int a;
 
        if (num_parms(cmdbuf) < 2) {
-               cprintf("%d Usage error.\n", ERROR);
+               cprintf("%d Usage error.\n", ERROR + ILLEGAL_VALUE);
                return;
        }
 
        is_this_for_real = extract_int(cmdbuf, 0);
-       extract(basenm, cmdbuf, 1);
+       extract_token(CC->upl_mimetype, cmdbuf, 1, '|', sizeof CC->upl_mimetype);
+       extract_token(basenm, cmdbuf, 2, '|', sizeof basenm);
        if (CC->upload_fp != NULL) {
                cprintf("%d You already have an upload file open.\n",
-                       ERROR);
+                       ERROR + RESOURCE_BUSY);
                return;
        }
 
        strcpy(CC->upl_path, "");
 
-       for (a = 0; a < strlen(basenm); ++a) {
+       for (a = 0; !IsEmptyStr(&basenm[a]); ++a) {
                basenm[a] = tolower(basenm[a]);
-               if (basenm[a] == '/') {
+               if ( (basenm[a] == '/') || (basenm[a] == '\\') ) {
                        basenm[a] = '_';
                }
        }
 
-       if (CC->usersupp.axlevel >= 6) {
-               snprintf(CC->upl_path, sizeof CC->upl_path, "./images/%s",
-                        basenm);
+       if (CC->user.axlevel >= 6) {
+               snprintf(CC->upl_path, sizeof CC->upl_path, 
+                                "%s/%s",
+                                ctdl_image_dir,
+                                basenm);
        }
 
        if (!strcasecmp(basenm, "_userpic_")) {
                snprintf(CC->upl_path, sizeof CC->upl_path,
-                        "./userpics/%ld.gif", CC->usersupp.usernum);
+                                "%s/%ld.gif",
+                                ctdl_usrpic_dir,
+                                CC->user.usernum);
        }
 
        if ((!strcasecmp(basenm, "_floorpic_"))
-           && (CC->usersupp.axlevel >= 6)) {
+           && (CC->user.axlevel >= 6)) {
                which_floor = extract_int(cmdbuf, 2);
                snprintf(CC->upl_path, sizeof CC->upl_path,
-                        "./images/floor.%d.gif", which_floor);
+                                "%s/floor.%d.gif",
+                                ctdl_image_dir,
+                                which_floor);
        }
 
        if ((!strcasecmp(basenm, "_roompic_")) && (is_room_aide())) {
-               assoc_file_name(CC->upl_path, sizeof CC->upl_path, &CC->quickroom, "images");
+               assoc_file_name(CC->upl_path, sizeof CC->upl_path, &CC->room, ctdl_image_dir);
        }
 
-       if (strlen(CC->upl_path) == 0) {
+       if (IsEmptyStr(CC->upl_path)) {
                cprintf("%d Higher access required.\n",
                        ERROR + HIGHER_ACCESS_REQUIRED);
                return;
        }
 
        if (is_this_for_real == 0) {
-               cprintf("%d Ok to send image\n", OK);
+               cprintf("%d Ok to send image\n", CIT_OK);
                return;
        }
 
        CC->upload_fp = fopen(CC->upl_path, "wb");
        if (CC->upload_fp == NULL) {
                cprintf("%d Cannot open %s: %s\n",
-                       ERROR, CC->upl_path, strerror(errno));
+                       ERROR + INTERNAL_ERROR, CC->upl_path, strerror(errno));
                return;
        }
-       cprintf("%d Ok\n", OK);
+       cprintf("%d Ok\n", CIT_OK);
        CC->upload_type = UPL_IMAGE;
 }
 
@@ -585,13 +518,13 @@ void cmd_uimg(char *cmdbuf)
 /*
  * close the download file
  */
-void cmd_clos(void)
+void cmd_clos(char *cmdbuf)
 {
-       char buf[SIZ];
+       char buf[256];
 
        if (CC->download_fp == NULL) {
                cprintf("%d You don't have a download file open.\n",
-                       ERROR);
+                       ERROR + RESOURCE_NOT_OPEN);
                return;
        }
 
@@ -600,12 +533,14 @@ void cmd_clos(void)
 
        if (CC->dl_is_net == 1) {
                CC->dl_is_net = 0;
-               snprintf(buf, sizeof buf, "%s/network/spoolout/%s", BBSDIR,
-                        CC->net_node);
+               snprintf(buf, sizeof buf, 
+                                "%s/%s",
+                                ctdl_netout_dir,
+                                CC->net_node);
                unlink(buf);
        }
 
-       cprintf("%d Ok\n", OK);
+       cprintf("%d Ok\n", CIT_OK);
 }
 
 
@@ -632,7 +567,7 @@ void cmd_ucls(char *cmd)
        char upload_notice[512];
 
        if (CC->upload_fp == NULL) {
-               cprintf("%d You don't have an upload file open.\n", ERROR);
+               cprintf("%d You don't have an upload file open.\n", ERROR + RESOURCE_NOT_OPEN);
                return;
        }
 
@@ -641,7 +576,7 @@ void cmd_ucls(char *cmd)
 
        if ((!strcasecmp(cmd, "1")) && (CC->upload_type != UPL_FILE)) {
                CC->upload_type = UPL_FILE;
-               cprintf("%d Upload completed.\n", OK);
+               cprintf("%d Upload completed.\n", CIT_OK);
 
                /* FIXME ... here we need to trigger a network run */
 
@@ -649,26 +584,29 @@ void cmd_ucls(char *cmd)
        }
 
        if (!strcasecmp(cmd, "1")) {
-               cprintf("%d File '%s' saved.\n", OK, CC->upl_path);
+               cprintf("%d File '%s' saved.\n", CIT_OK, CC->upl_path);
                fp = fopen(CC->upl_filedir, "a");
                if (fp == NULL) {
                        fp = fopen(CC->upl_filedir, "w");
                }
                if (fp != NULL) {
-                       fprintf(fp, "%s %s\n", CC->upl_file,
+                       fprintf(fp, "%s %s %s\n", CC->upl_file,
+                               CC->upl_mimetype,
                                CC->upl_comment);
                        fclose(fp);
                }
 
                /* put together an upload notice */
                snprintf(upload_notice, sizeof upload_notice,
-                       "NEW UPLOAD: '%s'\n %s\n",
-                       CC->upl_file, CC->upl_comment);
-               quickie_message(CC->curr_user, NULL, CC->quickroom.QRname,
-                               upload_notice);
+                       "NEW UPLOAD: '%s'\n %s\n%s\n",
+                        CC->upl_file, 
+                        CC->upl_comment, 
+                        CC->upl_mimetype);
+               quickie_message(CC->curr_user, NULL, NULL, CC->room.QRname,
+                               upload_notice, 0, NULL);
        } else {
                abort_upl(CC);
-               cprintf("%d File '%s' aborted.\n", OK, CC->upl_path);
+               cprintf("%d File '%s' aborted.\n", CIT_OK, CC->upl_path);
        }
 }
 
@@ -680,28 +618,27 @@ void cmd_ucls(char *cmd)
 void cmd_read(char *cmdbuf)
 {
        long start_pos;
-       int bytes;
-       char buf[4096];
+       size_t bytes;
+       size_t actual_bytes;
+       char *buf = NULL;
 
        start_pos = extract_long(cmdbuf, 0);
        bytes = extract_int(cmdbuf, 1);
 
        if (CC->download_fp == NULL) {
                cprintf("%d You don't have a download file open.\n",
-                       ERROR);
+                       ERROR + RESOURCE_NOT_OPEN);
                return;
        }
 
-       if (bytes > 4096) {
-               cprintf("%d You may not read more than 4096 bytes.\n",
-                       ERROR);
-               return;
-       }
+       if (bytes > 100000) bytes = 100000;
+       buf = malloc(bytes + 1);
 
        fseek(CC->download_fp, start_pos, 0);
-       fread(buf, bytes, 1, CC->download_fp);
-       cprintf("%d %d\n", BINARY_FOLLOWS, bytes);
-       client_write(buf, bytes);
+       actual_bytes = fread(buf, 1, bytes, CC->download_fp);
+       cprintf("%d %d\n", BINARY_FOLLOWS, (int)actual_bytes);
+       client_write(buf, actual_bytes);
+       free(buf);
 }
 
 
@@ -712,24 +649,28 @@ void cmd_read(char *cmdbuf)
 void cmd_writ(char *cmdbuf)
 {
        int bytes;
-       char buf[4096];
+       char *buf;
+
+       unbuffer_output();
 
        bytes = extract_int(cmdbuf, 0);
 
        if (CC->upload_fp == NULL) {
-               cprintf("%d You don't have an upload file open.\n", ERROR);
+               cprintf("%d You don't have an upload file open.\n", ERROR + RESOURCE_NOT_OPEN);
                return;
        }
 
-       if (bytes > 4096) {
-               cprintf("%d You may not write more than 4096 bytes.\n",
-                       ERROR);
+       if (bytes > 100000) {
+               cprintf("%d You may not write more than 100000 bytes.\n",
+                       ERROR + TOO_BIG);
                return;
        }
 
        cprintf("%d %d\n", SEND_BINARY, bytes);
+       buf = malloc(bytes + 1);
        client_read(buf, bytes);
        fwrite(buf, bytes, 1, CC->upload_fp);
+       free(buf);
 }
 
 
@@ -740,10 +681,10 @@ void cmd_writ(char *cmdbuf)
  */
 void cmd_ndop(char *cmdbuf)
 {
-       char pathname[SIZ];
+       char pathname[256];
        struct stat statbuf;
 
-       if (strlen(CC->net_node) == 0) {
+       if (IsEmptyStr(CC->net_node)) {
                cprintf("%d Not authenticated as a network node.\n",
                        ERROR + NOT_LOGGED_IN);
                return;
@@ -751,12 +692,14 @@ void cmd_ndop(char *cmdbuf)
 
        if (CC->download_fp != NULL) {
                cprintf("%d You already have a download file open.\n",
-                       ERROR);
+                       ERROR + RESOURCE_BUSY);
                return;
        }
 
-       snprintf(pathname, sizeof pathname, "%s/network/spoolout/%s",
-                BBSDIR, CC->net_node);
+       snprintf(pathname, sizeof pathname, 
+                        "%s/%s",
+                        ctdl_netout_dir,
+                        CC->net_node);
 
        /* first open the file in append mode in order to create a
         * zero-length file if it doesn't already exist 
@@ -769,7 +712,7 @@ void cmd_ndop(char *cmdbuf)
        CC->download_fp = fopen(pathname, "r");
        if (CC->download_fp == NULL) {
                cprintf("%d cannot open %s: %s\n",
-                       ERROR, pathname, strerror(errno));
+                       ERROR + INTERNAL_ERROR, pathname, strerror(errno));
                return;
        }
 
@@ -780,7 +723,7 @@ void cmd_ndop(char *cmdbuf)
        CC->dl_is_net = 1;
 
        stat(pathname, &statbuf);
-       cprintf("%d %ld\n", OK, (long)statbuf.st_size);
+       cprintf("%d %ld\n", CIT_OK, (long)statbuf.st_size);
 }
 
 /*
@@ -790,7 +733,7 @@ void cmd_nuop(char *cmdbuf)
 {
        static int seq = 1;
 
-       if (strlen(CC->net_node) == 0) {
+       if (IsEmptyStr(CC->net_node)) {
                cprintf("%d Not authenticated as a network node.\n",
                        ERROR + NOT_LOGGED_IN);
                return;
@@ -798,13 +741,16 @@ void cmd_nuop(char *cmdbuf)
 
        if (CC->upload_fp != NULL) {
                cprintf("%d You already have an upload file open.\n",
-                       ERROR);
+                       ERROR + RESOURCE_BUSY);
                return;
        }
 
        snprintf(CC->upl_path, sizeof CC->upl_path,
-                "%s/network/spoolin/%s.%04x.%04x",
-                BBSDIR, CC->net_node, getpid(), ++seq);
+                        "%s/%s.%04lx.%04x",
+                        ctdl_netin_dir,
+                        CC->net_node, 
+                        (long)getpid(), 
+                        ++seq);
 
        CC->upload_fp = fopen(CC->upl_path, "r");
        if (CC->upload_fp != NULL) {
@@ -818,10 +764,33 @@ void cmd_nuop(char *cmdbuf)
        CC->upload_fp = fopen(CC->upl_path, "w");
        if (CC->upload_fp == NULL) {
                cprintf("%d Cannot open %s: %s\n",
-                       ERROR, CC->upl_path, strerror(errno));
+                       ERROR + INTERNAL_ERROR, CC->upl_path, strerror(errno));
                return;
        }
 
        CC->upload_type = UPL_NET;
-       cprintf("%d Ok\n", OK);
+       cprintf("%d Ok\n", CIT_OK);
+}
+
+
+/*****************************************************************************/
+/*                      MODULE INITIALIZATION STUFF                          */
+/*****************************************************************************/
+
+CTDL_MODULE_INIT(file_ops)
+{
+       CtdlRegisterProtoHook(cmd_delf, "DELF", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_movf, "MOVF", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_open, "OPEN", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_clos, "CLOS", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_uopn, "UOPN", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_ucls, "UCLS", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_read, "READ", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_writ, "WRIT", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_oimg, "OIMG", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_ndop, "NDOP", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_nuop, "NUOP", "Autoconverted. TODO: document me.");
+       CtdlRegisterProtoHook(cmd_uimg, "UIMG", "Autoconverted. TODO: document me.");
+        /* return our Subversion id for the Log */
+       return "$Id$";
 }