/* $Cambridge: hermes/src/prayer/accountd/file.c,v 1.1.1.1 2003/04/15 13:00:02 dpc22 Exp $ */ /************************************************ * Prayer - a Webmail Interface * ************************************************/ /* Copyright (c) University of Cambridge 2000 - 2002 */ /* See the file NOTICE for conditions of use and distribution. */ #include "accountd.h" /* file_checkname() ****************************************************** * * Run saniy check on path. Looking for /.. * s: Filename to check * * Returns: T if name passes sanity check. ************************************************************************/ static BOOL file_checkname(char *s) { if (*s == '/') return (NIL); while (*s) { if ((s[0] == '.') && (s[1] == '.')) return (NIL); s++; } return (T); } /* file_get() ************************************************************ * * Get named file from peer. * config: Accountd configuration * stream: write file to this stream * line: Line following GET. Should be: * canon encoded filename e.g: Hello%20World * * Returns status on stream: * OK {size} - File download * NO (Text) - Couldn't download file (followed by reason) * BAD (Text) - Protocol error * ************************************************************************/ BOOL file_get(struct config * config, struct iostream * stream, char *line) { char *name; FILE *file; struct stat sbuf; int c; if (!((name = string_get_token(&line)) && (name[0]))) { ioputs(stream, "BAD No filename provided" CRLF); ioflush(stream); return (T); } string_canon_decode(name); if (!file_checkname(name)) { ioputs(stream, "NO Invalid file name" CRLF); ioflush(stream); return (T); } if (stat(name, &sbuf)) { ioputs(stream, "NO No such file" CRLF); ioflush(stream); return (T); } if (!(sbuf.st_mode & S_IFREG)) { ioputs(stream, "NO Not a regular file" CRLF); ioflush(stream); return (T); } if ((file = fopen(name, "r")) == NIL) { ioputs(stream, "NO Couldn't open file" CRLF); ioflush(stream); return (T); } ioprintf(stream, "OK {%lu}" CRLF, (unsigned long) sbuf.st_size); while ((c = getc(file)) != EOF) ioputc(c, stream); ioputs(stream, "" CRLF); ioflush(stream); fclose(file); return (T); } /* file_put() ************************************************************ * * Upload named file from peer. * config: Accountd configuration * stream: write file to this stream * line: Line following PUT command. Should be: * canon encoded filename e.g: Hello%20World * Size of following literal followed by CRLF * * Returns status on stream: * OK (Text) - File upload succeeded * NO (Text) - Couldn't upload file (followed by reason) * BAD (Text) - Protocol error ************************************************************************/ BOOL file_put(struct config * config, struct iostream * stream, char *line) { char *name, *size; FILE *file; int c, len; if (!((name = string_get_token(&line)) && (name[0]))) { ioputs(stream, "BAD No filename provided" CRLF); ioflush(stream); return (T); } string_canon_decode(name); if (!((size = string_get_token(&line)) && (size[0]))) { ioputs(stream, "BAD No file size provided" CRLF); ioflush(stream); return (T); } if (((len = strlen(size)) < 2) || (size[0] != '{') || (size[len - 1] != '}')) { ioputs(stream, "BAD Invalid file size" CRLF); ioflush(stream); return (T); } /* Check that size[1] -> size[len-1] all digits? */ size[len - 1] = '\0'; /* Probably not needed */ len = atoi(size + 1); if (!file_checkname(name)) { /* Swallow unwanted text */ while ((len > 0) && (c = iogetc(stream))) len--; ioputs(stream, "NO Invalid file name" CRLF); ioflush(stream); return (T); } if ((file = fopen(name, "w")) == NIL) { /* Swallow unwanted text */ while ((len > 0) && (c = iogetc(stream))) len--; ioputs(stream, "NO Couldn't open file" CRLF); ioflush(stream); return (T); } while ((len > 0) && (c = iogetc(stream))) { putc(c, file); len--; } if (len > 0) { ioprintf(stream, "BAD %d bytes missing from input" CRLF, len); ioflush(stream); return (T); } ioputs(stream, "OK File uploaded" CRLF); ioflush(stream); fclose(file); return (T); }