Hello,

it seems that some libssh2 SCP functions do not correctly handle
whitespace in file names. When trying to copy a file named "with blanks"
using libssh2_scp_recv() I get an error message.

The reason is that libssh2 builds a "scp" command line that will be
run on the remote side, but does not take care to quote the file
name. It runs the equivalent of the following "ssh" command:

    scp -f with blanks

instead of (note the quotation marks):

    scp -f 'with blanks'

The code causing problems is in libssh2_scp_recv():

    memcpy(session->scpRecv_command, "scp -f ", sizeof("scp -f ") - 1);
    memcpy(session->scpRecv_command + sizeof("scp -f ") - 1, path,
           path_len);

    (Similar code is in libssh2_scp_send()).

Variable "path" should get correct quoting.

I attached the function shell_quotearg() that could be used for quoting
the path name.

Greetings

Heiner

/*
    shell_quotearg - quote arguments for the shell in single quotation marks
    Heiner Steven <[EMAIL PROTECTED]>, Public Domain

    usage:
    	unsigned len;
	char *path, quotedpath[PATH_LEN];

    	len = shell_quotearg(path, quotedpath, sizeof(quotedpath));
	if (len == 0) {
	    fprintf(stderr, "ERROR: path buffer too small (%d bytes)\n",
	    	    sizeof(quotedpath));
	}

	printf("path=<%s>, quotedpath=<%s>\n", path, quotedpath);


    Basically we quote an argument in apostrophes, e.g.
    	one two
    becomes
    	'one two'

    If the string contains an apostrophe itself, we have a special case
    because the shell cannot handle it (the shell syntax 'doesn\'t' will
    not work). Instead we close the current argument word, add a quoted
    apostrophe, and open a new argument word:
         _____   _  _
    	'doesn' \' 't'

    The result buffer must be large enough for the expanded result. The
    worst case regarding expansion are alternating characters and
    apostrophes:

    	a'b'c'd'             (length 8) get converted to
	'a'\''b'\''c'\''d'\' (length 20)

    Maximum size of the result:

    	2 + 5 * length(result) / 2 + 1

    Explanation:
     o	leading + trailing apostrophy
     o	one pair of character and apostrophy (two characters) get
	represented as five characters: a' -> a'\''
     o	String terminator

    A result buffer roughly three times the size of the input buffer
    should be safe.

    Return value:
      Length of the resulting string (not counting the terminating '\0'),
      or 0 in case of errors, e.g. result buffer too small
*/

#include <assert.h>

unsigned shell_quotearg(const char *arg, char *buf, size_t bufsize)
{
    const char *src;
    char *dst, *endp;
    bool_t instring;

    assert(arg);
    assert (buf && bufsize >= 3);	/* Smallest result: "''" */

    endp = &buf[bufsize];
    src = arg;
    dst = buf;
    instring = false;		/* Are we within a ' string? */
    while (*src && dst < endp - 1) {
    	if (*src != '\'') {
	    if (!instring) {
	    	if (dst+2 >= endp) return 0;
	    	*dst++ = '\'';
		instring = true;
	    }
	    *dst++ = *src++;
	    continue;
	}

	if (instring) {
	    if (dst+3 >= endp) return 0;
	    *dst++ = '\'';
	    *dst++ = '\\';
	    *dst++ = '\'';
	    instring = false;
	} else {
	    if (dst+2 >= endp) return 0;
	    *dst++ = '\\';
	    *dst++ = '\'';
	}
	src++;
    }

    if (instring) {
	if (dst+1 >= endp) return 0;
    	*dst++ = '\'';
    }

    *dst = '\0';
    return dst - buf;
}
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
libssh2-devel mailing list
libssh2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libssh2-devel

Reply via email to