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