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