Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.os.linux.networking > #2196

HTTP POST for file upload

From Josef Moellers <josef.moellers@invalid.invalid>
Newsgroups comp.os.linux.networking
Subject HTTP POST for file upload
Date 2013-06-05 19:40 +0200
Message-ID <b19bg3FpriuU1@mid.individual.net> (permalink)

Show all headers | View raw


Hi,

I'm trying to extend an application to upload result files to a web
server using HTMP POST. By and large it works but the last couple of
bytes (the last line, to be precise) does not show up in the received
data. Maybe someone more knowing than I has an idea what I'm doing wrong.

Thanks in advance,

Josef


Here's my code:

# include	<sys/types.h>
# include	<sys/socket.h>
# include	<stdio.h>
# include	<string.h>
# include	<unistd.h>
# include	<netdb.h>
# include	<stdlib.h>
# include	<arpa/inet.h>

int upload(char *archive_name, char *local_name, char *remote_name, char
*servname);
static ssize_t writen(int sd, void *ptr, size_t nbytes);
static ssize_t readline(int sd, void *ptr, size_t maxlen);

char servname[] = "de2server";
char hostname[128];
/*
 * upload <archive> <file> <remote-name>
 */
int
main(int argc, char *argv[])
{
    if (argc != 4)
    {
        fprintf(stderr, "usage: %s <archive> <file> <remote-name>\n",
argv[0]);
	exit(1);
    }
    gethostname(hostname, sizeof(hostname));
    upload(argv[1], argv[2], argv[3], servname);
}

void
pr_inet(char **listptr, int length)
{
    struct in_addr *ptr;
    while ((ptr = (struct in_addr *) *listptr++) != NULL)
        printf("    %s\n", inet_ntoa(*ptr));
}
int
upload(char *archive_name, char *local_name, char *remote_name, char
*servname)
{
    int sd;
    struct sockaddr_in servaddr;
    struct hostent *he;
    FILE *src, *tmpfp;
    char buffer[BUFSIZ];
    char boundary[128];
    char line[256];
    size_t nread, content_length;

    if ((he = gethostbyname(servname)) == NULL)
    {
        fprintf(stderr, "Cannot find %s\n", servname);
	return 0;
    }
    pr_inet(he->h_addr_list, he->h_length);

    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
	return 0;
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(80);	/* Web port */
    memcpy(&servaddr.sin_addr, he->h_addr, he->h_length);

    if (connect(sd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        perror("connect");
	close(sd);
	return 0;
    }

    /* Let's assemble the body in a file so we can determine the
Content-Length */
    if ((src = fopen(local_name, "r")) == NULL)
    {
        perror(local_name);
        close(sd);
	return 0;
    }
    if ((tmpfp = tmpfile()) == NULL)
    {
        perror("tmpfile");
	close(sd);
	fclose(src);
	return 0;
    }

    snprintf(boundary, sizeof(boundary),
"WebKitFormBoundaryePkpFF7tjBAqx29L");
    content_length = 0;
    content_length += fprintf(tmpfp, "\r\n");	/* This belongs to the
content */
    content_length += fprintf(tmpfp, "------%s\r\n", boundary);
    content_length += fprintf(tmpfp, "Content-Disposition: form-data;
name=\"archive_name\"\r\n");
    content_length += fprintf(tmpfp, "\r\n");
    content_length += fprintf(tmpfp, "%s\r\n", archive_name);
    content_length += fprintf(tmpfp, "------%s\r\n", boundary);
    content_length += fprintf(tmpfp, "Content-Disposition: form-data;
name=\"destination_name\"\r\n");
    content_length += fprintf(tmpfp, "\r\n");
    content_length += fprintf(tmpfp, "%s\r\n", remote_name);
    content_length += fprintf(tmpfp, "------%s\r\n", boundary);
    content_length += fprintf(tmpfp, "Content-Disposition: form-data;
name=\"file_contents\"; filename=\"%s\"\r\n", local_name);
    content_length += fprintf(tmpfp, "Content-Type:
application/x-object\r\n");
    content_length += fprintf(tmpfp, "\r\n");
    while ((nread = fread(buffer, 1, sizeof(buffer), src)) > 0)
    {
    	fwrite(buffer, 1, nread, tmpfp);
	content_length += nread;
    }
    content_length += fprintf(tmpfp, "------%s--\r\n", boundary);
    fprintf(stderr, "content_length=%u, file length=%u\n",
content_length, ftell(tmpfp));
    fclose(src);	/* We don't need that any more */

    /* Now send request */
    snprintf(line, sizeof(line), "POST
/cgi-bin/zip.pl?upload_progress_id=12344 HTTP/1.1\r\n");
    writen(sd, line, strlen(line));
    snprintf(line, sizeof(line), "Host: %s\r\n", hostname);
    writen(sd, line, strlen(line));
    snprintf(line, sizeof(line), "Content-Length: %u\r\n", content_length);
    writen(sd, line, strlen(line));
    snprintf(line, sizeof(line), "Origin: http://%s\r\n", hostname);
    writen(sd, line, strlen(line));
    snprintf(line, sizeof(line), "Content-Type: multipart/form-data;
boundary=----%s\r\n", boundary);
    writen(sd, line, strlen(line));
    /* Copy file to sd */
    rewind(tmpfp);
    while ((nread = fread(buffer, 1, sizeof(buffer), tmpfp)) > 0)
    	writen(sd, buffer, nread);
    /*
     * Now await response
     */
    while (readline(sd, line, sizeof(line)))
	fprintf(stderr, ">>%s", line);

    close(sd);
    fclose(tmpfp);

    return 1;
}

static ssize_t
writen(int sd, void *ptr, size_t nbytes)
{
    ssize_t nleft, nwritten;
    fd_set writefds;
    struct timeval tensec;

    for (nleft = nbytes; nleft > 0; )
    {
        /* Wait up to 10s for permission to write, then give up */

        FD_ZERO(&writefds);
        FD_SET(sd, &writefds);
        tensec.tv_sec = 10;
        tensec.tv_usec = 0;
        if (select(sd+1, NULL, &writefds, NULL, &tensec) != 1)
            nwritten = -1;
        else
            nwritten = write(sd, ptr, nleft);

        if (nwritten == -1)
            return -1;
        nleft -= nwritten;
        ptr += nwritten;
    }

    return nbytes - nleft;
}

static ssize_t
readline(int sd, void *ptr, size_t maxlen)
{
    char *sp = ptr;
    ssize_t rc;
    int n;
    char c;
    fd_set readfds;
    struct timeval tensec;

    for (n = 1; n < maxlen; n++)
    {
        /* Wait up to 10s for data, then give up */

        FD_ZERO(&readfds);
        FD_SET(sd, &readfds);
        tensec.tv_sec = 10;
        tensec.tv_usec = 0;
        if (select(sd+1, &readfds, NULL, NULL, &tensec) != 1)
            rc = 0;
        else
            rc = read(sd, &c, 1);

        if (rc == 1)
        {
            *sp++ = c;
            if (c == '\n')
                break;
        }
        else if (rc == 0)       /* EOF */
        {
            if (n == 1)
                return 0;
            else
                break;
        }
        else
            return -1;
    }

    *sp = '\0';

    return n;
}
-eoc-

Back to comp.os.linux.networking | Previous | Next — Next in thread | Find similar | Unroll thread


Thread

HTTP POST for file upload Josef Moellers <josef.moellers@invalid.invalid> - 2013-06-05 19:40 +0200
  Re: HTTP POST for file upload Xavier Roche <xroche@free.fr.NOSPAM.invalid> - 2013-06-05 19:51 +0200
  Re: HTTP POST for file upload Richard Kettlewell <rjk@greenend.org.uk> - 2013-06-05 18:53 +0100
  Re: HTTP POST for file upload Josef Moellers <josef.moellers@invalid.invalid> - 2013-06-06 21:26 +0200
    Re: HTTP POST for file upload Jorgen Grahn <grahn+nntp@snipabacken.se> - 2013-06-06 21:51 +0000

csiph-web