Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) 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.haxx.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  ***************************************************************************/
     22 
     23 #include "curl_setup.h"
     24 
     25 #ifndef CURL_DISABLE_DICT
     26 
     27 #ifdef HAVE_NETINET_IN_H
     28 #include <netinet/in.h>
     29 #endif
     30 #ifdef HAVE_NETDB_H
     31 #include <netdb.h>
     32 #endif
     33 #ifdef HAVE_ARPA_INET_H
     34 #include <arpa/inet.h>
     35 #endif
     36 #ifdef HAVE_NET_IF_H
     37 #include <net/if.h>
     38 #endif
     39 #ifdef HAVE_SYS_IOCTL_H
     40 #include <sys/ioctl.h>
     41 #endif
     42 
     43 #ifdef HAVE_SYS_PARAM_H
     44 #include <sys/param.h>
     45 #endif
     46 
     47 #ifdef HAVE_SYS_SELECT_H
     48 #include <sys/select.h>
     49 #endif
     50 
     51 #include "urldata.h"
     52 #include <curl/curl.h>
     53 #include "transfer.h"
     54 #include "sendf.h"
     55 #include "escape.h"
     56 #include "progress.h"
     57 #include "dict.h"
     58 #include "strcase.h"
     59 #include "curl_memory.h"
     60 /* The last #include file should be: */
     61 #include "memdebug.h"
     62 
     63 /*
     64  * Forward declarations.
     65  */
     66 
     67 static CURLcode dict_do(struct connectdata *conn, bool *done);
     68 
     69 /*
     70  * DICT protocol handler.
     71  */
     72 
     73 const struct Curl_handler Curl_handler_dict = {
     74   "DICT",                               /* scheme */
     75   ZERO_NULL,                            /* setup_connection */
     76   dict_do,                              /* do_it */
     77   ZERO_NULL,                            /* done */
     78   ZERO_NULL,                            /* do_more */
     79   ZERO_NULL,                            /* connect_it */
     80   ZERO_NULL,                            /* connecting */
     81   ZERO_NULL,                            /* doing */
     82   ZERO_NULL,                            /* proto_getsock */
     83   ZERO_NULL,                            /* doing_getsock */
     84   ZERO_NULL,                            /* domore_getsock */
     85   ZERO_NULL,                            /* perform_getsock */
     86   ZERO_NULL,                            /* disconnect */
     87   ZERO_NULL,                            /* readwrite */
     88   PORT_DICT,                            /* defport */
     89   CURLPROTO_DICT,                       /* protocol */
     90   PROTOPT_NONE | PROTOPT_NOURLQUERY      /* flags */
     91 };
     92 
     93 static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
     94 {
     95   char *newp;
     96   char *dictp;
     97   char *ptr;
     98   size_t len;
     99   char ch;
    100   int olen=0;
    101 
    102   CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
    103   if(!newp || result)
    104     return NULL;
    105 
    106   dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
    107   if(dictp) {
    108     /* According to RFC2229 section 2.2, these letters need to be escaped with
    109        \[letter] */
    110     for(ptr = newp;
    111         (ch = *ptr) != 0;
    112         ptr++) {
    113       if((ch <= 32) || (ch == 127) ||
    114           (ch == '\'') || (ch == '\"') || (ch == '\\')) {
    115         dictp[olen++] = '\\';
    116       }
    117       dictp[olen++] = ch;
    118     }
    119     dictp[olen]=0;
    120   }
    121   free(newp);
    122   return dictp;
    123 }
    124 
    125 static CURLcode dict_do(struct connectdata *conn, bool *done)
    126 {
    127   char *word;
    128   char *eword;
    129   char *ppath;
    130   char *database = NULL;
    131   char *strategy = NULL;
    132   char *nthdef = NULL; /* This is not part of the protocol, but required
    133                           by RFC 2229 */
    134   CURLcode result=CURLE_OK;
    135   struct Curl_easy *data=conn->data;
    136   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
    137 
    138   char *path = data->state.path;
    139   curl_off_t *bytecount = &data->req.bytecount;
    140 
    141   *done = TRUE; /* unconditionally */
    142 
    143   if(conn->bits.user_passwd) {
    144     /* AUTH is missing */
    145   }
    146 
    147   if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
    148      strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
    149      strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
    150 
    151     word = strchr(path, ':');
    152     if(word) {
    153       word++;
    154       database = strchr(word, ':');
    155       if(database) {
    156         *database++ = (char)0;
    157         strategy = strchr(database, ':');
    158         if(strategy) {
    159           *strategy++ = (char)0;
    160           nthdef = strchr(strategy, ':');
    161           if(nthdef) {
    162             *nthdef = (char)0;
    163           }
    164         }
    165       }
    166     }
    167 
    168     if((word == NULL) || (*word == (char)0)) {
    169       infof(data, "lookup word is missing\n");
    170       word=(char *)"default";
    171     }
    172     if((database == NULL) || (*database == (char)0)) {
    173       database = (char *)"!";
    174     }
    175     if((strategy == NULL) || (*strategy == (char)0)) {
    176       strategy = (char *)".";
    177     }
    178 
    179     eword = unescape_word(data, word);
    180     if(!eword)
    181       return CURLE_OUT_OF_MEMORY;
    182 
    183     result = Curl_sendf(sockfd, conn,
    184                         "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
    185                         "MATCH "
    186                         "%s "    /* database */
    187                         "%s "    /* strategy */
    188                         "%s\r\n" /* word */
    189                         "QUIT\r\n",
    190 
    191                         database,
    192                         strategy,
    193                         eword
    194                         );
    195 
    196     free(eword);
    197 
    198     if(result) {
    199       failf(data, "Failed sending DICT request");
    200       return result;
    201     }
    202     Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
    203                         -1, NULL); /* no upload */
    204   }
    205   else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
    206           strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
    207           strncasecompare(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
    208 
    209     word = strchr(path, ':');
    210     if(word) {
    211       word++;
    212       database = strchr(word, ':');
    213       if(database) {
    214         *database++ = (char)0;
    215         nthdef = strchr(database, ':');
    216         if(nthdef) {
    217           *nthdef = (char)0;
    218         }
    219       }
    220     }
    221 
    222     if((word == NULL) || (*word == (char)0)) {
    223       infof(data, "lookup word is missing\n");
    224       word=(char *)"default";
    225     }
    226     if((database == NULL) || (*database == (char)0)) {
    227       database = (char *)"!";
    228     }
    229 
    230     eword = unescape_word(data, word);
    231     if(!eword)
    232       return CURLE_OUT_OF_MEMORY;
    233 
    234     result = Curl_sendf(sockfd, conn,
    235                         "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
    236                         "DEFINE "
    237                         "%s "     /* database */
    238                         "%s\r\n"  /* word */
    239                         "QUIT\r\n",
    240                         database,
    241                         eword);
    242 
    243     free(eword);
    244 
    245     if(result) {
    246       failf(data, "Failed sending DICT request");
    247       return result;
    248     }
    249     Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
    250                         -1, NULL); /* no upload */
    251   }
    252   else {
    253 
    254     ppath = strchr(path, '/');
    255     if(ppath) {
    256       int i;
    257 
    258       ppath++;
    259       for(i = 0; ppath[i]; i++) {
    260         if(ppath[i] == ':')
    261           ppath[i] = ' ';
    262       }
    263       result = Curl_sendf(sockfd, conn,
    264                           "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
    265                           "%s\r\n"
    266                           "QUIT\r\n", ppath);
    267       if(result) {
    268         failf(data, "Failed sending DICT request");
    269         return result;
    270       }
    271 
    272       Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL);
    273     }
    274   }
    275 
    276   return CURLE_OK;
    277 }
    278 #endif /*CURL_DISABLE_DICT*/
    279