]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
SFTP: support '*' prefix for quote operations
authorJonas Schnelli <jonas.schnelli@include7.ch>
Fri, 18 Nov 2011 14:55:09 +0000 (15:55 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 18 Nov 2011 15:04:52 +0000 (16:04 +0100)
prefixing a command with '*' means it is allowed to fail without
aborting the chain actions

docs/libcurl/symbols-in-versions
lib/ssh.c
lib/ssh.h
tests/data/Makefile.am

index 8c1792c88a8845e03ddcc391af0d4ed39b0fb572..ec902fd4e493c645f8b639c43f584cd37ad60b79 100644 (file)
@@ -320,6 +320,7 @@ CURLOPT_DEBUGDATA               7.9.6
 CURLOPT_DEBUGFUNCTION           7.9.6
 CURLOPT_DIRLISTONLY             7.17.0
 CURLOPT_DNS_CACHE_TIMEOUT       7.9.3
+CURLOPT_DNS_SERVERS             7.24.0
 CURLOPT_DNS_USE_GLOBAL_CACHE    7.9.3         7.11.1
 CURLOPT_EGDSOCKET               7.7
 CURLOPT_ENCODING                7.10
index a9e4c56e47ef8ea72c791d4c1b342b3ae0cee720..410f3973060cef6996f960ef2eb6e8f5f9184a6d 100644 (file)
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -1063,7 +1063,20 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       /*
        * Support some of the "FTP" commands
        */
-      if(curl_strequal("pwd", sshc->quote_item->data)) {
+      char *cmd = sshc->quote_item->data;
+      sshc->acceptfail = FALSE;
+
+      /* if a command starts with an asterisk, which a legal SFTP command never
+         can, the command will be allowed to fail without it causing any
+         aborts or cancels etc. It will cause libcurl to act as if the command
+         is successful, whatever the server reponds. */
+
+      if(cmd[0] == '*') {
+        cmd++;
+        sshc->acceptfail = TRUE;
+      }
+
+      if(curl_strequal("pwd", cmd)) {
         /* output debug output if that is requested */
         char *tmp = aprintf("257 \"%s\" is current directory.\n",
                             sftp_scp->path);
@@ -1085,12 +1098,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         state(conn, SSH_SFTP_NEXT_QUOTE);
         break;
       }
-      else if(sshc->quote_item->data) {
+      else if(cmd) {
         /*
          * the arguments following the command must be separated from the
          * command with a space so we can check for it unconditionally
          */
-        cp = strchr(sshc->quote_item->data, ' ');
+        cp = strchr(cmd, ' ');
         if(cp == NULL) {
           failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
           state(conn, SSH_SFTP_CLOSE);
@@ -1121,9 +1134,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
          * OpenSSH's sftp program and call the appropriate libssh2
          * functions.
          */
-        if(curl_strnequal(sshc->quote_item->data, "chgrp ", 6) ||
-           curl_strnequal(sshc->quote_item->data, "chmod ", 6) ||
-           curl_strnequal(sshc->quote_item->data, "chown ", 6) ) {
+        if(curl_strnequal(cmd, "chgrp ", 6) ||
+           curl_strnequal(cmd, "chmod ", 6) ||
+           curl_strnequal(cmd, "chown ", 6) ) {
           /* attribute change */
 
           /* sshc->quote_path1 contains the mode to set */
@@ -1146,8 +1159,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           state(conn, SSH_SFTP_QUOTE_STAT);
           break;
         }
-        else if(curl_strnequal(sshc->quote_item->data, "ln ", 3) ||
-                curl_strnequal(sshc->quote_item->data, "symlink ", 8)) {
+        else if(curl_strnequal(cmd, "ln ", 3) ||
+                curl_strnequal(cmd, "symlink ", 8)) {
           /* symbolic linking */
           /* sshc->quote_path1 is the source */
           /* get the destination */
@@ -1168,12 +1181,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           state(conn, SSH_SFTP_QUOTE_SYMLINK);
           break;
         }
-        else if(curl_strnequal(sshc->quote_item->data, "mkdir ", 6)) {
+        else if(curl_strnequal(cmd, "mkdir ", 6)) {
           /* create dir */
           state(conn, SSH_SFTP_QUOTE_MKDIR);
           break;
         }
-        else if(curl_strnequal(sshc->quote_item->data, "rename ", 7)) {
+        else if(curl_strnequal(cmd, "rename ", 7)) {
           /* rename file */
           /* first param is the source path */
           /* second param is the dest. path */
@@ -1193,12 +1206,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           state(conn, SSH_SFTP_QUOTE_RENAME);
           break;
         }
-        else if(curl_strnequal(sshc->quote_item->data, "rmdir ", 6)) {
+        else if(curl_strnequal(cmd, "rmdir ", 6)) {
           /* delete dir */
           state(conn, SSH_SFTP_QUOTE_RMDIR);
           break;
         }
-        else if(curl_strnequal(sshc->quote_item->data, "rm ", 3)) {
+        else if(curl_strnequal(cmd, "rm ", 3)) {
           state(conn, SSH_SFTP_QUOTE_UNLINK);
           break;
         }
@@ -1246,7 +1259,21 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       break;
 
     case SSH_SFTP_QUOTE_STAT:
-      if(!curl_strnequal(sshc->quote_item->data, "chmod", 5)) {
+    {
+      char *cmd = sshc->quote_item->data;
+      sshc->acceptfail = FALSE;
+
+      /* if a command starts with an asterisk, which a legal SFTP command never
+         can, the command will be allowed to fail without it causing any
+         aborts or cancels etc. It will cause libcurl to act as if the command
+         is successful, whatever the server reponds. */
+
+      if(cmd[0] == '*') {
+        cmd++;
+        sshc->acceptfail = TRUE;
+      }
+
+      if(!curl_strnequal(cmd, "chmod", 5)) {
         /* Since chown and chgrp only set owner OR group but libssh2 wants to
          * set them both at once, we need to obtain the current ownership
          * first.  This takes an extra protocol round trip.
@@ -1258,7 +1285,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc != 0) { /* get those attributes */
+        else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
           err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
           Curl_safefree(sshc->quote_path1);
           sshc->quote_path1 = NULL;
@@ -1274,10 +1301,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       }
 
       /* Now set the new attributes... */
-      if(curl_strnequal(sshc->quote_item->data, "chgrp", 5)) {
+      if(curl_strnequal(cmd, "chgrp", 5)) {
         sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
         sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
-        if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0])) {
+        if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+           !sshc->acceptfail) {
           Curl_safefree(sshc->quote_path1);
           sshc->quote_path1 = NULL;
           Curl_safefree(sshc->quote_path2);
@@ -1289,7 +1317,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           break;
         }
       }
-      else if(curl_strnequal(sshc->quote_item->data, "chmod", 5)) {
+      else if(curl_strnequal(cmd, "chmod", 5)) {
         sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
         sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
         /* permissions are octal */
@@ -1306,10 +1334,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           break;
         }
       }
-      else if(curl_strnequal(sshc->quote_item->data, "chown", 5)) {
+      else if(curl_strnequal(cmd, "chown", 5)) {
         sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
         sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
-        if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0])) {
+        if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+           !sshc->acceptfail) {
           Curl_safefree(sshc->quote_path1);
           sshc->quote_path1 = NULL;
           Curl_safefree(sshc->quote_path2);
@@ -1325,6 +1354,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       /* Now send the completed structure... */
       state(conn, SSH_SFTP_QUOTE_SETSTAT);
       break;
+    }
 
     case SSH_SFTP_QUOTE_SETSTAT:
       rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
@@ -1334,7 +1364,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0) {
+      else if(rc != 0 && !sshc->acceptfail) {
         err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
         Curl_safefree(sshc->quote_path1);
         sshc->quote_path1 = NULL;
@@ -1359,7 +1389,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0) {
+      else if(rc != 0 && !sshc->acceptfail) {
         err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
         Curl_safefree(sshc->quote_path1);
         sshc->quote_path1 = NULL;
@@ -1382,7 +1412,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0) {
+      else if(rc != 0 && !sshc->acceptfail) {
         err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
         Curl_safefree(sshc->quote_path1);
         sshc->quote_path1 = NULL;
@@ -1407,7 +1437,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0) {
+      else if(rc != 0 && !sshc->acceptfail) {
         err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
         Curl_safefree(sshc->quote_path1);
         sshc->quote_path1 = NULL;
@@ -1428,7 +1458,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0) {
+      else if(rc != 0 && !sshc->acceptfail) {
         err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
         Curl_safefree(sshc->quote_path1);
         sshc->quote_path1 = NULL;
@@ -1447,7 +1477,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0) {
+      else if(rc != 0 && !sshc->acceptfail) {
         err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
         Curl_safefree(sshc->quote_path1);
         sshc->quote_path1 = NULL;
index 6257b96fcf6bdf817b8acea80a110d7023ccefb6..7ab5255c1459dc02222826bd8d3b18d05ba441fa 100644 (file)
--- a/lib/ssh.h
+++ b/lib/ssh.h
@@ -115,6 +115,7 @@ struct ssh_conn {
   char *quote_path1;          /* two generic pointers for the QUOTE stuff */
   char *quote_path2;
   LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
+  bool acceptfail;            /* accept file in SFTP_QUOTE state */
   char *homedir;              /* when doing SFTP we figure out home dir in the
                                  connect phase */
 
index fdfa75547af489c0712a332d22192da9bbc36a2e..581d46b86120c5d8fee63d2d2d73ecff43b39139 100644 (file)
@@ -53,8 +53,9 @@ test600 test601 test602 test603 test604       \
 test605 test606 test607 test608 test609 test610 test611 test612 test613        \
 test614 test615 test616 test617 test618 test619 test620 test621 test622        \
 test623 test624 test625 test626 test627 test628 test629 test630 test631        \
-test632 test633 test634 test635 test636 test637 test700 test701 test702        \
-test703 test704 test705 test706 test707 test708 test709 test710 \
+test632 test633 test634 test635 test636 test637 test638 test639 \
+test700 test701 test702        test703 test704 test705 test706 test707 test708 \
+test709 test710 \
 test800 test801 test802        \
 test803 test804 test805 test806 test807 test808 test809 test810 test811        \
 test812 test813 test814 \