Supress "comparison between signed and unsigned" warning.
[platform/upstream/curl.git] / lib / sendf.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2007, 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  * $Id$
22  ***************************************************************************/
23
24 #include "setup.h"
25
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <errno.h>
30
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
33 #endif
34
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h> /* required for send() & recv() prototypes */
37 #endif
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
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"
50
51 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
52 #include <curl/mprintf.h>
53
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
60
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"
67
68 /* returns last node in linked list */
69 static struct curl_slist *slist_get_last(struct curl_slist *list)
70 {
71   struct curl_slist     *item;
72
73   /* if caller passed us a NULL, return now */
74   if (!list)
75     return NULL;
76
77   /* loop through to find the last item */
78   item = list;
79   while (item->next) {
80     item = item->next;
81   }
82   return item;
83 }
84
85 /*
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.
91  */
92 struct curl_slist *curl_slist_append(struct curl_slist *list,
93                                      const char *data)
94 {
95   struct curl_slist     *last;
96   struct curl_slist     *new_item;
97
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;
104     }
105     else {
106       free(new_item);
107       return NULL;
108     }
109   }
110   else
111     return NULL;
112
113   if (list) {
114     last = slist_get_last(list);
115     last->next = new_item;
116     return list;
117   }
118
119   /* if this is the first item, then new_item *is* the list */
120   return new_item;
121 }
122
123 /* be nice and clean up resources */
124 void curl_slist_free_all(struct curl_slist *list)
125 {
126   struct curl_slist     *next;
127   struct curl_slist     *item;
128
129   if (!list)
130     return;
131
132   item = list;
133   do {
134     next = item->next;
135
136     if (item->data) {
137       free(item->data);
138     }
139     free(item);
140     item = next;
141   } while (next);
142 }
143
144 #ifdef CURL_DO_LINEEND_CONV
145 /*
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.
150  */
151 static size_t convert_lineends(struct SessionHandle *data,
152                                char *startPtr, size_t size)
153 {
154   char *inPtr, *outPtr;
155
156   /* sanity check */
157   if ((startPtr == NULL) || (size < 1)) {
158     return(size);
159   }
160
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++;
171     }
172     data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
173   }
174
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++;
187       }
188       else {
189         if (*inPtr == '\r') {
190           /* lone CR, move LF instead */
191           *outPtr = '\n';
192         }
193         else {
194           /* not a CRLF nor a CR, just copy whatever it is */
195           *outPtr = *inPtr;
196         }
197       }
198       outPtr++;
199       inPtr++;
200     } /* end of while loop */
201
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;
209       }
210       else {
211         /* copy last byte */
212         *outPtr = *inPtr;
213       }
214       outPtr++;
215       inPtr++;
216     }
217     if (outPtr < startPtr+size) {
218       /* tidy up by null terminating the now shorter data */
219       *outPtr = '\0';
220     }
221     return(outPtr - startPtr);
222   }
223   return(size);
224 }
225 #endif /* CURL_DO_LINEEND_CONV */
226
227 /* Curl_infof() is for info message along the way */
228
229 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
230 {
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);
240   }
241 }
242
243 /* Curl_failf() is for messages stating why we failed.
244  * The message SHALL NOT include any LF or CR.
245  */
246
247 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
248 {
249   va_list ap;
250   size_t len;
251   va_start(ap, fmt);
252
253   vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
254
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 */
258   }
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';
264     }
265     Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
266   }
267
268   va_end(ap);
269 }
270
271 /* Curl_sendf() sends formated data to the server */
272 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
273                     const char *fmt, ...)
274 {
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 */
287
288   bytes_written=0;
289   write_len = strlen(s);
290   sptr = s;
291
292   while (1) {
293     /* Write the buffer to the socket */
294     res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
295
296     if(CURLE_OK != res)
297       break;
298
299     if(data->set.verbose)
300       Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
301
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;
307     }
308     else
309       break;
310   }
311
312   free(s); /* free the output string */
313
314   return res;
315 }
316
317 static ssize_t Curl_plain_send(struct connectdata *conn,
318                                int num,
319                                void *mem,
320                                size_t len)
321 {
322   curl_socket_t sockfd = conn->sock[num];
323   ssize_t bytes_written = swrite(sockfd, mem, len);
324
325   if(-1 == bytes_written) {
326     int err = Curl_sockerrno();
327
328     if(
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
338       )
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));
344   }
345   return bytes_written;
346 }
347
348 /*
349  * Curl_write() is an internal write function that sends data to the
350  * server. Works with plain sockets, SCP, SSL or kerberos.
351  */
352 CURLcode Curl_write(struct connectdata *conn,
353                     curl_socket_t sockfd,
354                     void *mem,
355                     size_t len,
356                     ssize_t *written)
357 {
358   ssize_t bytes_written;
359   CURLcode retcode;
360   int num = (sockfd == conn->sock[SECONDARYSOCKET]);
361
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);
376
377   *written = bytes_written;
378   retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
379
380   return retcode;
381 }
382
383 /* client_write() sends data to the write callback(s)
384
385    The bit pattern defines to what "streams" to write to. Body and/or header.
386    The defines are in sendf.h of course.
387  */
388 CURLcode Curl_client_write(struct connectdata *conn,
389                            int type,
390                            char *ptr,
391                            size_t len)
392 {
393   struct SessionHandle *data = conn->data;
394   size_t wrote;
395
396   if (data->state.cancelled) {
397       /* We just suck everything into a black hole */
398       return CURLE_OK;
399   }
400
401   if(0 == len)
402     len = strlen(ptr);
403
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 */
414
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 */
419     }
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);
424     }
425     else {
426       wrote = len;
427     }
428
429     if(wrote != len) {
430       failf (data, "Failed writing body");
431       return CURLE_WRITE_ERROR;
432     }
433   }
434
435   if((type & CLIENTWRITE_HEADER) &&
436      (data->set.fwrite_header || data->set.writeheader) ) {
437     /*
438      * Write headers to the same callback or to the especially setup
439      * header callback function (added after version 7.7.1).
440      */
441     curl_write_callback writeit=
442       data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite;
443
444     /* Note: The header is in the host encoding
445        regardless of the ftp transfer mode (ASCII/Image) */
446
447     wrote = writeit(ptr, 1, len, data->set.writeheader);
448     if(wrote != len) {
449       failf (data, "Failed writing header");
450       return CURLE_WRITE_ERROR;
451     }
452   }
453
454   return CURLE_OK;
455 }
456
457 #ifndef MIN
458 #define MIN(a,b) ((a) < (b) ? (a) : (b))
459 #endif
460
461 /*
462  * Internal read-from-socket function. This is meant to deal with plain
463  * sockets, SSL sockets and kerberos sockets.
464  *
465  * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
466  * a regular CURLcode value.
467  */
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 */
473 {
474   ssize_t nread;
475   size_t bytesfromsocket = 0;
476   char *buffertofill = NULL;
477   bool pipelining = (conn->data->multi &&
478                      Curl_multi_canPipeline(conn->data->multi));
479
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]);
484
485   *n=0; /* reset amount to zero */
486
487   /* If session can pipeline, check connection buffer  */
488   if(pipelining) {
489     size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);
490
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;
496
497       *n = (ssize_t)bytestocopy;
498       return CURLE_OK;
499     }
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;
504   }
505   else {
506     bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ?
507                           conn->data->set.buffer_size : BUFSIZE);
508     buffertofill = buf;
509   }
510
511   if(conn->ssl[num].use) {
512     nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
513
514     if(nread == -1) {
515       return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
516     }
517   }
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 ? */
523   }
524   else if (conn->protocol & PROT_SFTP) {
525     nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
526   }
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);
534
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;
543     }
544   }
545
546   if (nread >= 0) {
547     if(pipelining) {
548       memcpy(buf, conn->master_buffer, nread);
549       conn->buf_len = nread;
550       conn->read_pos = nread;
551     }
552
553     *n += nread;
554   }
555
556   return CURLE_OK;
557 }
558
559 /* return 0 on success */
560 static int showit(struct SessionHandle *data, curl_infotype type,
561                   char *ptr, size_t size)
562 {
563   static const char * const s_infotype[CURLINFO_END] = {
564     "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
565
566 #ifdef CURL_DOES_CONVERSIONS
567   char buf[BUFSIZE+1];
568   size_t conv_size = 0;
569
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';
577     }
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.
583      */
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;
591         }
592       }
593     }
594
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;
603   }
604 #endif /* CURL_DOES_CONVERSIONS */
605
606   if(data->set.fdebug)
607     return (*data->set.fdebug)(data, type, ptr, size,
608                                data->set.debugdata);
609
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);
620     }
621 #endif
622     break;
623   default: /* nada */
624     break;
625   }
626   return 0;
627 }
628
629 int Curl_debug(struct SessionHandle *data, curl_infotype type,
630                char *ptr, size_t size,
631                struct connectdata *conn)
632 {
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;
651     }
652
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;
659     }
660   }
661   rc = showit(data, type, ptr, size);
662   return rc;
663 }