00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "setup.h"
00025
00026 #include <stdio.h>
00027 #include <stdarg.h>
00028 #include <stdlib.h>
00029 #include <errno.h>
00030
00031 #ifdef HAVE_SYS_SOCKET_H
00032 #include <sys/socket.h>
00033 #endif
00034
00035 #ifdef HAVE_UNISTD_H
00036 #include <unistd.h>
00037 #endif
00038
00039 #include <curl/curl.h>
00040 #include "urldata.h"
00041 #include "sendf.h"
00042 #include "connect.h"
00043 #include "sslgen.h"
00044 #include "ssh.h"
00045 #include "multiif.h"
00046
00047 #define _MPRINTF_REPLACE
00048 #include <curl/mprintf.h>
00049
00050 #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
00051 #include "krb4.h"
00052 #else
00053 #define Curl_sec_send(a,b,c,d) -1
00054 #define Curl_sec_read(a,b,c,d) -1
00055 #endif
00056
00057 #include <string.h>
00058 #include "memory.h"
00059 #include "strerror.h"
00060 #include "easyif.h"
00061
00062 #include "memdebug.h"
00063
00064
00065 static struct curl_slist *slist_get_last(struct curl_slist *list)
00066 {
00067 struct curl_slist *item;
00068
00069
00070 if (!list)
00071 return NULL;
00072
00073
00074 item = list;
00075 while (item->next) {
00076 item = item->next;
00077 }
00078 return item;
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088 struct curl_slist *curl_slist_append(struct curl_slist *list,
00089 const char *data)
00090 {
00091 struct curl_slist *last;
00092 struct curl_slist *new_item;
00093
00094 new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
00095 if (new_item) {
00096 char *dup = strdup(data);
00097 if(dup) {
00098 new_item->next = NULL;
00099 new_item->data = dup;
00100 }
00101 else {
00102 free(new_item);
00103 return NULL;
00104 }
00105 }
00106 else
00107 return NULL;
00108
00109 if (list) {
00110 last = slist_get_last(list);
00111 last->next = new_item;
00112 return list;
00113 }
00114
00115
00116 return new_item;
00117 }
00118
00119
00120 void curl_slist_free_all(struct curl_slist *list)
00121 {
00122 struct curl_slist *next;
00123 struct curl_slist *item;
00124
00125 if (!list)
00126 return;
00127
00128 item = list;
00129 do {
00130 next = item->next;
00131
00132 if (item->data) {
00133 free(item->data);
00134 }
00135 free(item);
00136 item = next;
00137 } while (next);
00138 }
00139
00140 #ifdef CURL_DO_LINEEND_CONV
00141
00142
00143
00144
00145
00146
00147 static size_t convert_lineends(struct SessionHandle *data,
00148 char *startPtr, size_t size)
00149 {
00150 char *inPtr, *outPtr;
00151
00152
00153 if ((startPtr == NULL) || (size < 1)) {
00154 return(size);
00155 }
00156
00157 if (data->state.prev_block_had_trailing_cr == TRUE) {
00158
00159
00160 if (*startPtr == '\n') {
00161
00162
00163 memcpy(startPtr, startPtr+1, size-1);
00164 size--;
00165
00166 data->state.crlf_conversions++;
00167 }
00168 data->state.prev_block_had_trailing_cr = FALSE;
00169 }
00170
00171
00172 inPtr = outPtr = memchr(startPtr, '\r', size);
00173 if (inPtr) {
00174
00175 while (inPtr < (startPtr+size-1)) {
00176
00177 if (memcmp(inPtr, "\r\n", 2) == 0) {
00178
00179 inPtr++;
00180 *outPtr = *inPtr;
00181
00182 data->state.crlf_conversions++;
00183 }
00184 else {
00185 if (*inPtr == '\r') {
00186
00187 *outPtr = '\n';
00188 }
00189 else {
00190
00191 *outPtr = *inPtr;
00192 }
00193 }
00194 outPtr++;
00195 inPtr++;
00196 }
00197
00198 if (inPtr < startPtr+size) {
00199
00200 if (*inPtr == '\r') {
00201
00202 *outPtr = '\n';
00203
00204 data->state.prev_block_had_trailing_cr = TRUE;
00205 }
00206 else {
00207
00208 *outPtr = *inPtr;
00209 }
00210 outPtr++;
00211 inPtr++;
00212 }
00213 if (outPtr < startPtr+size) {
00214
00215 *outPtr = '\0';
00216 }
00217 return(outPtr - startPtr);
00218 }
00219 return(size);
00220 }
00221 #endif
00222
00223
00224
00225 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
00226 {
00227 if(data && data->set.verbose) {
00228 va_list ap;
00229 size_t len;
00230 char print_buffer[1024 + 1];
00231 va_start(ap, fmt);
00232 vsnprintf(print_buffer, 1024, fmt, ap);
00233 va_end(ap);
00234 len = strlen(print_buffer);
00235 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
00236 }
00237 }
00238
00239
00240
00241
00242
00243 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
00244 {
00245 va_list ap;
00246 size_t len;
00247 va_start(ap, fmt);
00248
00249 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
00250
00251 if(data->set.errorbuffer && !data->state.errorbuf) {
00252 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
00253 data->state.errorbuf = TRUE;
00254 }
00255 if(data->set.verbose) {
00256 len = strlen(data->state.buffer);
00257 if(len < BUFSIZE - 1) {
00258 data->state.buffer[len] = '\n';
00259 data->state.buffer[++len] = '\0';
00260 }
00261 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
00262 }
00263
00264 va_end(ap);
00265 }
00266
00267
00268 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
00269 const char *fmt, ...)
00270 {
00271 struct SessionHandle *data = conn->data;
00272 ssize_t bytes_written;
00273 size_t write_len;
00274 CURLcode res = CURLE_OK;
00275 char *s;
00276 char *sptr;
00277 va_list ap;
00278 va_start(ap, fmt);
00279 s = vaprintf(fmt, ap);
00280 va_end(ap);
00281 if(!s)
00282 return CURLE_OUT_OF_MEMORY;
00283
00284 bytes_written=0;
00285 write_len = strlen(s);
00286 sptr = s;
00287
00288 while (1) {
00289
00290 res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
00291
00292 if(CURLE_OK != res)
00293 break;
00294
00295 if(data->set.verbose)
00296 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
00297
00298 if((size_t)bytes_written != write_len) {
00299
00300
00301 write_len -= bytes_written;
00302 sptr += bytes_written;
00303 }
00304 else
00305 break;
00306 }
00307
00308 free(s);
00309
00310 return res;
00311 }
00312
00313 static ssize_t Curl_plain_send(struct connectdata *conn,
00314 int num,
00315 void *mem,
00316 size_t len)
00317 {
00318 curl_socket_t sockfd = conn->sock[num];
00319 ssize_t bytes_written = swrite(sockfd, mem, len);
00320
00321 if(-1 == bytes_written) {
00322 int err = SOCKERRNO;
00323
00324 if(
00325 #ifdef WSAEWOULDBLOCK
00326
00327 (WSAEWOULDBLOCK == err)
00328 #else
00329
00330
00331
00332 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
00333 #endif
00334 )
00335
00336 bytes_written=0;
00337 else
00338 failf(conn->data, "Send failure: %s",
00339 Curl_strerror(conn, err));
00340 }
00341 return bytes_written;
00342 }
00343
00344
00345
00346
00347
00348 CURLcode Curl_write(struct connectdata *conn,
00349 curl_socket_t sockfd,
00350 void *mem,
00351 size_t len,
00352 ssize_t *written)
00353 {
00354 ssize_t bytes_written;
00355 CURLcode retcode;
00356 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
00357
00358 if (conn->ssl[num].use)
00359
00360 bytes_written = Curl_ssl_send(conn, num, mem, len);
00361 #ifdef USE_LIBSSH2
00362 else if (conn->protocol & PROT_SCP)
00363 bytes_written = Curl_scp_send(conn, num, mem, len);
00364 else if (conn->protocol & PROT_SFTP)
00365 bytes_written = Curl_sftp_send(conn, num, mem, len);
00366 #endif
00367 else if(conn->sec_complete)
00368
00369 bytes_written = Curl_sec_send(conn, num, mem, len);
00370 else
00371 bytes_written = Curl_plain_send(conn, num, mem, len);
00372
00373 *written = bytes_written;
00374 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
00375
00376 return retcode;
00377 }
00378
00379
00380
00381
00382
00383
00384 CURLcode Curl_client_write(struct connectdata *conn,
00385 int type,
00386 char *ptr,
00387 size_t len)
00388 {
00389 struct SessionHandle *data = conn->data;
00390 size_t wrote;
00391
00392 if (data->state.cancelled) {
00393
00394 return CURLE_OK;
00395 }
00396
00397 if(0 == len)
00398 len = strlen(ptr);
00399
00400 if(type & CLIENTWRITE_BODY) {
00401 if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
00402 #ifdef CURL_DOES_CONVERSIONS
00403
00404 size_t rc;
00405 rc = Curl_convert_from_network(data, ptr, len);
00406
00407 if(rc != CURLE_OK)
00408 return rc;
00409 #endif
00410
00411 #ifdef CURL_DO_LINEEND_CONV
00412
00413 len = convert_lineends(data, ptr, len);
00414 #endif
00415 }
00416
00417
00418 if (len) {
00419 wrote = data->set.fwrite(ptr, 1, len, data->set.out);
00420 }
00421 else {
00422 wrote = len;
00423 }
00424
00425 if(wrote != len) {
00426 failf (data, "Failed writing body");
00427 return CURLE_WRITE_ERROR;
00428 }
00429 }
00430
00431 if((type & CLIENTWRITE_HEADER) &&
00432 (data->set.fwrite_header || data->set.writeheader) ) {
00433
00434
00435
00436
00437 curl_write_callback writeit=
00438 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite;
00439
00440
00441
00442
00443 wrote = writeit(ptr, 1, len, data->set.writeheader);
00444 if(wrote != len) {
00445 failf (data, "Failed writing header");
00446 return CURLE_WRITE_ERROR;
00447 }
00448 }
00449
00450 return CURLE_OK;
00451 }
00452
00453 #ifndef MIN
00454 #define MIN(a,b) ((a) < (b) ? (a) : (b))
00455 #endif
00456
00457
00458
00459
00460
00461
00462
00463
00464 int Curl_read(struct connectdata *conn,
00465 curl_socket_t sockfd,
00466 char *buf,
00467 size_t sizerequested,
00468 ssize_t *n)
00469 {
00470 ssize_t nread = 0;
00471 size_t bytesfromsocket = 0;
00472 char *buffertofill = NULL;
00473 bool pipelining = (bool)(conn->data->multi &&
00474 Curl_multi_canPipeline(conn->data->multi));
00475
00476
00477
00478
00479 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
00480
00481 *n=0;
00482
00483
00484 if(pipelining) {
00485 size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);
00486
00487
00488 if (bytestocopy > 0) {
00489 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
00490 conn->read_pos += bytestocopy;
00491 conn->bits.stream_was_rewound = FALSE;
00492
00493 *n = (ssize_t)bytestocopy;
00494 return CURLE_OK;
00495 }
00496
00497
00498 bytesfromsocket = MIN(sizerequested, BUFSIZE * sizeof (char));
00499 buffertofill = conn->master_buffer;
00500 }
00501 else {
00502 bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ?
00503 conn->data->set.buffer_size : BUFSIZE);
00504 buffertofill = buf;
00505 }
00506
00507 if(conn->ssl[num].use) {
00508 nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
00509
00510 if(nread == -1) {
00511 return -1;
00512 }
00513 }
00514 #ifdef USE_LIBSSH2
00515 else if (conn->protocol & (PROT_SCP|PROT_SFTP)) {
00516 if(conn->protocol & PROT_SCP)
00517 nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
00518 else if (conn->protocol & PROT_SFTP)
00519 nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
00520 #ifdef LIBSSH2CHANNEL_EAGAIN
00521 if((nread == LIBSSH2CHANNEL_EAGAIN) || (nread == 0))
00522
00523 return -1;
00524 #endif
00525 if(nread < 0)
00526
00527 return CURLE_RECV_ERROR;
00528 }
00529 #endif
00530 else {
00531 if(conn->sec_complete)
00532 nread = Curl_sec_read(conn, sockfd, buffertofill,
00533 bytesfromsocket);
00534 else
00535 nread = sread(sockfd, buffertofill, bytesfromsocket);
00536
00537 if(-1 == nread) {
00538 int err = SOCKERRNO;
00539 #ifdef USE_WINSOCK
00540 if(WSAEWOULDBLOCK == err)
00541 #else
00542 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
00543 #endif
00544 return -1;
00545 }
00546 }
00547
00548 if (nread >= 0) {
00549 if(pipelining) {
00550 memcpy(buf, conn->master_buffer, nread);
00551 conn->buf_len = nread;
00552 conn->read_pos = nread;
00553 }
00554
00555 *n += nread;
00556 }
00557
00558 return CURLE_OK;
00559 }
00560
00561
00562 static int showit(struct SessionHandle *data, curl_infotype type,
00563 char *ptr, size_t size)
00564 {
00565 static const char * const s_infotype[CURLINFO_END] = {
00566 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
00567
00568 #ifdef CURL_DOES_CONVERSIONS
00569 char buf[BUFSIZE+1];
00570 size_t conv_size = 0;
00571
00572 switch(type) {
00573 case CURLINFO_HEADER_OUT:
00574
00575
00576 if (size > BUFSIZE) {
00577 size = BUFSIZE;
00578 buf[BUFSIZE] = '\0';
00579 }
00580 conv_size = size;
00581 memcpy(buf, ptr, size);
00582
00583
00584
00585
00586 if(size > 4) {
00587 size_t i;
00588 for(i = 0; i < size-4; i++) {
00589 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
00590
00591 conv_size = i + 4;
00592 break;
00593 }
00594 }
00595 }
00596
00597 Curl_convert_from_network(data, buf, conv_size);
00598
00599
00600 ptr = buf;
00601 break;
00602 default:
00603
00604 break;
00605 }
00606 #endif
00607
00608 if(data->set.fdebug)
00609 return (*data->set.fdebug)(data, type, ptr, size,
00610 data->set.debugdata);
00611
00612 switch(type) {
00613 case CURLINFO_TEXT:
00614 case CURLINFO_HEADER_OUT:
00615 case CURLINFO_HEADER_IN:
00616 fwrite(s_infotype[type], 2, 1, data->set.err);
00617 fwrite(ptr, size, 1, data->set.err);
00618 #ifdef CURL_DOES_CONVERSIONS
00619 if(size != conv_size) {
00620
00621 fwrite("\n", 1, 1, data->set.err);
00622 }
00623 #endif
00624 break;
00625 default:
00626 break;
00627 }
00628 return 0;
00629 }
00630
00631 int Curl_debug(struct SessionHandle *data, curl_infotype type,
00632 char *ptr, size_t size,
00633 struct connectdata *conn)
00634 {
00635 int rc;
00636 if(data->set.printhost && conn && conn->host.dispname) {
00637 char buffer[160];
00638 const char *t=NULL;
00639 const char *w="Data";
00640 switch (type) {
00641 case CURLINFO_HEADER_IN:
00642 w = "Header";
00643 case CURLINFO_DATA_IN:
00644 t = "from";
00645 break;
00646 case CURLINFO_HEADER_OUT:
00647 w = "Header";
00648 case CURLINFO_DATA_OUT:
00649 t = "to";
00650 break;
00651 default:
00652 break;
00653 }
00654
00655 if(t) {
00656 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
00657 conn->host.dispname);
00658 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
00659 if(rc)
00660 return rc;
00661 }
00662 }
00663 rc = showit(data, type, ptr, size);
00664 return rc;
00665 }