/*
- * $Id: client.cc,v 1.58 1998/03/05 00:42:48 wessels Exp $
+ * $Id: client.cc,v 1.59 1998/03/06 05:43:33 kostas Exp $
*
* DEBUG: section 0 WWW Client
* AUTHOR: Harvest Derived
static void usage(const char *progname);
static int Now(struct timeval *);
static SIGHDLR catch;
+static SIGHDLR pipe_handler;
+static void set_our_signal();
static int put_fd;
static char *put_file = NULL;
static struct stat p;
+int total_bytes=0;
static void
usage(const char *progname)
opt_put = 1;
method = xstrdup("PUT");
put_fd = open(put_file, O_RDONLY);
+ set_our_signal();
if (put_fd < 0) {
fprintf(stderr, "%s: can't open file (%s)\n", argv[0],
xstrerror());
int x;
while ((x = read(put_fd, msg, BUFSIZ)) > 0) {
x = write(conn, msg, x);
+ total_bytes+=x;
if (x <= 0)
break;
}
- if (x != 0) {
+ if (x != 0)
fprintf(stderr, "client: ERROR: Cannot send file.\n");
- exit(1);
- }
+ fprintf(stderr, "TOTAL SENT: %d\n",total_bytes);
close(put_fd);
}
/* Read the data */
+
while ((len = read(conn, buf, sizeof(buf))) > 0) {
if (to_stdout)
fwrite(buf, len, 1, stdout);
interrupted = 1;
fprintf(stderr, "Interrupted.\n");
}
+void
+pipe_handler(int sig)
+{
+ fprintf(stderr,"SIGPIPE received.\n");
+}
+
+static void
+set_our_signal()
+{
+#if HAVE_SIGACTION
+ struct sigaction sa;
+ sa.sa_handler = pipe_handler;
+ sa.sa_flags = SA_RESTART;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGPIPE, &sa, NULL) < 0) {
+ fprintf(stderr,"Cannot set PIPE signal.\n");
+ exit(-1);
+ }
+#else
+ signal(SIGPIPE, pipe_handler);
+#endif
+
+}
/*
- * $Id: ftp.cc,v 1.201 1998/03/05 00:42:52 wessels Exp $
+ * $Id: ftp.cc,v 1.202 1998/03/06 05:43:36 kostas Exp $
*
* DEBUG: section 9 File Transfer Protocol (FTP)
* AUTHOR: Harvest Derived
FTP_HTML_HEADER_SENT,
FTP_BINARY,
FTP_TRY_SLASH_HACK,
+ FTP_PUT,
+ FTP_PUT_MKDIR,
FTP_LISTFORMAT_UNKNOWN
};
SENT_NLST,
SENT_REST,
SENT_RETR,
+ SENT_STOR,
SENT_QUIT,
- READING_DATA
+ READING_DATA,
+ WRITING_DATA,
+ SENT_MKDIR
} ftp_state_t;
typedef struct _Ftpdata {
static void ftpAuthRequired(HttpReply * reply, request_t * request, const char *realm);
static STABH ftpAbort;
static void ftpHackShortcut(FtpStateData * ftpState, FTPSM * nextState);
+static void ftpPutStart(FtpStateData *);
+static CWCB ftpPutTransferDone;
/* State machine functions
* send == state transition
static FTPSM ftpFail;
static FTPSM ftpDataTransferDone;
static FTPSM ftpRestOrList;
-
+static FTPSM ftpSendStor;
+static FTPSM ftpReadStor;
+static FTPSM ftpSendReply;
+static FTPSM ftpTryMkdir;
+static FTPSM ftpReadMkdir;
/************************************************
** State Machine Description (excluding hacks) **
*************************************************
ftpReadList, /* SENT_NLST */
ftpReadRest,
ftpReadRetr,
+ ftpReadStor,
ftpReadQuit,
- ftpReadTransferDone
+ ftpReadTransferDone,
+ ftpSendReply,
+ ftpReadMkdir
};
static void
FtpStateData *ftpState = data;
if (ftpState == NULL)
return;
- debug(9, 3) ("ftpStateFree: %s\n", storeUrl(ftpState->entry));
+ debug(9, 3) ("ftpStateFree: %d\n", storeUrl(ftpState->entry));
storeUnregisterAbort(ftpState->entry);
storeUnlockObject(ftpState->entry);
if (ftpState->reply_hdr) {
/* Connection closed; retrieval done. */
if (EBIT_TEST(ftpState->flags, FTP_HTML_HEADER_SENT))
ftpListingFinish(ftpState);
- storeTimestampsSet(ftpState->entry);
- storeComplete(ftpState->entry);
+ if (!EBIT_TEST(ftpState->flags, FTP_PUT)) {
+ storeTimestampsSet(ftpState->entry);
+ storeComplete(ftpState->entry);
+ }
/* expect the "transfer complete" message on the control socket */
commSetSelect(ftpState->ctrl.fd,
COMM_SELECT_READ,
ftpState->data.fd = -1;
EBIT_SET(ftpState->flags, FTP_PASV_SUPPORTED);
EBIT_SET(ftpState->flags, FTP_REST_SUPPORTED);
+ if (ftpState->request->method == METHOD_PUT)
+ EBIT_SET(ftpState->flags, FTP_PUT);
if (!ftpCheckAuth(ftpState, request->headers)) {
/* This request is not fully authenticated */
if (request->port == 21) {
ftpState->ctrl.last_reply = (*W)->key;
safe_free(*W);
ftpState->ctrl.offset = 0;
+ debug(9,8)("ftpReadControlReply: state=%d\n",ftpState->state);
FTP_SM_FUNCS[ftpState->state] (ftpState);
}
ftpTraverseDirectory(FtpStateData * ftpState)
{
wordlist *w;
- debug(9, 4) ("ftpTraverseDirectory\n");
+ debug(9, 4) ("ftpTraverseDirectory %s\n", ftpState->filepath);
safe_free(ftpState->filepath);
/* Done? */
ftpTraverseDirectory(ftpState);
} else {
/* CWD FAILED */
- ftpFail(ftpState);
+ if (!EBIT_TEST(ftpState->flags, FTP_PUT))
+ ftpFail(ftpState);
+ else
+ ftpTryMkdir(ftpState);
}
}
+static void
+ftpTryMkdir(FtpStateData *ftpState)
+{
+ char *path=ftpState->filepath;
+ debug(9,3)("ftpTryMkdir: with path=%s\n",path);
+ snprintf(cbuf, 1024, "MKD %s\r\n", path);
+ ftpWriteCommand(cbuf, ftpState);
+ ftpState->state = SENT_MKDIR;
+}
+
+static void
+ftpReadMkdir(FtpStateData *ftpState)
+{
+ char *path=ftpState->filepath;
+ int code = ftpState->ctrl.replycode;
+
+ debug(9,3)("Here, with code %d\n",path,code);
+ if (code==257) { /* success */
+ ftpSendCwd(ftpState);
+ } else if (code==550) { /* dir exists */
+ if (EBIT_TEST(ftpState->flags, FTP_PUT_MKDIR)) {
+ EBIT_SET(ftpState->flags, FTP_PUT_MKDIR);
+ ftpSendCwd(ftpState);
+ } else
+ ftpSendReply(ftpState);
+ } else ftpSendReply(ftpState);
+}
+
static void
ftpGetFile(FtpStateData * ftpState)
{
static void
ftpRestOrList(FtpStateData * ftpState)
{
+
debug(9, 3) ("This is ftpRestOrList\n");
- if (ftpState->typecode == 'D') {
+ if (EBIT_TEST(ftpState->flags, FTP_PUT)) {
+ debug(9,3)("ftpRestOrList: Sending STOR request...\n");
+ ftpSendStor(ftpState);
+ } else if (ftpState->typecode == 'D') {
/* XXX This should NOT be here */
ftpSendNlst(ftpState); /* sec 3.2.2 of RFC 1738 */
EBIT_SET(ftpState->flags, FTP_ISDIR);
ftpSendRetr(ftpState);
}
+static void
+ftpSendStor(FtpStateData * ftpState)
+{
+ assert(ftpState->filepath != NULL);
+ snprintf(cbuf, 1024, "STOR %s\r\n", ftpState->filepath);
+ ftpWriteCommand(cbuf, ftpState);
+ ftpState->state = SENT_STOR;
+}
+
+static void
+ftpReadStor(FtpStateData * ftpState)
+{
+ int code = ftpState->ctrl.replycode;
+ debug(9, 3) ("This is ftpReadStor\n");
+ if (code >= 100 && code < 200) {
+ ftpPutStart(ftpState);
+ debug(9, 3) ("ftpReadStor: writing data channel\n");
+ ftpState->state = WRITING_DATA;
+ }
+ else if (code==553) { /* directory does not exist, have to create, sigh */
+#if 0
+ ftpTraverseDirectory(ftpState);
+#endif
+ ftpSendReply(ftpState);
+ } else {
+ debug(9, 3) ("ftpReadStor: that's all folks\n");
+ ftpSendReply(ftpState);
+ }
+}
+
static void
ftpSendRest(FtpStateData * ftpState)
{
comm_close(ftpState->ctrl.fd);
}
+static void
+ftpPutStart(FtpStateData * ftpState)
+{
+ debug(9, 3) ("ftpPutStart\n");
+ pumpStart(ftpState->data.fd, ftpState->entry ,
+ ftpState->request, ftpPutTransferDone, ftpState);
+}
+
+static void
+ftpPutTransferDone(int fd, char *bufnotused, size_t size, int errflag, void *data)
+{
+ FtpStateData * ftpState=(FtpStateData *)data;
+ if (ftpState->data.fd >= 0) {
+ comm_close(ftpState->data.fd);
+ ftpState->data.fd = -1;
+ }
+ ftpReadComplete(ftpState);
+}
+
+static void
+ftpSendReply(FtpStateData * ftpState)
+{
+ ErrorState *err;
+ int code=ftpState->ctrl.replycode;
+ int http_code;
+ int err_code=ERR_NONE;
+ debug(9,5)("ftpSendReply for %x (%d)\n", ftpState,code);
+ if (cbdataValid(ftpState))
+ debug(9,5)("ftpSendReply: ftpState (%p) is valid!\n", ftpState);
+
+
+ if (code==226) {
+ err_code= (ftpState->mdtm>0)?ERR_FTP_PUT_MODIFIED:ERR_FTP_PUT_CREATED;
+ http_code= (ftpState->mdtm>0)?HTTP_ACCEPTED:HTTP_CREATED;
+ } else {
+ err_code = ERR_FTP_PUT_ERROR;
+ http_code=HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ err = errorCon(err_code, http_code);
+ err->request = requestLink(ftpState->request);
+ if (ftpState->old_request)
+ err->ftp.request = ftpState->old_request;
+ else
+ err->ftp.request = ftpState->ctrl.last_command;
+ if (ftpState->old_reply)
+ err->ftp.reply = ftpState->old_reply;
+ else
+ err->ftp.reply = ftpState->ctrl.last_reply;
+
+ errorAppendEntry(ftpState->entry, err);
+
+ storeBufferFlush(ftpState->entry);
+ comm_close(ftpState->ctrl.fd);
+}
+
static void
ftpAppendSuccessHeader(FtpStateData * ftpState)
{
/*
- * $Id: http.cc,v 1.246 1998/03/05 00:42:55 wessels Exp $
+ * $Id: http.cc,v 1.247 1998/03/06 05:43:37 kostas Exp $
*
* DEBUG: section 11 Hypertext Transfer Protocol (HTTP)
* AUTHOR: Harvest Derived
static CNCB httpConnectDone;
static CWCB httpSendComplete;
+static void *sendHeaderDone;
+static CWCB httpSendRequestEntry;
+
static PF httpReadReply;
static PF httpSendRequest;
static PF httpStateFree;
buflen += req->headers_sz + 1;
buflen += 512; /* lots of extra */
- if ((req->method == METHOD_POST || req->method == METHOD_PUT)) {
- debug_trap("httpSendRequest: should not be handling POST/PUT request");
- return;
- }
+ if ((req->method == METHOD_POST || req->method == METHOD_PUT))
+ sendHeaderDone= httpSendRequestEntry;
+ else
+ sendHeaderDone= httpSendComplete;
+
if (buflen < DISK_PAGE_SIZE) {
buf = memAllocate(MEM_8K_BUF);
buftype = BUF_TYPE_8K;
comm_write(fd,
buf,
len,
- httpSendComplete,
+ sendHeaderDone,
httpState,
buftype == BUF_TYPE_8K ? memFree8K : xfree);
#ifdef BREAKS_PCONN_RESTART
return buf;
}
#endif
+
+static void
+httpSendRequestEntry(int fd, char *bufnotused, size_t size, int errflag, void *data)
+{
+ HttpStateData *httpState = data;
+ StoreEntry *entry = httpState->entry;
+ ErrorState *err;
+ debug(11, 5) ("httpSendRequestEntry: FD %d: size %d: errflag %d.\n",
+ fd, size, errflag);
+ if (size > 0) {
+ fd_bytes(fd, size, FD_WRITE);
+ kb_incr(&Counter.server.all.kbytes_out, size);
+ kb_incr(&Counter.server.http.kbytes_out, size);
+ }
+ if (errflag == COMM_ERR_CLOSING)
+ return;
+ if (errflag) {
+ err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);
+ err->xerrno = errno;
+ err->request = requestLink(httpState->orig_request);
+ errorAppendEntry(entry, err);
+ comm_close(fd);
+ return;
+ } else {
+ pumpStart(fd, entry, httpState->orig_request , httpSendComplete, httpState);
+ }
+}