Skip to content
http.c 67.3 KiB
Newer Older

    case HTTPREQ_PUT: /* Let's PUT the data to the server! */
Daniel Stenberg's avatar
Daniel Stenberg committed

      if(conn->bits.authneg)
        postsize = 0;
      else
        postsize = data->set.infilesize;

      if((postsize != -1) && !conn->bits.upload_chunky) {
        /* only add Content-Length if not uploading chunked */
        result = add_bufferf(req_buffer,
                             "Content-Length: %" FORMAT_OFF_T "\r\n",
                             postsize );
      result = expect100(data, req_buffer);
      if(result)
        return result;
Daniel Stenberg's avatar
Daniel Stenberg committed

      result = add_buffer(req_buffer, "\r\n", 2); /* end of headers */
      if(result)
        return result;
      /* set the upload size to the progress meter */
      Curl_pgrsSetUploadSize(data, postsize);
Daniel Stenberg's avatar
Daniel Stenberg committed

      /* this sends the buffer and frees all the buffer resources */
      result = add_buffer_send(req_buffer, conn,
        failf(data, "Failed sending PUT request");
        result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE,
                               postsize?FIRSTSOCKET:-1,
                               postsize?&http->writebytecount:NULL);
Daniel Stenberg's avatar
Daniel Stenberg committed
      if(result)
        return result;
    case HTTPREQ_POST:
      /* this is the simple POST, using x-www-form-urlencoded style */
      if(conn->bits.authneg)
        postsize = 0;
      else
        /* figure out the size of the postfields */
        postsize = (data->set.postfieldsize != -1)?
          data->set.postfieldsize:
          (data->set.postfields?(curl_off_t)strlen(data->set.postfields):0);
      if(!conn->bits.upload_chunky) {
        /* We only set Content-Length and allow a custom Content-Length if
           we don't upload data chunked, as RFC2616 forbids us to set both
           kinds of headers (Transfer-Encoding: chunked and Content-Length) */

        if(!checkheaders(data, "Content-Length:")) {
          /* we allow replacing this header, although it isn't very wise to
             actually set your own */
          result = add_bufferf(req_buffer,
                               "Content-Length: %" FORMAT_OFF_T"\r\n",
                               postsize);
          if(result)
            return result;
        }
      if(!checkheaders(data, "Content-Type:")) {
        result = add_bufferf(req_buffer,
                             "Content-Type: application/x-www-form-urlencoded\r\n");
        if(result)
          return result;
      }
        if((data->state.authhost.done || data->state.authproxy.done )
           && (postsize < MAX_INITIAL_POST_SIZE)) {
Daniel Stenberg's avatar
Daniel Stenberg committed
          /* If we're not done with the authentication phase, we don't expect
             to actually send off any data yet. Hence, we delay the sending of
             the body until we receive that friendly 100-continue response */
          /* The post data is less than MAX_INITIAL_PORT_SIZE, then append it
             to the header. This limit is no magic limit but only set to
             prevent really huge POSTs to get the data duplicated with
             malloc() and family. */
Daniel Stenberg's avatar
Daniel Stenberg committed
          result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
Daniel Stenberg's avatar
Daniel Stenberg committed

            /* We're not sending it 'chunked', append it to the request
               already now to reduce the number if send() calls */
            result = add_buffer(req_buffer, data->set.postfields,
                                (size_t)postsize);
          }
          else {
            /* Append the POST data chunky-style */
            result = add_bufferf(req_buffer, "%x\r\n", (int)postsize);
            if(CURLE_OK == result)
              result = add_buffer(req_buffer, data->set.postfields,
                                  (size_t)postsize);
            if(CURLE_OK == result)
              result = add_buffer(req_buffer,
                                  "\r\n0\r\n\r\n", 7); /* end of a chunked
                                                          transfer stream */
          /* A huge POST coming up, do data separate from the request */
          http->postsize = postsize;
          http->postdata = data->set.postfields;
          conn->fread = (curl_read_callback)readmoredata;
          conn->fread_in = (void *)conn;

          /* set the upload size to the progress meter */
          Curl_pgrsSetUploadSize(data, http->postsize);
Daniel Stenberg's avatar
Daniel Stenberg committed

          result = expect100(data, req_buffer);
          if(result)
            return result;
Daniel Stenberg's avatar
Daniel Stenberg committed

          add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
        result = expect100(data, req_buffer);
        if(result)
          return result;

Daniel Stenberg's avatar
Daniel Stenberg committed
        add_buffer(req_buffer, "\r\n", 2); /* end of headers! */

        if(data->set.postfieldsize) {
          /* set the upload size to the progress meter */
          Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
          /* set the pointer to mark that we will send the post body using
             the read callback */
          http->postdata = (char *)&http->postdata;
        }
      result = add_buffer_send(req_buffer, conn,
                               &data->info.request_size);

      if(result)
        failf(data, "Failed sending HTTP POST request");
          Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE,
                        http->postdata?&http->writebytecount:NULL);
    default:
      add_buffer(req_buffer, "\r\n", 2);
      /* issue the request */
      result = add_buffer_send(req_buffer, conn,
      if(result)
        failf(data, "Failed sending HTTP request");
      else
        /* HTTP GET/HEAD download: */
        result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE,
                               http->postdata?&http->writebytecount:NULL);
Daniel Stenberg's avatar
Daniel Stenberg committed
    if(result)
      return result;
Daniel Stenberg's avatar
Daniel Stenberg committed

  return CURLE_OK;
Daniel Stenberg's avatar
Daniel Stenberg committed
}