quickjs-tart

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

dict.c (8853B)


      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
     22  *
     23  ***************************************************************************/
     24 
     25 #include "curl_setup.h"
     26 
     27 #ifndef CURL_DISABLE_DICT
     28 
     29 #ifdef HAVE_NETINET_IN_H
     30 #include <netinet/in.h>
     31 #endif
     32 #ifdef HAVE_NETDB_H
     33 #include <netdb.h>
     34 #endif
     35 #ifdef HAVE_ARPA_INET_H
     36 #include <arpa/inet.h>
     37 #endif
     38 #ifdef HAVE_NET_IF_H
     39 #include <net/if.h>
     40 #endif
     41 #ifdef HAVE_SYS_IOCTL_H
     42 #include <sys/ioctl.h>
     43 #endif
     44 
     45 #ifdef HAVE_SYS_PARAM_H
     46 #include <sys/param.h>
     47 #endif
     48 
     49 #ifdef HAVE_SYS_SELECT_H
     50 #include <sys/select.h>
     51 #elif defined(HAVE_UNISTD_H)
     52 #include <unistd.h>
     53 #endif
     54 
     55 #include "urldata.h"
     56 #include <curl/curl.h>
     57 #include "transfer.h"
     58 #include "sendf.h"
     59 #include "escape.h"
     60 #include "progress.h"
     61 #include "dict.h"
     62 #include "curl_printf.h"
     63 #include "curl_memory.h"
     64 /* The last #include file should be: */
     65 #include "memdebug.h"
     66 
     67 
     68 #define DICT_MATCH "/MATCH:"
     69 #define DICT_MATCH2 "/M:"
     70 #define DICT_MATCH3 "/FIND:"
     71 #define DICT_DEFINE "/DEFINE:"
     72 #define DICT_DEFINE2 "/D:"
     73 #define DICT_DEFINE3 "/LOOKUP:"
     74 
     75 
     76 /*
     77  * Forward declarations.
     78  */
     79 
     80 static CURLcode dict_do(struct Curl_easy *data, bool *done);
     81 
     82 /*
     83  * DICT protocol handler.
     84  */
     85 
     86 const struct Curl_handler Curl_handler_dict = {
     87   "dict",                               /* scheme */
     88   ZERO_NULL,                            /* setup_connection */
     89   dict_do,                              /* do_it */
     90   ZERO_NULL,                            /* done */
     91   ZERO_NULL,                            /* do_more */
     92   ZERO_NULL,                            /* connect_it */
     93   ZERO_NULL,                            /* connecting */
     94   ZERO_NULL,                            /* doing */
     95   ZERO_NULL,                            /* proto_getsock */
     96   ZERO_NULL,                            /* doing_getsock */
     97   ZERO_NULL,                            /* domore_getsock */
     98   ZERO_NULL,                            /* perform_getsock */
     99   ZERO_NULL,                            /* disconnect */
    100   ZERO_NULL,                            /* write_resp */
    101   ZERO_NULL,                            /* write_resp_hd */
    102   ZERO_NULL,                            /* connection_check */
    103   ZERO_NULL,                            /* attach connection */
    104   ZERO_NULL,                            /* follow */
    105   PORT_DICT,                            /* defport */
    106   CURLPROTO_DICT,                       /* protocol */
    107   CURLPROTO_DICT,                       /* family */
    108   PROTOPT_NONE | PROTOPT_NOURLQUERY     /* flags */
    109 };
    110 
    111 #define DYN_DICT_WORD 10000
    112 static char *unescape_word(const char *input)
    113 {
    114   struct dynbuf out;
    115   const char *ptr;
    116   CURLcode result = CURLE_OK;
    117   curlx_dyn_init(&out, DYN_DICT_WORD);
    118 
    119   /* According to RFC2229 section 2.2, these letters need to be escaped with
    120      \[letter] */
    121   for(ptr = input; *ptr; ptr++) {
    122     char ch = *ptr;
    123     if((ch <= 32) || (ch == 127) ||
    124        (ch == '\'') || (ch == '\"') || (ch == '\\'))
    125       result = curlx_dyn_addn(&out, "\\", 1);
    126     if(!result)
    127       result = curlx_dyn_addn(&out, ptr, 1);
    128     if(result)
    129       return NULL;
    130   }
    131   return curlx_dyn_ptr(&out);
    132 }
    133 
    134 /* sendf() sends formatted data to the server */
    135 static CURLcode sendf(struct Curl_easy *data,
    136                       const char *fmt, ...) CURL_PRINTF(2, 3);
    137 
    138 static CURLcode sendf(struct Curl_easy *data, const char *fmt, ...)
    139 {
    140   size_t bytes_written;
    141   size_t write_len;
    142   CURLcode result = CURLE_OK;
    143   char *s;
    144   char *sptr;
    145   va_list ap;
    146   va_start(ap, fmt);
    147   s = vaprintf(fmt, ap); /* returns an allocated string */
    148   va_end(ap);
    149   if(!s)
    150     return CURLE_OUT_OF_MEMORY; /* failure */
    151 
    152   bytes_written = 0;
    153   write_len = strlen(s);
    154   sptr = s;
    155 
    156   for(;;) {
    157     /* Write the buffer to the socket */
    158     result = Curl_xfer_send(data, sptr, write_len, FALSE, &bytes_written);
    159 
    160     if(result)
    161       break;
    162 
    163     Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);
    164 
    165     if((size_t)bytes_written != write_len) {
    166       /* if not all was written at once, we must advance the pointer, decrease
    167          the size left and try again! */
    168       write_len -= bytes_written;
    169       sptr += bytes_written;
    170     }
    171     else
    172       break;
    173   }
    174 
    175   free(s); /* free the output string */
    176 
    177   return result;
    178 }
    179 
    180 static CURLcode dict_do(struct Curl_easy *data, bool *done)
    181 {
    182   char *word;
    183   char *eword = NULL;
    184   char *ppath;
    185   char *database = NULL;
    186   char *strategy = NULL;
    187   char *nthdef = NULL; /* This is not part of the protocol, but required
    188                           by RFC 2229 */
    189   CURLcode result;
    190 
    191   char *path;
    192 
    193   *done = TRUE; /* unconditionally */
    194 
    195   /* url-decode path before further evaluation */
    196   result = Curl_urldecode(data->state.up.path, 0, &path, NULL, REJECT_CTRL);
    197   if(result)
    198     return result;
    199 
    200   if(curl_strnequal(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
    201      curl_strnequal(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
    202      curl_strnequal(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
    203 
    204     word = strchr(path, ':');
    205     if(word) {
    206       word++;
    207       database = strchr(word, ':');
    208       if(database) {
    209         *database++ = (char)0;
    210         strategy = strchr(database, ':');
    211         if(strategy) {
    212           *strategy++ = (char)0;
    213           nthdef = strchr(strategy, ':');
    214           if(nthdef) {
    215             *nthdef = (char)0;
    216           }
    217         }
    218       }
    219     }
    220 
    221     if(!word || (*word == (char)0)) {
    222       infof(data, "lookup word is missing");
    223     }
    224     eword = unescape_word((!word || (*word == (char)0)) ? "default" : word);
    225     if(!eword) {
    226       result = CURLE_OUT_OF_MEMORY;
    227       goto error;
    228     }
    229 
    230     result = sendf(data,
    231                    "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
    232                    "MATCH "
    233                    "%s "    /* database */
    234                    "%s "    /* strategy */
    235                    "%s\r\n" /* word */
    236                    "QUIT\r\n",
    237                    (!database || (*database == (char)0)) ? "!" : database,
    238                    (!strategy || (*strategy == (char)0)) ? "." : strategy,
    239                    eword);
    240 
    241     if(result) {
    242       failf(data, "Failed sending DICT request");
    243       goto error;
    244     }
    245     Curl_xfer_setup1(data, CURL_XFER_RECV, -1, FALSE); /* no upload */
    246   }
    247   else if(curl_strnequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
    248           curl_strnequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
    249           curl_strnequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
    250 
    251     word = strchr(path, ':');
    252     if(word) {
    253       word++;
    254       database = strchr(word, ':');
    255       if(database) {
    256         *database++ = (char)0;
    257         nthdef = strchr(database, ':');
    258         if(nthdef) {
    259           *nthdef = (char)0;
    260         }
    261       }
    262     }
    263 
    264     if(!word || (*word == (char)0)) {
    265       infof(data, "lookup word is missing");
    266     }
    267     eword = unescape_word((!word || (*word == (char)0)) ? "default" : word);
    268     if(!eword) {
    269       result = CURLE_OUT_OF_MEMORY;
    270       goto error;
    271     }
    272 
    273     result = sendf(data,
    274                    "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
    275                    "DEFINE "
    276                    "%s "     /* database */
    277                    "%s\r\n"  /* word */
    278                    "QUIT\r\n",
    279                    (!database || (*database == (char)0)) ? "!" : database,
    280                    eword);
    281 
    282     if(result) {
    283       failf(data, "Failed sending DICT request");
    284       goto error;
    285     }
    286     Curl_xfer_setup1(data, CURL_XFER_RECV, -1, FALSE);
    287   }
    288   else {
    289 
    290     ppath = strchr(path, '/');
    291     if(ppath) {
    292       int i;
    293 
    294       ppath++;
    295       for(i = 0; ppath[i]; i++) {
    296         if(ppath[i] == ':')
    297           ppath[i] = ' ';
    298       }
    299       result = sendf(data,
    300                      "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
    301                      "%s\r\n"
    302                      "QUIT\r\n", ppath);
    303       if(result) {
    304         failf(data, "Failed sending DICT request");
    305         goto error;
    306       }
    307 
    308       Curl_xfer_setup1(data, CURL_XFER_RECV, -1, FALSE);
    309     }
    310   }
    311 
    312 error:
    313   free(eword);
    314   free(path);
    315   return result;
    316 }
    317 #endif /* CURL_DISABLE_DICT */