quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

curl_path.c (6433B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl AND ISC
     22  *
     23  ***************************************************************************/
     24 
     25 #include "../curl_setup.h"
     26 
     27 #if defined(USE_SSH)
     28 
     29 #include "curl_path.h"
     30 #include <curl/curl.h>
     31 #include "../curl_memory.h"
     32 #include "../escape.h"
     33 #include "../memdebug.h"
     34 
     35 #define MAX_SSHPATH_LEN 100000 /* arbitrary */
     36 
     37 /* figure out the path to work with in this particular request */
     38 CURLcode Curl_getworkingpath(struct Curl_easy *data,
     39                              char *homedir,  /* when SFTP is used */
     40                              char **path) /* returns the  allocated
     41                                              real path to work with */
     42 {
     43   char *working_path;
     44   size_t working_path_len;
     45   struct dynbuf npath;
     46   CURLcode result =
     47     Curl_urldecode(data->state.up.path, 0, &working_path,
     48                    &working_path_len, REJECT_ZERO);
     49   if(result)
     50     return result;
     51 
     52   /* new path to switch to in case we need to */
     53   curlx_dyn_init(&npath, MAX_SSHPATH_LEN);
     54 
     55   /* Check for /~/, indicating relative to the user's home directory */
     56   if((data->conn->handler->protocol & CURLPROTO_SCP) &&
     57      (working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) {
     58     /* It is referenced to the home directory, so strip the leading '/~/' */
     59     if(curlx_dyn_addn(&npath, &working_path[3], working_path_len - 3)) {
     60       free(working_path);
     61       return CURLE_OUT_OF_MEMORY;
     62     }
     63   }
     64   else if((data->conn->handler->protocol & CURLPROTO_SFTP) &&
     65           (!strcmp("/~", working_path) ||
     66            ((working_path_len > 2) && !memcmp(working_path, "/~/", 3)))) {
     67     if(curlx_dyn_add(&npath, homedir)) {
     68       free(working_path);
     69       return CURLE_OUT_OF_MEMORY;
     70     }
     71     if(working_path_len > 2) {
     72       size_t len;
     73       const char *p;
     74       int copyfrom = 3;
     75       /* Copy a separating '/' if homedir does not end with one */
     76       len = curlx_dyn_len(&npath);
     77       p = curlx_dyn_ptr(&npath);
     78       if(len && (p[len-1] != '/'))
     79         copyfrom = 2;
     80 
     81       if(curlx_dyn_addn(&npath, &working_path[copyfrom],
     82                         working_path_len - copyfrom)) {
     83         free(working_path);
     84         return CURLE_OUT_OF_MEMORY;
     85       }
     86     }
     87     else {
     88       if(curlx_dyn_add(&npath, "/")) {
     89         free(working_path);
     90         return CURLE_OUT_OF_MEMORY;
     91       }
     92     }
     93   }
     94 
     95   if(curlx_dyn_len(&npath)) {
     96     free(working_path);
     97 
     98     /* store the pointer for the caller to receive */
     99     *path = curlx_dyn_ptr(&npath);
    100   }
    101   else
    102     *path = working_path;
    103 
    104   return CURLE_OK;
    105 }
    106 
    107 /* The original get_pathname() function came from OpenSSH sftp.c version
    108    4.6p1. */
    109 /*
    110  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
    111  *
    112  * Permission to use, copy, modify, and distribute this software for any
    113  * purpose with or without fee is hereby granted, provided that the above
    114  * copyright notice and this permission notice appear in all copies.
    115  *
    116  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    117  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    118  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    119  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    120  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    121  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    122  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    123  */
    124 
    125 #define MAX_PATHLENGTH 65535 /* arbitrary long */
    126 
    127 CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir)
    128 {
    129   const char *cp = *cpp, *end;
    130   char quot;
    131   unsigned int i;
    132   static const char WHITESPACE[] = " \t\r\n";
    133   struct dynbuf out;
    134   CURLcode result;
    135 
    136   DEBUGASSERT(homedir);
    137   *path = NULL;
    138   *cpp = NULL;
    139   if(!*cp || !homedir)
    140     return CURLE_QUOTE_ERROR;
    141 
    142   curlx_dyn_init(&out, MAX_PATHLENGTH);
    143 
    144   /* Ignore leading whitespace */
    145   cp += strspn(cp, WHITESPACE);
    146 
    147   /* Check for quoted filenames */
    148   if(*cp == '\"' || *cp == '\'') {
    149     quot = *cp++;
    150 
    151     /* Search for terminating quote, unescape some chars */
    152     for(i = 0; i <= strlen(cp); i++) {
    153       if(cp[i] == quot) {  /* Found quote */
    154         i++;
    155         break;
    156       }
    157       if(cp[i] == '\0') {  /* End of string */
    158         goto fail;
    159       }
    160       if(cp[i] == '\\') {  /* Escaped characters */
    161         i++;
    162         if(cp[i] != '\'' && cp[i] != '\"' &&
    163             cp[i] != '\\') {
    164           goto fail;
    165         }
    166       }
    167       result = curlx_dyn_addn(&out, &cp[i], 1);
    168       if(result)
    169         return result;
    170     }
    171 
    172     if(!curlx_dyn_len(&out))
    173       goto fail;
    174 
    175     /* return pointer to second parameter if it exists */
    176     *cpp = &cp[i] + strspn(&cp[i], WHITESPACE);
    177   }
    178   else {
    179     /* Read to end of filename - either to whitespace or terminator */
    180     end = strpbrk(cp, WHITESPACE);
    181     if(!end)
    182       end = strchr(cp, '\0');
    183 
    184     /* return pointer to second parameter if it exists */
    185     *cpp = end + strspn(end, WHITESPACE);
    186 
    187     /* Handling for relative path - prepend home directory */
    188     if(cp[0] == '/' && cp[1] == '~' && cp[2] == '/') {
    189       result = curlx_dyn_add(&out, homedir);
    190       if(!result)
    191         result = curlx_dyn_addn(&out, "/", 1);
    192       if(result)
    193         return result;
    194       cp += 3;
    195     }
    196     /* Copy path name up until first "whitespace" */
    197     result = curlx_dyn_addn(&out, cp, (end - cp));
    198     if(result)
    199       return result;
    200   }
    201   *path = curlx_dyn_ptr(&out);
    202   return CURLE_OK;
    203 
    204 fail:
    205   curlx_dyn_free(&out);
    206   return CURLE_QUOTE_ERROR;
    207 }
    208 
    209 #endif /* if SSH is used */