cURL / Mailing Lists / curl-library / Single Mail

curl-library

Content Type - Message Boundary issue in YouTube upload

From: Tanmay Anjaria <tanmay.anjaria_at_gmail.com>
Date: Wed, 14 Jan 2009 14:30:56 +0530

Hi Daniel,

Sorry for top posting. I'll take care now on.

and sorry that I could not comprehend your point before but it took me time
as I'm working for the first time on HTTP and cURL, both. As I have got it
now, libcurl do not support multipart/related format.

Please do a final favor to me. I'm sending the full code including my
username, pw, client ID and developer key. So that you can build and run it
if you wish. I'm doing this because I'm not allowed to attach codes to
gmail.

Can you please tell me if this implementation is okay.

Thanks,
Tanmay

code:
=====

#include <stdio.h>
#include <string.h>
#include <curl.h>

const char
data[]="Email=iamutubefanno1&Passwd=myutubemyutube&service=youtube&source=Test";

char tempData[MAX_PATH];
char tempDataCopy[MAX_PATH];
char auth[MAX_PATH]="Authorization:";
char authFinal[MAX_PATH];
char authToken[MAX_PATH]="AuthSub token=";
char clientID[MAX_PATH]="ytapi-TanmayAnjaria-YouTubeTest-p4pkm8dley";
char
developerKey[MAX_PATH]="AI39si7FhRPBr38Mc6H8KkVb6PGU0osPIUpZBAL8gNd4dQ8u0Tv5aOqr2enp25-EGVyZLva1hA0eUASqn9NVAMyLB7ISABeHDQ";
char boundary[MAX_PATH]="multipart/related; boundary=1a177433f849";

char quote[5]="\"";
char quote_temp[MAX_PATH]={0};

struct WriteThis {
  const char *readptr;
  int sizeleft;
};

size_t WriteDataCallback(void *ptr, size_t size, size_t count, void *data)
{

    char *st=NULL;
    char *temp = NULL;
    int i=0;

    strcpy(&tempData,ptr);
    printf("tempData = \n");
    printf("%s",tempData);
    printf("\n");

    return size * count;
}

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void
*userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if(pooh->sizeleft) {
    *(char *)ptr = pooh->readptr[0]; /* copy one single byte */
    pooh->readptr++; /* advance pointer */
    pooh->sizeleft--; /* less data left */
    return 1; /* we return 1 byte at a time! */
  }

  printf("pooh->sizeleft = %d\n\n",pooh->sizeleft);

  return 0; /* no more data left to deliver */
}

int main(void)
{
    CURL *curl;
    CURLcode res;

    struct WriteThis pooh;
    struct curl_httppost* formpost = NULL;
    struct curl_httppost* lastptr = NULL;

    FILE *fp = NULL;
    FILE *name = NULL;
    FILE *fp_xml = NULL;

    char *video_buffer = NULL;
    long begin, end;
    char file_length[MAX_PATH];
    char *buffer;

    int i=0;
    long lFileSize = 0;
    long lXmlSize = 0;

    int read_bytes = 0;
    int written_bytes = 0;

    pooh.readptr = data;
    pooh.sizeleft = strlen(data);

    video_buffer = (char *) malloc(1024 * 230 * 1024 * sizeof(char));
    if(NULL == video_buffer)
    {
        printf("ERROR: in allocating the video buffer\n");
    }

    curl = curl_easy_init();
    if(curl) {
        /* First set the URL that is about to receive our POST. */
        curl_easy_setopt(curl, CURLOPT_URL, "
https://www.google.com/youtube/accounts/ClientLogin");

        curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,FALSE);

        curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1);

        /* Now specify we want to POST data */
        curl_easy_setopt(curl, CURLOPT_POST, 1L);

        /* we want to use our own read function */
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);

        /* pointer to pass to our read function */
        curl_easy_setopt(curl, CURLOPT_READDATA, &pooh);

        /* get verbose debug output please */
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteDataCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);

        /*
        If you use POST to a HTTP 1.1 server, you can send data without
knowing
        the size before starting the POST if you use chunked encoding. You
        enable this by adding a header like "Transfer-Encoding: chunked"
with
        CURLOPT_HTTPHEADER. With HTTP 1.0 or without chunked transfer, you
must
        specify the size in the request.
        */
#ifdef USE_CHUNKED
        {
            struct curl_slist *chunk = NULL;

            chunk = curl_slist_append(chunk, "Transfer-Encoding: chunked");
            res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
            /* use curl_slist_free_all() after the *perform() call to free
this
            list again */
        }
#else
        /* Set the expected POST size. If you want to POST large amounts of
data,
        consider CURLOPT_POSTFIELDSIZE_LARGE */
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,
(curl_off_t)pooh.sizeleft);
#endif

        /* Perform the request, res will get the return code */
        res = curl_easy_perform(curl);

        for(i=5;tempData[i]!='\n';i++)
        {
            tempDataCopy[i-5] = tempData[i];
        }

        strcpy(authFinal,auth);
        strcat(authFinal, tempDataCopy);

        /************ FILE Uploading Starts ************/

        fp = fopen("search.mp4","rb");
        if(NULL == fp)
        {
            printf("ERROR: in opening the file\n");
        }

        fp_xml = fopen("test.xml","rb");
        if(NULL == fp_xml)
        {
            printf("ERROR: in opening the file\n");
        }

        begin = ftell(fp);
        fseek(fp,0L,SEEK_END);
        end = ftell(fp);
        lFileSize = end - begin;
        fseek(fp,0L,SEEK_SET);

        begin = ftell(fp_xml);
        fseek(fp_xml,0L,SEEK_END);
        end = ftell(fp_xml);
        lXmlSize = end - begin;
        fseek(fp_xml,0L,SEEK_SET);

        buffer = (char *) malloc(lXmlSize);
        if(NULL == buffer)
        {
            printf("ERROR: in allocating the xml buffer\n");
        }

        fread(buffer,1,lXmlSize,fp_xml);

        fclose(fp);
        fclose(fp_xml);

        itoa(lFileSize,file_length,10);

        fp = fopen("search.mp4","rb");
        read_bytes = fread(video_buffer,1,lFileSize,fp);
        fclose(fp);

        name = fopen("output.mp4","wb");
        written_bytes = fwrite(video_buffer,1,lFileSize,name);
        fclose(name);

        /* First set the URL that is about to receive our POST. */
        curl_easy_setopt(curl, CURLOPT_URL, "
http://uploads.gdata.youtube.com/feeds/api/users/default/uploads");

        res = curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
CURL_HTTP_VERSION_1_1);

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "Host:",
                        CURLFORM_NAMELENGTH, strlen("Host:"),
                        CURLFORM_COPYCONTENTS, "uploads.gdata.youtube.com",
                        CURLFORM_CONTENTSLENGTH,strlen("
uploads.gdata.youtube.com"),
                        CURLFORM_END );

        strcat(authToken, tempDataCopy);

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, auth,
                        CURLFORM_NAMELENGTH, strlen(auth),
                        CURLFORM_COPYCONTENTS, authToken,
                        CURLFORM_CONTENTSLENGTH,strlen(authToken),
                        CURLFORM_END );

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "GData-Version:",
                        CURLFORM_NAMELENGTH, strlen("GData-Version:"),
                        CURLFORM_COPYCONTENTS, "2",
                        CURLFORM_CONTENTSLENGTH,strlen("2"),
                        CURLFORM_END );

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "X-GData-Client:",
                        CURLFORM_NAMELENGTH, strlen("X-GData-Client:"),
                        CURLFORM_COPYCONTENTS, clientID,
                        CURLFORM_CONTENTSLENGTH,strlen(clientID),
                        CURLFORM_END );

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "X-GData-Key:",
                        CURLFORM_NAMELENGTH, strlen("X-GData-Key:"),
                        CURLFORM_COPYCONTENTS, developerKey,
                        CURLFORM_CONTENTSLENGTH,strlen(developerKey),
                        CURLFORM_END );

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "Slug:",
                        CURLFORM_NAMELENGTH, strlen("Slug:"),
                        CURLFORM_COPYCONTENTS, "search.mp4",
                        CURLFORM_CONTENTSLENGTH,strlen("search.mp4"),
                        CURLFORM_END );

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "Content-Type:",
                        CURLFORM_NAMELENGTH, strlen("Content-Type:"),
                        CURLFORM_COPYCONTENTS, boundary,
                        CURLFORM_CONTENTSLENGTH,strlen(boundary),
                        CURLFORM_END );

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "Content-Length:",
                        CURLFORM_NAMELENGTH, strlen("Content-Length:"),
                        CURLFORM_COPYCONTENTS, file_length,
                        CURLFORM_CONTENTSLENGTH,strlen(file_length),
                        CURLFORM_END );

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "Connection:",
                        CURLFORM_NAMELENGTH, strlen("Connection:"),
                        CURLFORM_COPYCONTENTS, "close",
                        CURLFORM_CONTENTSLENGTH,strlen("close"),
                        CURLFORM_END );

        /****************************** API_XML_request
******************************/
#if 1
        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "Content-Type:",
                        CURLFORM_NAMELENGTH, strlen("Content-Type:"),
                        CURLFORM_COPYCONTENTS, "application/atom+xml;
charset=UTF-8",

CURLFORM_CONTENTSLENGTH,strlen("application/atom+xml; charset=UTF-8"),
                        CURLFORM_END );

        /* POST the xml file here */
        /* Set the expected POST field and size */
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buffer);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)lXmlSize);

#endif

/*****************************************************************************/

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "Content-Type:",
                        CURLFORM_NAMELENGTH, strlen("Content-Type:"),
                        CURLFORM_COPYCONTENTS, "video/mp4",
                        CURLFORM_CONTENTSLENGTH,strlen("video/mp4"),
                        CURLFORM_END );

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_COPYNAME, "Content-Transfer-Encoding:",
                        CURLFORM_NAMELENGTH,
strlen("Content-Transfer-Encoding:"),
                        CURLFORM_COPYCONTENTS, "binary",
                        CURLFORM_CONTENTSLENGTH,strlen("binary"),
                        CURLFORM_END );

        curl_formadd( &formpost, &lastptr,
                        CURLFORM_BUFFER, "search.mp4",
                        CURLFORM_BUFFERPTR, video_buffer,
                        CURLFORM_BUFFERLENGTH, lFileSize,
                        CURLFORM_END );

        res = curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

        /* Perform the request, res will get the return code */
        res = curl_easy_perform(curl);

        /* always cleanup */
        curl_easy_cleanup(curl);
    }
  return 0;
}
Received on 2009-01-14