]> code.citadel.org Git - citadel.git/blobdiff - citadel/file_ops.c
Sanitize out backslashes in upload filenames
[citadel.git] / citadel / file_ops.c
index 926d7b357f700afa2143ada8d7b0ec982e3e91ca..af4a872a1d5a43bbd840e0193a3c2d018f3f0f82 100644 (file)
@@ -28,9 +28,9 @@
 #endif
 
 #include <limits.h>
+#include <libcitadel.h>
 #include "citadel.h"
 #include "server.h"
-#include "serv_extensions.h"
 #include "config.h"
 #include "file_ops.h"
 #include "sysdep_decls.h"
@@ -38,8 +38,8 @@
 #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"
@@ -71,13 +71,13 @@ int network_talking_to(char *nodename, int operation) {
 
                case NTT_REMOVE:
                        if (nttlist == NULL) break;
-                       if (strlen(nttlist) == 0) break;
+                       if (IsEmptyStr(nttlist)) break;
                        ptr = malloc(strlen(nttlist));
                        if (ptr == NULL) break;
                        strcpy(ptr, "");
                        for (i = 0; i < num_tokens(nttlist, '|'); ++i) {
                                extract_token(buf, nttlist, i, '|', sizeof buf);
-                               if ( (strlen(buf) > 0)
+                               if ( (!IsEmptyStr(buf))
                                     && (strcasecmp(buf, nodename)) ) {
                                                strcat(ptr, buf);
                                                strcat(ptr, "|");
@@ -89,7 +89,7 @@ int network_talking_to(char *nodename, int operation) {
 
                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_token(buf, nttlist, i, '|', sizeof buf);
                                if (!strcasecmp(buf, nodename)) ++retval;
@@ -97,7 +97,7 @@ int network_talking_to(char *nodename, int operation) {
                        break;
        }
 
-       if (nttlist != NULL) lprintf(CTDL_DEBUG, "nttlist=<%s>\n", nttlist);
+       if (nttlist != NULL) CtdlLogPrintf(CTDL_DEBUG, "nttlist=<%s>\n", nttlist);
        end_critical_section(S_NTTLIST);
        return(retval);
 }
@@ -122,13 +122,13 @@ void cmd_delf(char *filename)
                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] = '_';
                }
        }
@@ -173,14 +173,14 @@ void cmd_movf(char *cmdbuf)
                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] = '_';
                }
        }
@@ -212,7 +212,7 @@ 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",
+                "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", CIT_OK, filename);
@@ -242,14 +242,14 @@ void cmd_netf(char *cmdbuf)
                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] = '_';
                }
        }
@@ -280,7 +280,7 @@ void cmd_netf(char *cmdbuf)
        putc(255, ofp);
        putc(MES_NORMAL, ofp);
        putc(0, ofp);
-       fprintf(ofp, "Pcit%ld", CC->user.usernum);
+       fprintf(ofp, "P%s", CC->user.fullname);
        putc(0, ofp);
        time(&now);
        fprintf(ofp, "T%ld", (long) now);
@@ -322,7 +322,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;
@@ -356,7 +356,7 @@ void cmd_open(char *cmdbuf)
                return;
        }
 
-       if (strlen(filename) == 0) {
+       if (IsEmptyStr(filename)) {
                cprintf("%d You must specify a file name.\n",
                        ERROR + FILE_NOT_FOUND);
                return;
@@ -368,8 +368,8 @@ void cmd_open(char *cmdbuf)
                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] = '_';
                }
        }
@@ -396,6 +396,7 @@ void cmd_oimg(char *cmdbuf)
 {
        char filename[256];
        char pathname[PATH_MAX];
+       char MimeTestBuf[32];
        struct ctdluser usbuf;
        char which_user[USERNAME_SIZE];
        int which_floor;
@@ -403,7 +404,7 @@ void cmd_oimg(char *cmdbuf)
 
        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;
@@ -423,37 +424,42 @@ void cmd_oimg(char *cmdbuf)
                        return;
                }
                snprintf(pathname, sizeof pathname, 
-                                "%s/%ld.gif",
+                                "%s/%ld",
                                 ctdl_usrpic_dir,
                                 usbuf.usernum);
        } else if (!strcasecmp(filename, "_floorpic_")) {
                which_floor = extract_int(cmdbuf, 1);
                snprintf(pathname, sizeof pathname,
-                                "%s/floor.%d.gif",
+                                "%s/floor.%d",
                                 ctdl_image_dir, which_floor);
        } else if (!strcasecmp(filename, "_roompic_")) {
-               assoc_file_name(pathname, sizeof pathname, &CC->room, "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,
-                                "%s/%s.gif",
+                                "%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));
 }
 
 /*
@@ -464,7 +470,8 @@ void cmd_uopn(char *cmdbuf)
        int a;
 
        extract_token(CC->upl_file, cmdbuf, 0, '|', sizeof CC->upl_file);
-       extract_token(CC->upl_comment, cmdbuf, 1, '|', sizeof CC->upl_comment);
+       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;
 
@@ -474,7 +481,7 @@ void cmd_uopn(char *cmdbuf)
                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;
@@ -486,8 +493,8 @@ void cmd_uopn(char *cmdbuf)
                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] = '_';
                }
        }
@@ -536,7 +543,8 @@ void cmd_uimg(char *cmdbuf)
        }
 
        is_this_for_real = extract_int(cmdbuf, 0);
-       extract_token(basenm, cmdbuf, 1, '|', sizeof basenm);
+       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 + RESOURCE_BUSY);
@@ -545,9 +553,9 @@ void cmd_uimg(char *cmdbuf)
 
        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] = '_';
                }
        }
@@ -576,10 +584,10 @@ void cmd_uimg(char *cmdbuf)
        }
 
        if ((!strcasecmp(basenm, "_roompic_")) && (is_room_aide())) {
-               assoc_file_name(CC->upl_path, sizeof CC->upl_path, &CC->room, "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;
@@ -676,16 +684,19 @@ void cmd_ucls(char *cmd)
                        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->room.QRname,
+                       "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);
@@ -767,7 +778,7 @@ void cmd_ndop(char *cmdbuf)
        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;
@@ -816,7 +827,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;