This patch against sitecopy 0.11.4 (currently latest version) adds the new
keywords

	ftp usecwd
	ftp nousecwd

which control whether to use change-directory commands before uploading a file.
This makes sitecopy work with servers which return an error when using a path
with the STOR command (ftp protocol) and the file already exists (which is the
common case when updating sites).

The default behaviour is the same as previosuly, which is the same as nousecwd
(however the default may change).

Setting usecwd is safe with all servers, it merely increases ftp traffic by a
very fractional amount.

I have tested that ftp usecwd and ftp nousecwd as well as the lack of either
works as desired, and that the dir changing works with passive and active ftp.

TODO: make usecwd work with relative remote paths (keyword remote).

This patch is also located at
	http://volker.orcon.net.nz/soft/sitecopy-0.11.4-CWDpatch.diff

More info:
	http://dav.lyra.org/pipermail/sitecopy/2002-March/001061.html
	http://dav.lyra.org/pipermail/sitecopy/2002-March/001062.html
	http://dav.lyra.org/pipermail/sitecopy/2002-April/001066.html
	http://dav.lyra.org/pipermail/sitecopy/2002-April/001068.html

07, 08 Apr 2002, Volker Kuhlmann <VolkerKuhlmann@GMX.de>


This patch was included in the current sitecopy (CVS?), although somewhat
rewritten.  - Volker



--- sitecopy-0.11.4/doc/sitecopy.1.orig	Mon Sep 24 06:50:41 2001
+++ sitecopy-0.11.4/doc/sitecopy.1	Sun Apr  7 13:56:16 2002
@@ -298,6 +298,9 @@
 .BR ftp " showquit ]"
 .br
  [ 
+.BR ftp " { usecwd | nousecwd } ]"
+.br
+ [ 
 .BR http " expect ]"
 .br
  [ 
@@ -364,6 +367,17 @@
 on closing the connection, use the 
 .B ftp showquit
 option.
+If the server does not support uploading files with paths and therefore needs a
+change-dir command before uploading a file, use the key
+.B ftp usecwd
+(possible symptom: "overwrite permission denied"). To make sitecopy not to
+change directory on the remote server, use
+.B ftp nousecwd
+(currently default). Note that the remote-directory (keyword
+.B remote\fP)
+must be an absolute path (starting with '/'), or
+.B usecwd
+will be ignored.
 
 If the WebDAV server correctly supports the 100-continue
 expectation, e.g. Apache 1.3.9 and later, the key
--- sitecopy-0.11.4/src/ftp.c.orig	Fri Jan  4 03:27:34 2002
+++ sitecopy-0.11.4/src/ftp.c	Sun Apr  7 13:30:39 2002
@@ -37,6 +37,7 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <time.h>
+#include <limits.h> 	/* for PATH_MAX */
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
@@ -68,6 +69,7 @@
     /* User options */
     unsigned int use_passive:1;
     unsigned int echo_quit:1;
+    unsigned int use_cwd:1; /* CWD before STOR */
 
     unsigned int connection:1; /* true when open */
 
@@ -92,6 +94,9 @@
      *   1: ASCII
      */
     int using_ascii;
+	
+    /* Stores the current working dir on the remote server */
+    char cwd[PATH_MAX];
 
     /* time from MDTM response... bit crap having this here. */
     time_t get_modtime;
@@ -277,6 +282,7 @@
     ftp_session *sess = ne_calloc(sizeof(ftp_session));
     sess->connection = 0;
     sess->using_ascii = -1; /* unknown */
+    sess->cwd[0] = '\0'; /* current dir on server is the login dir */
     return sess;
 }
 
@@ -285,6 +291,11 @@
     sess->use_passive = use_passive;
 }
 
+void ftp_set_usecwd(ftp_session *sess, int use_cwd) 
+{
+    sess->use_cwd = use_cwd;
+}
+
 int ftp_set_server(ftp_session *sess, struct site_host *server)
 {
     if (server->username) {
@@ -543,6 +554,38 @@
     return ret;
 }
 
+/* Change dir before uploading
+   Problem: STOR /some/path/file fails for the server my hoster is using if
+   the file exists (error overwrite permission denied, proftp 1.2.5rc1).
+   However, a CWD to /some/ fixes that. Yes, seems dumb, but it's true.
+   perhaps it has to do with the /some/ part being equal to the server's FQDN
+   and virtual hosting.
+   5, 7 Apr 2002, Volker Kuhlmann <VolkerKuhlmann@GMX.de>
+*/
+static int ftp_chdir(ftp_session *sess, const char *remotefile)
+{
+    char dir[PATH_MAX], *lastslash;
+    int len;
+
+    /* Do nothing unless remote path of file to be uploaded is absolute. */
+    if (remotefile[0] != '/') return FTP_OK;
+    
+    /* Obtain dir name component of file to be uploaded */
+    lastslash = strrchr(remotefile, '/');   /* can't be NULL here */
+    len = lastslash - remotefile;
+    strncpy(dir, remotefile, len);  /* we assume here remotefile was checked
+    	    	    	    	    	 for PATH_MAX before */
+    dir[len] = '\0';
+
+    if (strcmp(sess->cwd, dir)) {
+    	int ret = ftp_exec(sess, "CWD %s", dir);
+	if (ret == FTP_OK) strcpy(sess->cwd, dir);
+	return ret;
+    }
+
+    return FTP_OK;
+}
+
 /* upload the given file */
 int ftp_put(ftp_session *sess, 
 	    const char *localfile, const char *remotefile, int ascii) 
@@ -574,6 +617,19 @@
 	return FTP_ERROR;
     }
 
+    if (sess->use_cwd) {
+    	char *slash;
+	
+    	ret = ftp_chdir (sess, remotefile);
+	if (ret != FTP_OK)
+	    return ret;
+	
+	/* strip path off remotefile */
+	slash = strrchr(remotefile, '/');
+	if (slash != NULL && *slash == '/') {
+	    remotefile = slash + 1; /* can remotefile[] be empty string now? */
+	}
+    }
     ret = ftp_data_open(sess, "STOR %s", remotefile);
     if (ret == FTP_READY) {
 
--- sitecopy-0.11.4/src/ftpdriver.c.orig	Fri Jan  4 03:27:34 2002
+++ sitecopy-0.11.4/src/ftpdriver.c	Sun Apr  7 13:30:39 2002
@@ -59,6 +59,9 @@
 	if (site->ftp_pasv_mode) {
 	    ftp_set_passive(sess, 1);
 	}
+	if (site->ftp_use_cwd) {
+	    ftp_set_usecwd(sess, 1);
+	}
 	ret = ftp_open(sess);
     }
     *session = sess;
--- sitecopy-0.11.4/src/rcfile.c.orig	Mon Sep 24 07:37:23 2001
+++ sitecopy-0.11.4/src/rcfile.c	Sun Apr  7 13:30:39 2002
@@ -108,6 +108,7 @@
     default_site.symlinks = sitesym_follow;
     default_site.protocol = siteproto_ftp;
     default_site.ftp_pasv_mode = true;
+    default_site.ftp_use_cwd = false;
     
     last_site = this_site = NULL;
     rcfile_linenum = 0;
@@ -387,6 +388,10 @@
 		    this_site->ftp_pasv_mode = false;
 		} else if (strcmp(val, "showquit") == 0) {
 		    this_site->ftp_echo_quit = true;		    
+		} else if (strcmp(val, "usecwd") == 0) {
+		    this_site->ftp_use_cwd = true;		    
+		} else if (strcmp(val, "nousecwd") == 0) {
+		    this_site->ftp_use_cwd = false;		    
 		} else {
 		    ret = RC_CORRUPT;
 		}
@@ -740,6 +745,7 @@
 	
 	RCWRITEBOOL(!current->ftp_pasv_mode, "ftp nopasv");
 	RCWRITEBOOL(current->ftp_echo_quit, "ftp showquit");
+	RCWRITEBOOL(current->ftp_use_cwd, "ftp usecwd");
 	RCWRITEBOOL(current->http_limit, "http limit");
 	RCWRITEBOOL(current->http_use_expect, "http expect");
 	
--- sitecopy-0.11.4/src/sites.h.orig	Fri Jan  4 03:27:34 2002
+++ sitecopy-0.11.4/src/sites.h	Sun Apr  7 13:30:39 2002
@@ -371,6 +371,7 @@
     /* Protocol-driver specific options here */
     unsigned int ftp_pasv_mode:1;
     unsigned int ftp_echo_quit:1;
+    unsigned int ftp_use_cwd:1;
     unsigned int ftp_forcecd:1;
     unsigned int http_use_expect:1;
     unsigned int http_limit:1;
--- sitecopy-0.11.4/configure.in.orig	Mon Jan 14 11:10:38 2002
+++ sitecopy-0.11.4/configure.in	Sun Apr  7 13:30:39 2002
@@ -30,7 +30,7 @@
 dnl Setup some defaults
 
 PACKAGE="sitecopy"
-VERSION="0.11.4"
+VERSION="0.11.4-CWDpatch"
 LIBOBJS=""
 EXTRAOBJS=""
 SUBDIRS="libneon"

