Compiler warning fix
[platform/upstream/curl.git] / lib / sendf.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2006, 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
49 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
50 #include <curl/mprintf.h>
51
52 #ifdef HAVE_KRB4
53 #include "krb4.h"
54 #else
55 #define Curl_sec_write(a,b,c,d) -1
56 #define Curl_sec_read(a,b,c,d) -1
57 #endif
58
59 #include <string.h>
60 #include "memory.h"
61 #include "strerror.h"
62 #include "easyif.h" /* for the Curl_convert_from_network prototype */
63 /* The last #include file should be: */
64 #include "memdebug.h"
65
66 /* returns last node in linked list */
67 static struct curl_slist *slist_get_last(struct curl_slist *list)
68 {
69   struct curl_slist     *item;
70
71   /* if caller passed us a NULL, return now */
72   if (!list)
73     return NULL;
74
75   /* loop through to find the last item */
76   item = list;
77   while (item->next) {
78     item = item->next;
79   }
80   return item;
81 }
82
83 /*
84  * curl_slist_append() appends a string to the linked list. It always retunrs
85  * the address of the first record, so that you can sure this function as an
86  * initialization function as well as an append function. If you find this
87  * bothersome, then simply create a separate _init function and call it
88  * appropriately from within the proram.
89  */
90 struct curl_slist *curl_slist_append(struct curl_slist *list,
91                                      const char *data)
92 {
93   struct curl_slist     *last;
94   struct curl_slist     *new_item;
95
96   new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
97   if (new_item) {
98     char *dup = strdup(data);
99     if(dup) {
100       new_item->next = NULL;
101       new_item->data = dup;
102     }
103     else {
104       free(new_item);
105       return NULL;
106     }
107   }
108   else
109     return NULL;
110
111   if (list) {
112     last = slist_get_last(list);
113     last->next = new_item;
114     return list;
115   }
116
117   /* if this is the first item, then new_item *is* the list */
118   return new_item;
119 }
120
121 /* be nice and clean up resources */
122 void curl_slist_free_all(struct curl_slist *list)
123 {
124   struct curl_slist     *next;
125   struct curl_slist     *item;
126
127   if (!list)
128     return;
129
130   item = list;
131   do {
132     next = item->next;
133
134     if (item->data) {
135       free(item->data);
136     }
137     free(item);
138     item = next;
139   } while (next);
140 }
141
142 #ifdef CURL_DO_LINEEND_CONV
143 /*
144  * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
145  * (\n), with special processing for CRLF sequences that are split between two
146  * blocks of data.  Remaining, bare CRs are changed to LFs.  The possibly new
147  * size of the data is returned.
148  */
149 static size_t convert_lineends(struct SessionHandle *data,
150                                char *startPtr, size_t size)
151 {
152   char *inPtr, *outPtr;
153
154   /* sanity check */
155   if ((startPtr == NULL) || (size < 1)) {
156     return(size);
157   }
158
159   if (data->state.prev_block_had_trailing_cr == TRUE) {
160     /* The previous block of incoming data
161        had a trailing CR, which was turned into a LF. */
162     if (*startPtr == '\n') {
163       /* This block of incoming data starts with the
164          previous block's LF so get rid of it */
165       memcpy(startPtr, startPtr+1, size-1);
166       size--;
167       /* and it wasn't a bare CR but a CRLF conversion instead */
168       data->state.crlf_conversions++;
169     }
170     data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
171   }
172
173   /* find 1st CR, if any */
174   inPtr = outPtr = memchr(startPtr, '\r', size);
175   if (inPtr) {
176     /* at least one CR, now look for CRLF */
177     while (inPtr < (startPtr+size-1)) {
178       /* note that it's size-1, so we'll never look past the last byte */
179       if (memcmp(inPtr, "\r\n", 2) == 0) {
180         /* CRLF found, bump past the CR and copy the NL */
181         inPtr++;
182         *outPtr = *inPtr;
183         /* keep track of how many CRLFs we converted */
184         data->state.crlf_conversions++;
185       }
186       else {
187         if (*inPtr == '\r') {
188           /* lone CR, move LF instead */
189           *outPtr = '\n';
190         }
191         else {
192           /* not a CRLF nor a CR, just copy whatever it is */
193           *outPtr = *inPtr;
194         }
195       }
196       outPtr++;
197       inPtr++;
198     } /* end of while loop */
199
200     if (inPtr < startPtr+size) {
201       /* handle last byte */
202       if (*inPtr == '\r') {
203         /* deal with a CR at the end of the buffer */
204         *outPtr = '\n'; /* copy a NL instead */
205         /* note that a CRLF might be split across two blocks */
206         data->state.prev_block_had_trailing_cr = TRUE;
207       }
208       else {
209         /* copy last byte */
210         *outPtr = *inPtr;
211       }
212       outPtr++;
213       inPtr++;
214     }
215     if (outPtr < startPtr+size) {
216       /* tidy up by null terminating the now shorter data */
217       *outPtr = '\0';
218     }
219     return(outPtr - startPtr);
220   }
221   return(size);
222 }
223 #endif /* CURL_DO_LINEEND_CONV */
224
225 /* Curl_infof() is for info message along the way */
226
227 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
228 {
229   if(data && data->set.verbose) {
230     va_list ap;
231     size_t len;
232     char print_buffer[1024 + 1];
233     va_start(ap, fmt);
234     vsnprintf(print_buffer, 1024, fmt, ap);
235     va_end(ap);
236     len = strlen(print_buffer);
237     Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
238   }
239 }
240
241 /* Curl_failf() is for messages stating why we failed.
242  * The message SHALL NOT include any LF or CR.
243  */
244
245 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
246 {
247   va_list ap;
248   size_t len;
249   va_start(ap, fmt);
250
251   vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
252
253   if(data->set.errorbuffer && !data->state.errorbuf) {
254     snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
255     data->state.errorbuf = TRUE; /* wrote error string */
256   }
257   if(data->set.verbose) {
258     len = strlen(data->state.buffer);
259     if(len < BUFSIZE - 1) {
260       data->state.buffer[len] = '\n';
261       data->state.buffer[++len] = '\0';
262     }
263     Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
264   }
265
266   va_end(ap);
267 }
268
269 /* Curl_sendf() sends formated data to the server */
270 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
271                     const char *fmt, ...)
272 {
273   struct SessionHandle *data = conn->data;
274   ssize_t bytes_written;
275   size_t write_len;
276   CURLcode res = CURLE_OK;
277   char *s;
278   char *sptr;
279   va_list ap;
280   va_start(ap, fmt);
281   s = vaprintf(fmt, ap); /* returns an allocated string */
282   va_end(ap);
283   if(!s)
284     return CURLE_OUT_OF_MEMORY; /* failure */
285
286   bytes_written=0;
287   write_len = strlen(s);
288   sptr = s;
289
290   while (1) {
291     /* Write the buffer to the socket */
292     res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
293
294     if(CURLE_OK != res)
295       break;
296
297     if(data->set.verbose)
298       Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
299
300     if((size_t)bytes_written != write_len) {
301       /* if not all was written at once, we must advance the pointer, decrease
302          the size left and try again! */
303       write_len -= bytes_written;
304       sptr += bytes_written;
305     }
306     else
307       break;
308   }
309
310   free(s); /* free the output string */
311
312   return res;
313 }
314
315 /*
316  * Curl_write() is an internal write function that sends plain (binary) data
317  * to the server. Works with plain sockets, SSL or kerberos.
318  */
319 CURLcode Curl_write(struct connectdata *conn,
320                     curl_socket_t sockfd,
321                     void *mem,
322                     size_t len,
323                     ssize_t *written)
324 {
325   ssize_t bytes_written;
326   CURLcode retcode;
327   int num = (sockfd == conn->sock[SECONDARYSOCKET]);
328
329   if (conn->ssl[num].use)
330     /* only TRUE if SSL enabled */
331     bytes_written = Curl_ssl_send(conn, num, mem, len);
332   else {
333     if(conn->sec_complete)
334       /* only TRUE if krb4 enabled */
335       bytes_written = Curl_sec_write(conn, sockfd, mem, len);
336     else
337       bytes_written = swrite(sockfd, mem, len);
338
339     if(-1 == bytes_written) {
340       int err = Curl_sockerrno();
341
342       if(
343 #ifdef WSAEWOULDBLOCK
344         /* This is how Windows does it */
345         (WSAEWOULDBLOCK == err)
346 #else
347         /* As pointed out by Christophe Demory on March 11 2003, errno
348            may be EWOULDBLOCK or on some systems EAGAIN when it returned
349            due to its inability to send off data without blocking. We
350            therefor treat both error codes the same here */
351         (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
352 #endif
353         )
354         /* this is just a case of EWOULDBLOCK */
355         bytes_written=0;
356       else
357         failf(conn->data, "Send failure: %s",
358               Curl_strerror(conn, err));
359     }
360   }
361   *written = bytes_written;
362   retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
363
364   return retcode;
365 }
366
367 /* client_write() sends data to the write callback(s)
368
369    The bit pattern defines to what "streams" to write to. Body and/or header.
370    The defines are in sendf.h of course.
371  */
372 CURLcode Curl_client_write(struct connectdata *conn,
373                            int type,
374                            char *ptr,
375                            size_t len)
376 {
377   struct SessionHandle *data = conn->data;
378   size_t wrote;
379
380   if (data->state.cancelled) {
381       /* We just suck everything into a black hole */
382       return CURLE_OK;
383   }
384
385   if(0 == len)
386     len = strlen(ptr);
387
388   if(type & CLIENTWRITE_BODY) {
389     if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
390 #ifdef CURL_DOES_CONVERSIONS
391       /* convert from the network encoding */
392       size_t rc;
393       rc = Curl_convert_from_network(data, ptr, len);
394       /* Curl_convert_from_network calls failf if unsuccessful */
395       if(rc != CURLE_OK)
396         return rc;
397 #endif /* CURL_DOES_CONVERSIONS */
398
399 #ifdef CURL_DO_LINEEND_CONV
400       /* convert end-of-line markers */
401       len = convert_lineends(data, ptr, len);
402 #endif /* CURL_DO_LINEEND_CONV */
403     }
404     /* If the previous block of data ended with CR and this block of data is
405        just a NL, then the length might be zero */
406     if (len) {
407       wrote = data->set.fwrite(ptr, 1, len, data->set.out);
408     }
409     else {
410       wrote = len;
411     }
412
413     if(wrote != len) {
414       failf (data, "Failed writing body");
415       return CURLE_WRITE_ERROR;
416     }
417   }
418
419   if((type & CLIENTWRITE_HEADER) &&
420      (data->set.fwrite_header || data->set.writeheader) ) {
421     /*
422      * Write headers to the same callback or to the especially setup
423      * header callback function (added after version 7.7.1).
424      */
425     curl_write_callback writeit=
426       data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite;
427
428     /* Note: The header is in the host encoding
429        regardless of the ftp transfer mode (ASCII/Image) */
430
431     wrote = writeit(ptr, 1, len, data->set.writeheader);
432     if(wrote != len) {
433       failf (data, "Failed writing header");
434       return CURLE_WRITE_ERROR;
435     }
436   }
437
438   return CURLE_OK;
439 }
440
441 void Curl_read_rewind(struct connectdata *conn,
442                       size_t extraBytesRead)
443 {
444     conn->read_pos -= extraBytesRead;
445     conn->bits.stream_was_rewound = TRUE;
446 }
447
448 #define MIN(a,b) (a < b ? a : b)
449
450 /*
451  * Internal read-from-socket function. This is meant to deal with plain
452  * sockets, SSL sockets and kerberos sockets.
453  *
454  * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
455  * a regular CURLcode value.
456  */
457 int Curl_read(struct connectdata *conn, /* connection data */
458               curl_socket_t sockfd,     /* read from this socket */
459               char *buf,                /* store read data here */
460               size_t buffersize,        /* max amount to read */
461               ssize_t *n)               /* amount bytes read */
462 {
463   ssize_t nread;
464   size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, buffersize);
465   size_t bytesremaining = buffersize - bytestocopy;
466
467   /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
468      If it is the second socket, we set num to 1. Otherwise to 0. This lets
469      us use the correct ssl handle. */
470   int num = (sockfd == conn->sock[SECONDARYSOCKET]);
471
472   *n=0; /* reset amount to zero */
473
474   bytesremaining = MIN(bytesremaining, sizeof(conn->master_buffer));
475
476   /* Copy from our master buffer first */
477   memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
478   conn->read_pos += bytestocopy;
479
480   conn->bits.stream_was_rewound = FALSE;
481
482   *n = (ssize_t)bytestocopy;
483
484   if (bytesremaining == 0) {
485       return CURLE_OK;
486   }
487
488   if(conn->ssl[num].use) {
489     nread = Curl_ssl_recv(conn, num, conn->master_buffer, bytesremaining);
490
491     if(nread == -1 && bytestocopy == 0) {
492       return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
493     }
494
495   } else {
496     if(conn->sec_complete)
497       nread = Curl_sec_read(conn, sockfd, conn->master_buffer, bytesremaining);
498     else
499       nread = sread(sockfd, conn->master_buffer, bytesremaining);
500
501     if(-1 == nread && bytestocopy == 0) {
502       int err = Curl_sockerrno();
503 #ifdef USE_WINSOCK
504       if(WSAEWOULDBLOCK == err)
505 #else
506       if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
507 #endif
508         return -1;
509     }
510   }
511
512   if (nread > 0) {
513       memcpy(buf, conn->master_buffer, nread);
514
515       conn->buf_len = nread;
516       conn->read_pos = nread;
517       *n += nread;
518   }
519
520   return CURLE_OK;
521 }
522
523 /* return 0 on success */
524 static int showit(struct SessionHandle *data, curl_infotype type,
525                   char *ptr, size_t size)
526 {
527   static const char * const s_infotype[CURLINFO_END] = {
528     "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
529
530 #ifdef CURL_DOES_CONVERSIONS
531   char buf[BUFSIZE+1];
532
533   switch(type) {
534   case CURLINFO_HEADER_OUT:
535     /* assume output headers are ASCII */
536     /* copy the data into my buffer so the original is unchanged */
537     if (size > BUFSIZE) {
538       size = BUFSIZE; /* truncate if necessary */
539       buf[BUFSIZE] = '\0';
540     }
541     memcpy(buf, ptr, size);
542     Curl_convert_from_network(data, buf, size);
543     /* Curl_convert_from_network calls failf if unsuccessful */
544     /* we might as well continue even if it fails...   */
545     ptr = buf; /* switch pointer to use my buffer instead */
546     break;
547   default:
548     /* leave everything else as-is */
549     break;
550   }
551 #endif /* CURL_DOES_CONVERSIONS */
552
553   if(data->set.fdebug)
554     return (*data->set.fdebug)(data, type, ptr, size,
555                                data->set.debugdata);
556
557   switch(type) {
558   case CURLINFO_TEXT:
559   case CURLINFO_HEADER_OUT:
560   case CURLINFO_HEADER_IN:
561     fwrite(s_infotype[type], 2, 1, data->set.err);
562     fwrite(ptr, size, 1, data->set.err);
563     break;
564   default: /* nada */
565     break;
566   }
567   return 0;
568 }
569
570 int Curl_debug(struct SessionHandle *data, curl_infotype type,
571                char *ptr, size_t size,
572                struct connectdata *conn)
573 {
574   int rc;
575   if(data->set.printhost && conn && conn->host.dispname) {
576     char buffer[160];
577     const char *t=NULL;
578     const char *w="Data";
579     switch (type) {
580     case CURLINFO_HEADER_IN:
581       w = "Header";
582     case CURLINFO_DATA_IN:
583       t = "from";
584       break;
585     case CURLINFO_HEADER_OUT:
586       w = "Header";
587     case CURLINFO_DATA_OUT:
588       t = "to";
589       break;
590     default:
591       break;
592     }
593
594     if(t) {
595       snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
596                conn->host.dispname);
597       rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
598       if(rc)
599         return rc;
600     }
601   }
602   rc = showit(data, type, ptr, size);
603   return rc;
604 }