Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Utilities / cmcurl / sendf.c
blob9fed3ed18d2591da444637cf46e6ef79e3295354
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 * $Id: sendf.c,v 1.2 2007/03/15 19:22:13 andy Exp $
22 ***************************************************************************/
24 #include "setup.h"
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <errno.h>
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
33 #endif
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h> /* required for send() & recv() prototypes */
37 #endif
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
43 #include <curl/curl.h>
44 #include "urldata.h"
45 #include "sendf.h"
46 #include "connect.h" /* for the Curl_sockerrno() proto */
47 #include "sslgen.h"
48 #include "ssh.h"
49 #include "multiif.h"
51 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
52 #include <curl/mprintf.h>
54 #ifdef HAVE_KRB4
55 #include "krb4.h"
56 #else
57 #define Curl_sec_send(a,b,c,d) -1
58 #define Curl_sec_read(a,b,c,d) -1
59 #endif
61 #include <string.h>
62 #include "memory.h"
63 #include "strerror.h"
64 #include "easyif.h" /* for the Curl_convert_from_network prototype */
65 /* The last #include file should be: */
66 #include "memdebug.h"
68 /* returns last node in linked list */
69 static struct curl_slist *slist_get_last(struct curl_slist *list)
71 struct curl_slist *item;
73 /* if caller passed us a NULL, return now */
74 if (!list)
75 return NULL;
77 /* loop through to find the last item */
78 item = list;
79 while (item->next) {
80 item = item->next;
82 return item;
86 * curl_slist_append() appends a string to the linked list. It always retunrs
87 * the address of the first record, so that you can sure this function as an
88 * initialization function as well as an append function. If you find this
89 * bothersome, then simply create a separate _init function and call it
90 * appropriately from within the proram.
92 struct curl_slist *curl_slist_append(struct curl_slist *list,
93 const char *data)
95 struct curl_slist *last;
96 struct curl_slist *new_item;
98 new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
99 if (new_item) {
100 char *dup = strdup(data);
101 if(dup) {
102 new_item->next = NULL;
103 new_item->data = dup;
105 else {
106 free(new_item);
107 return NULL;
110 else
111 return NULL;
113 if (list) {
114 last = slist_get_last(list);
115 last->next = new_item;
116 return list;
119 /* if this is the first item, then new_item *is* the list */
120 return new_item;
123 /* be nice and clean up resources */
124 void curl_slist_free_all(struct curl_slist *list)
126 struct curl_slist *next;
127 struct curl_slist *item;
129 if (!list)
130 return;
132 item = list;
133 do {
134 next = item->next;
136 if (item->data) {
137 free(item->data);
139 free(item);
140 item = next;
141 } while (next);
144 #ifdef CURL_DO_LINEEND_CONV
146 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
147 * (\n), with special processing for CRLF sequences that are split between two
148 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
149 * size of the data is returned.
151 static size_t convert_lineends(struct SessionHandle *data,
152 char *startPtr, size_t size)
154 char *inPtr, *outPtr;
156 /* sanity check */
157 if ((startPtr == NULL) || (size < 1)) {
158 return(size);
161 if (data->state.prev_block_had_trailing_cr == TRUE) {
162 /* The previous block of incoming data
163 had a trailing CR, which was turned into a LF. */
164 if (*startPtr == '\n') {
165 /* This block of incoming data starts with the
166 previous block's LF so get rid of it */
167 memcpy(startPtr, startPtr+1, size-1);
168 size--;
169 /* and it wasn't a bare CR but a CRLF conversion instead */
170 data->state.crlf_conversions++;
172 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
175 /* find 1st CR, if any */
176 inPtr = outPtr = memchr(startPtr, '\r', size);
177 if (inPtr) {
178 /* at least one CR, now look for CRLF */
179 while (inPtr < (startPtr+size-1)) {
180 /* note that it's size-1, so we'll never look past the last byte */
181 if (memcmp(inPtr, "\r\n", 2) == 0) {
182 /* CRLF found, bump past the CR and copy the NL */
183 inPtr++;
184 *outPtr = *inPtr;
185 /* keep track of how many CRLFs we converted */
186 data->state.crlf_conversions++;
188 else {
189 if (*inPtr == '\r') {
190 /* lone CR, move LF instead */
191 *outPtr = '\n';
193 else {
194 /* not a CRLF nor a CR, just copy whatever it is */
195 *outPtr = *inPtr;
198 outPtr++;
199 inPtr++;
200 } /* end of while loop */
202 if (inPtr < startPtr+size) {
203 /* handle last byte */
204 if (*inPtr == '\r') {
205 /* deal with a CR at the end of the buffer */
206 *outPtr = '\n'; /* copy a NL instead */
207 /* note that a CRLF might be split across two blocks */
208 data->state.prev_block_had_trailing_cr = TRUE;
210 else {
211 /* copy last byte */
212 *outPtr = *inPtr;
214 outPtr++;
215 inPtr++;
217 if (outPtr < startPtr+size) {
218 /* tidy up by null terminating the now shorter data */
219 *outPtr = '\0';
221 return(outPtr - startPtr);
223 return(size);
225 #endif /* CURL_DO_LINEEND_CONV */
227 /* Curl_infof() is for info message along the way */
229 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
231 if(data && data->set.verbose) {
232 va_list ap;
233 size_t len;
234 char print_buffer[1024 + 1];
235 va_start(ap, fmt);
236 vsnprintf(print_buffer, 1024, fmt, ap);
237 va_end(ap);
238 len = strlen(print_buffer);
239 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
243 /* Curl_failf() is for messages stating why we failed.
244 * The message SHALL NOT include any LF or CR.
247 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
249 va_list ap;
250 size_t len;
251 va_start(ap, fmt);
253 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
255 if(data->set.errorbuffer && !data->state.errorbuf) {
256 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
257 data->state.errorbuf = TRUE; /* wrote error string */
259 if(data->set.verbose) {
260 len = strlen(data->state.buffer);
261 if(len < BUFSIZE - 1) {
262 data->state.buffer[len] = '\n';
263 data->state.buffer[++len] = '\0';
265 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
268 va_end(ap);
271 /* Curl_sendf() sends formated data to the server */
272 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
273 const char *fmt, ...)
275 struct SessionHandle *data = conn->data;
276 ssize_t bytes_written;
277 size_t write_len;
278 CURLcode res = CURLE_OK;
279 char *s;
280 char *sptr;
281 va_list ap;
282 va_start(ap, fmt);
283 s = vaprintf(fmt, ap); /* returns an allocated string */
284 va_end(ap);
285 if(!s)
286 return CURLE_OUT_OF_MEMORY; /* failure */
288 bytes_written=0;
289 write_len = strlen(s);
290 sptr = s;
292 while (1) {
293 /* Write the buffer to the socket */
294 res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
296 if(CURLE_OK != res)
297 break;
299 if(data->set.verbose)
300 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
302 if((size_t)bytes_written != write_len) {
303 /* if not all was written at once, we must advance the pointer, decrease
304 the size left and try again! */
305 write_len -= bytes_written;
306 sptr += bytes_written;
308 else
309 break;
312 free(s); /* free the output string */
314 return res;
317 static ssize_t Curl_plain_send(struct connectdata *conn,
318 int num,
319 void *mem,
320 size_t len)
322 curl_socket_t sockfd = conn->sock[num];
323 ssize_t bytes_written = swrite(sockfd, mem, len);
325 if(-1 == bytes_written) {
326 int err = Curl_sockerrno();
329 #ifdef WSAEWOULDBLOCK
330 /* This is how Windows does it */
331 (WSAEWOULDBLOCK == err)
332 #else
333 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
334 due to its inability to send off data without blocking. We therefor
335 treat both error codes the same here */
336 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
337 #endif
339 /* this is just a case of EWOULDBLOCK */
340 bytes_written=0;
341 else
342 failf(conn->data, "Send failure: %s",
343 Curl_strerror(conn, err));
345 return bytes_written;
349 * Curl_write() is an internal write function that sends data to the
350 * server. Works with plain sockets, SCP, SSL or kerberos.
352 CURLcode Curl_write(struct connectdata *conn,
353 curl_socket_t sockfd,
354 void *mem,
355 size_t len,
356 ssize_t *written)
358 ssize_t bytes_written;
359 CURLcode retcode;
360 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
362 if (conn->ssl[num].use)
363 /* only TRUE if SSL enabled */
364 bytes_written = Curl_ssl_send(conn, num, mem, len);
365 #ifdef USE_LIBSSH2
366 else if (conn->protocol & PROT_SCP)
367 bytes_written = Curl_scp_send(conn, num, mem, len);
368 else if (conn->protocol & PROT_SFTP)
369 bytes_written = Curl_sftp_send(conn, num, mem, len);
370 #endif /* !USE_LIBSSH2 */
371 else if(conn->sec_complete)
372 /* only TRUE if krb4 enabled */
373 bytes_written = Curl_sec_send(conn, num, mem, len);
374 else
375 bytes_written = Curl_plain_send(conn, num, mem, len);
377 *written = bytes_written;
378 retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
380 return retcode;
383 /* client_write() sends data to the write callback(s)
385 The bit pattern defines to what "streams" to write to. Body and/or header.
386 The defines are in sendf.h of course.
388 CURLcode Curl_client_write(struct connectdata *conn,
389 int type,
390 char *ptr,
391 size_t len)
393 struct SessionHandle *data = conn->data;
394 size_t wrote;
396 if (data->state.cancelled) {
397 /* We just suck everything into a black hole */
398 return CURLE_OK;
401 if(0 == len)
402 len = strlen(ptr);
404 if(type & CLIENTWRITE_BODY) {
405 if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
406 #ifdef CURL_DOES_CONVERSIONS
407 /* convert from the network encoding */
408 size_t rc;
409 rc = Curl_convert_from_network(data, ptr, len);
410 /* Curl_convert_from_network calls failf if unsuccessful */
411 if(rc != CURLE_OK)
412 return rc;
413 #endif /* CURL_DOES_CONVERSIONS */
415 #ifdef CURL_DO_LINEEND_CONV
416 /* convert end-of-line markers */
417 len = convert_lineends(data, ptr, len);
418 #endif /* CURL_DO_LINEEND_CONV */
420 /* If the previous block of data ended with CR and this block of data is
421 just a NL, then the length might be zero */
422 if (len) {
423 wrote = data->set.fwrite(ptr, 1, len, data->set.out);
425 else {
426 wrote = len;
429 if(wrote != len) {
430 failf (data, "Failed writing body");
431 return CURLE_WRITE_ERROR;
435 if((type & CLIENTWRITE_HEADER) &&
436 (data->set.fwrite_header || data->set.writeheader) ) {
438 * Write headers to the same callback or to the especially setup
439 * header callback function (added after version 7.7.1).
441 curl_write_callback writeit=
442 data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite;
444 /* Note: The header is in the host encoding
445 regardless of the ftp transfer mode (ASCII/Image) */
447 wrote = writeit(ptr, 1, len, data->set.writeheader);
448 if(wrote != len) {
449 failf (data, "Failed writing header");
450 return CURLE_WRITE_ERROR;
454 return CURLE_OK;
457 #ifndef MIN
458 #define MIN(a,b) ((a) < (b) ? (a) : (b))
459 #endif
462 * Internal read-from-socket function. This is meant to deal with plain
463 * sockets, SSL sockets and kerberos sockets.
465 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
466 * a regular CURLcode value.
468 int Curl_read(struct connectdata *conn, /* connection data */
469 curl_socket_t sockfd, /* read from this socket */
470 char *buf, /* store read data here */
471 size_t sizerequested, /* max amount to read */
472 ssize_t *n) /* amount bytes read */
474 ssize_t nread;
475 size_t bytesfromsocket = 0;
476 char *buffertofill = NULL;
477 bool pipelining = (bool)(conn->data->multi &&
478 Curl_multi_canPipeline(conn->data->multi));
480 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
481 If it is the second socket, we set num to 1. Otherwise to 0. This lets
482 us use the correct ssl handle. */
483 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
485 *n=0; /* reset amount to zero */
487 /* If session can pipeline, check connection buffer */
488 if(pipelining) {
489 size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);
491 /* Copy from our master buffer first if we have some unread data there*/
492 if (bytestocopy > 0) {
493 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
494 conn->read_pos += bytestocopy;
495 conn->bits.stream_was_rewound = FALSE;
497 *n = (ssize_t)bytestocopy;
498 return CURLE_OK;
500 /* If we come here, it means that there is no data to read from the buffer,
501 * so we read from the socket */
502 bytesfromsocket = MIN(sizerequested, sizeof(conn->master_buffer));
503 buffertofill = conn->master_buffer;
505 else {
506 bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ?
507 conn->data->set.buffer_size : BUFSIZE);
508 buffertofill = buf;
511 if(conn->ssl[num].use) {
512 nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
514 if(nread == -1) {
515 return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
518 #ifdef USE_LIBSSH2
519 else if (conn->protocol & PROT_SCP) {
520 nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
521 /* TODO: return CURLE_OK also for nread <= 0
522 read failures and timeouts ? */
524 else if (conn->protocol & PROT_SFTP) {
525 nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
527 #endif /* !USE_LIBSSH2 */
528 else {
529 if(conn->sec_complete)
530 nread = Curl_sec_read(conn, sockfd, buffertofill,
531 bytesfromsocket);
532 else
533 nread = sread(sockfd, buffertofill, bytesfromsocket);
535 if(-1 == nread) {
536 int err = Curl_sockerrno();
537 #ifdef USE_WINSOCK
538 if(WSAEWOULDBLOCK == err)
539 #else
540 if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
541 #endif
542 return -1;
546 if (nread >= 0) {
547 if(pipelining) {
548 memcpy(buf, conn->master_buffer, nread);
549 conn->buf_len = nread;
550 conn->read_pos = nread;
553 *n += nread;
556 return CURLE_OK;
559 /* return 0 on success */
560 static int showit(struct SessionHandle *data, curl_infotype type,
561 char *ptr, size_t size)
563 static const char * const s_infotype[CURLINFO_END] = {
564 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
566 #ifdef CURL_DOES_CONVERSIONS
567 char buf[BUFSIZE+1];
568 size_t conv_size = 0;
570 switch(type) {
571 case CURLINFO_HEADER_OUT:
572 /* assume output headers are ASCII */
573 /* copy the data into my buffer so the original is unchanged */
574 if (size > BUFSIZE) {
575 size = BUFSIZE; /* truncate if necessary */
576 buf[BUFSIZE] = '\0';
578 conv_size = size;
579 memcpy(buf, ptr, size);
580 /* Special processing is needed for this block if it
581 * contains both headers and data (separated by CRLFCRLF).
582 * We want to convert just the headers, leaving the data as-is.
584 if(size > 4) {
585 size_t i;
586 for(i = 0; i < size-4; i++) {
587 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
588 /* convert everthing through this CRLFCRLF but no further */
589 conv_size = i + 4;
590 break;
595 Curl_convert_from_network(data, buf, conv_size);
596 /* Curl_convert_from_network calls failf if unsuccessful */
597 /* we might as well continue even if it fails... */
598 ptr = buf; /* switch pointer to use my buffer instead */
599 break;
600 default:
601 /* leave everything else as-is */
602 break;
604 #endif /* CURL_DOES_CONVERSIONS */
606 if(data->set.fdebug)
607 return (*data->set.fdebug)(data, type, ptr, size,
608 data->set.debugdata);
610 switch(type) {
611 case CURLINFO_TEXT:
612 case CURLINFO_HEADER_OUT:
613 case CURLINFO_HEADER_IN:
614 fwrite(s_infotype[type], 2, 1, data->set.err);
615 fwrite(ptr, size, 1, data->set.err);
616 #ifdef CURL_DOES_CONVERSIONS
617 if(size != conv_size) {
618 /* we had untranslated data so we need an explicit newline */
619 fwrite("\n", 1, 1, data->set.err);
621 #endif
622 break;
623 default: /* nada */
624 break;
626 return 0;
629 int Curl_debug(struct SessionHandle *data, curl_infotype type,
630 char *ptr, size_t size,
631 struct connectdata *conn)
633 int rc;
634 if(data->set.printhost && conn && conn->host.dispname) {
635 char buffer[160];
636 const char *t=NULL;
637 const char *w="Data";
638 switch (type) {
639 case CURLINFO_HEADER_IN:
640 w = "Header";
641 case CURLINFO_DATA_IN:
642 t = "from";
643 break;
644 case CURLINFO_HEADER_OUT:
645 w = "Header";
646 case CURLINFO_DATA_OUT:
647 t = "to";
648 break;
649 default:
650 break;
653 if(t) {
654 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
655 conn->host.dispname);
656 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
657 if(rc)
658 return rc;
661 rc = showit(data, type, ptr, size);
662 return rc;