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