/* $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);
}
syntax highlighted by Code2HTML, v. 0.9.1