cmake/Utilities/cmcurl/lib/curl_path.c

200 lines
6.2 KiB
C
Raw Normal View History

2018-04-23 21:13:27 +02:00
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
2023-07-02 19:51:09 +02:00
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
2018-04-23 21:13:27 +02:00
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
2021-09-14 00:13:48 +02:00
* are also available at https://curl.se/docs/copyright.html.
2018-04-23 21:13:27 +02:00
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
2022-11-16 20:14:03 +01:00
* SPDX-License-Identifier: curl AND ISC
*
2018-04-23 21:13:27 +02:00
***************************************************************************/
#include "curl_setup.h"
2019-11-11 23:01:05 +01:00
#if defined(USE_SSH)
2018-04-23 21:13:27 +02:00
#include <curl/curl.h>
#include "curl_memory.h"
#include "curl_path.h"
#include "escape.h"
#include "memdebug.h"
2023-07-02 19:51:09 +02:00
#define MAX_SSHPATH_LEN 100000 /* arbitrary */
2018-04-23 21:13:27 +02:00
/* figure out the path to work with in this particular request */
2021-09-14 00:13:48 +02:00
CURLcode Curl_getworkingpath(struct Curl_easy *data,
2018-04-23 21:13:27 +02:00
char *homedir, /* when SFTP is used */
char **path) /* returns the allocated
real path to work with */
{
char *working_path;
size_t working_path_len;
2023-07-02 19:51:09 +02:00
struct dynbuf npath;
2018-04-23 21:13:27 +02:00
CURLcode result =
2022-08-04 22:12:04 +02:00
Curl_urldecode(data->state.up.path, 0, &working_path,
2020-08-30 11:54:41 +02:00
&working_path_len, REJECT_ZERO);
2018-04-23 21:13:27 +02:00
if(result)
return result;
2023-07-02 19:51:09 +02:00
/* new path to switch to in case we need to */
Curl_dyn_init(&npath, MAX_SSHPATH_LEN);
2018-04-23 21:13:27 +02:00
/* Check for /~/, indicating relative to the user's home directory */
2023-07-02 19:51:09 +02:00
if((data->conn->handler->protocol & CURLPROTO_SCP) &&
(working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) {
/* It is referenced to the home directory, so strip the leading '/~/' */
if(Curl_dyn_addn(&npath, &working_path[3], working_path_len - 3)) {
2018-04-23 21:13:27 +02:00
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
}
2023-07-02 19:51:09 +02:00
else if((data->conn->handler->protocol & CURLPROTO_SFTP) &&
(!strcmp("/~", working_path) ||
((working_path_len > 2) && !memcmp(working_path, "/~/", 3)))) {
if(Curl_dyn_add(&npath, homedir)) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
2018-04-23 21:13:27 +02:00
}
2023-07-02 19:51:09 +02:00
if(working_path_len > 2) {
size_t len;
const char *p;
int copyfrom = 3;
/* Copy a separating '/' if homedir does not end with one */
len = Curl_dyn_len(&npath);
p = Curl_dyn_ptr(&npath);
if(len && (p[len-1] != '/'))
copyfrom = 2;
if(Curl_dyn_addn(&npath,
&working_path[copyfrom], working_path_len - copyfrom)) {
2018-04-23 21:13:27 +02:00
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
}
}
2023-07-02 19:51:09 +02:00
if(Curl_dyn_len(&npath)) {
free(working_path);
2018-04-23 21:13:27 +02:00
2023-07-02 19:51:09 +02:00
/* store the pointer for the caller to receive */
*path = Curl_dyn_ptr(&npath);
}
else
*path = working_path;
2018-04-23 21:13:27 +02:00
return CURLE_OK;
}
/* The get_pathname() function is being borrowed from OpenSSH sftp.c
version 4.6p1. */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
{
const char *cp = *cpp, *end;
char quot;
unsigned int i, j;
size_t fullPathLength, pathLength;
bool relativePath = false;
static const char WHITESPACE[] = " \t\r\n";
2022-11-16 20:14:03 +01:00
DEBUGASSERT(homedir);
if(!*cp || !homedir) {
2018-04-23 21:13:27 +02:00
*cpp = NULL;
*path = NULL;
return CURLE_QUOTE_ERROR;
}
/* Ignore leading whitespace */
cp += strspn(cp, WHITESPACE);
/* Allocate enough space for home directory and filename + separator */
fullPathLength = strlen(cp) + strlen(homedir) + 2;
*path = malloc(fullPathLength);
2021-09-14 00:13:48 +02:00
if(!*path)
2018-04-23 21:13:27 +02:00
return CURLE_OUT_OF_MEMORY;
/* Check for quoted filenames */
if(*cp == '\"' || *cp == '\'') {
quot = *cp++;
/* Search for terminating quote, unescape some chars */
for(i = j = 0; i <= strlen(cp); i++) {
if(cp[i] == quot) { /* Found quote */
i++;
(*path)[j] = '\0';
break;
}
if(cp[i] == '\0') { /* End of string */
goto fail;
}
if(cp[i] == '\\') { /* Escaped characters */
i++;
if(cp[i] != '\'' && cp[i] != '\"' &&
cp[i] != '\\') {
goto fail;
}
}
(*path)[j++] = cp[i];
}
if(j == 0) {
goto fail;
}
*cpp = cp + i + strspn(cp + i, WHITESPACE);
}
else {
2021-09-14 00:13:48 +02:00
/* Read to end of filename - either to whitespace or terminator */
2018-04-23 21:13:27 +02:00
end = strpbrk(cp, WHITESPACE);
2021-09-14 00:13:48 +02:00
if(!end)
2018-04-23 21:13:27 +02:00
end = strchr(cp, '\0');
/* return pointer to second parameter if it exists */
*cpp = end + strspn(end, WHITESPACE);
pathLength = 0;
relativePath = (cp[0] == '/' && cp[1] == '~' && cp[2] == '/');
/* Handling for relative path - prepend home directory */
if(relativePath) {
strcpy(*path, homedir);
pathLength = strlen(homedir);
(*path)[pathLength++] = '/';
(*path)[pathLength] = '\0';
cp += 3;
}
2021-09-14 00:13:48 +02:00
/* Copy path name up until first "whitespace" */
2018-04-23 21:13:27 +02:00
memcpy(&(*path)[pathLength], cp, (int)(end - cp));
pathLength += (int)(end - cp);
(*path)[pathLength] = '\0';
}
return CURLE_OK;
2023-07-02 19:51:09 +02:00
fail:
2018-04-23 21:13:27 +02:00
Curl_safefree(*path);
return CURLE_QUOTE_ERROR;
}
2019-11-11 23:01:05 +01:00
#endif /* if SSH is used */