xref: /petsc/src/sys/webclient/box.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
14a285bdaSBarry Smith 
24a285bdaSBarry Smith #include <petscwebclient.h>
3bb04b57dSBarry Smith #pragma clang diagnostic ignored "-Wdeprecated-declarations"
445e40e47SBarry Smith #pragma gcc diagnostic ignored "-Wdeprecated-declarations"
54a285bdaSBarry Smith 
64a285bdaSBarry Smith /*
74a285bdaSBarry Smith    These variables identify the code as a PETSc application to Box.
84a285bdaSBarry Smith 
9a8d69d7bSBarry Smith    See -   https://stackoverflow.com/questions/4616553/using-oauth-in-free-open-source-software
10a8d69d7bSBarry Smith    Users can get their own application IDs - goto https://developer.box.com
114a285bdaSBarry Smith 
124a285bdaSBarry Smith */
134a285bdaSBarry Smith #define PETSC_BOX_CLIENT_ID  "sse42nygt4zqgrdwi0luv79q1u1f0xza"
144a285bdaSBarry Smith #define PETSC_BOX_CLIENT_ST  "A0Dy4KgOYLB2JIYZqpbze4EzjeIiX5k4"
154a285bdaSBarry Smith 
16f044a08eSBarry Smith #if defined(PETSC_HAVE_SAWS)
174a285bdaSBarry Smith #include <mongoose.h>
184a285bdaSBarry Smith 
194a285bdaSBarry Smith static volatile char *result = NULL;
204a285bdaSBarry Smith 
214a285bdaSBarry Smith static int PetscBoxWebServer_Private(struct mg_connection *conn)
224a285bdaSBarry Smith {
234a285bdaSBarry Smith   const struct mg_request_info *request_info = mg_get_request_info(conn);
244a285bdaSBarry Smith   result = (char*) request_info->query_string;
25f044a08eSBarry Smith   return 1;  /* Mongoose will now not handle the request */
264a285bdaSBarry Smith }
274a285bdaSBarry Smith 
28f044a08eSBarry Smith /*
29f044a08eSBarry Smith     Box can only return an authorization code to a Webserver, hence we need to start one up and wait for
30f044a08eSBarry Smith     the authorization code to arrive from Box
31f044a08eSBarry Smith */
324a285bdaSBarry Smith static PetscErrorCode PetscBoxStartWebServer_Private(void)
334a285bdaSBarry Smith {
344a285bdaSBarry Smith   PetscErrorCode      ierr;
354a285bdaSBarry Smith   int                 optionsLen = 5;
364a285bdaSBarry Smith   const char          *options[optionsLen];
374a285bdaSBarry Smith   struct mg_callbacks callbacks;
384a285bdaSBarry Smith   struct mg_context   *ctx;
3968e69593SBarry Smith   char                keyfile[PETSC_MAX_PATH_LEN];
4068e69593SBarry Smith   PetscBool           exists;
414a285bdaSBarry Smith 
424a285bdaSBarry Smith   PetscFunctionBegin;
434a285bdaSBarry Smith   options[0] = "listening_ports";
444a285bdaSBarry Smith   options[1] = "8081s";
4568e69593SBarry Smith 
465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcpy(keyfile,"sslclient.pem"));
475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTestFile(keyfile,'r',&exists));
4868e69593SBarry Smith   if (!exists) {
495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscGetHomeDirectory(keyfile,PETSC_MAX_PATH_LEN));
505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(keyfile,"/"));
515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(keyfile,"sslclient.pem"));
525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTestFile(keyfile,'r',&exists));
53*28b400f6SJacob Faibussowitsch     PetscCheck(exists,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate sslclient.pem file in current directory or home directory");
5468e69593SBarry Smith   }
5568e69593SBarry Smith 
564a285bdaSBarry Smith   options[2] = "ssl_certificate";
5768e69593SBarry Smith   options[3] = keyfile;
584a285bdaSBarry Smith   options[4] = NULL;
594a285bdaSBarry Smith 
604a285bdaSBarry Smith   /* Prepare callbacks structure. We have only one callback, the rest are NULL. */
615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemzero(&callbacks, sizeof(callbacks)));
624a285bdaSBarry Smith   callbacks.begin_request = PetscBoxWebServer_Private;
634a285bdaSBarry Smith   ctx = mg_start(&callbacks, NULL, options);
64*28b400f6SJacob Faibussowitsch   PetscCheck(ctx,PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to start up webserver");
654a285bdaSBarry Smith   while (!result) {};
664a285bdaSBarry Smith   PetscFunctionReturn(0);
674a285bdaSBarry Smith }
684a285bdaSBarry Smith 
6968e69593SBarry Smith #if defined(PETSC_HAVE_UNISTD_H)
7068e69593SBarry Smith #include <unistd.h>
7168e69593SBarry Smith #endif
7268e69593SBarry Smith 
734a285bdaSBarry Smith /*@C
744a285bdaSBarry Smith      PetscBoxAuthorize - Get authorization and refresh token for accessing Box drive from PETSc
754a285bdaSBarry Smith 
764a285bdaSBarry Smith    Not collective, only the first process in MPI_Comm does anything
774a285bdaSBarry Smith 
784a285bdaSBarry Smith    Input Parameters:
794a285bdaSBarry Smith +  comm - the MPI communicator
804a285bdaSBarry Smith -  tokensize - size of the token arrays
814a285bdaSBarry Smith 
824a285bdaSBarry Smith    Output Parameters:
834a285bdaSBarry Smith +  access_token - can be used with PetscBoxUpload() for this one session
844a285bdaSBarry Smith -  refresh_token - can be used for ever to obtain new access_tokens with PetscBoxRefresh(), guard this like a password
854a285bdaSBarry Smith                    it gives access to your Box Drive
864a285bdaSBarry Smith 
8795452b02SPatrick Sanan    Notes:
8895452b02SPatrick Sanan     This call requires stdout and stdin access from process 0 on the MPI communicator
894a285bdaSBarry Smith 
90c4762a1bSJed Brown    You can run src/sys/webclient/tutorials/boxobtainrefreshtoken to get a refresh token and then in the future pass it to
914a285bdaSBarry Smith    PETSc programs with -box_refresh_token XXX
924a285bdaSBarry Smith 
93f044a08eSBarry Smith    This requires PETSc be installed using --with-saws or --download-saws
94f044a08eSBarry Smith 
9568e69593SBarry Smith    Requires the user have created a self-signed ssl certificate with
9668e69593SBarry Smith 
9768e69593SBarry Smith $    saws/CA.pl  -newcert  (using the passphrase of password)
9868e69593SBarry Smith $    cat newkey.pem newcert.pem > sslclient.pem
9968e69593SBarry Smith 
10068e69593SBarry Smith     and put the resulting file in either the current directory (with the application) or in the home directory. This seems kind of
10168e69593SBarry Smith     silly but it was all I could figure out.
10268e69593SBarry Smith 
1032b26979fSBarry Smith    Level: intermediate
1042b26979fSBarry Smith 
1054a285bdaSBarry Smith .seealso: PetscBoxRefresh(), PetscBoxUpload(), PetscURLShorten()
1064a285bdaSBarry Smith 
1074a285bdaSBarry Smith @*/
1084a285bdaSBarry Smith PetscErrorCode PetscBoxAuthorize(MPI_Comm comm,char access_token[],char refresh_token[],size_t tokensize)
1094a285bdaSBarry Smith {
1104a285bdaSBarry Smith   SSL_CTX        *ctx;
1114a285bdaSBarry Smith   SSL            *ssl;
1124a285bdaSBarry Smith   int            sock;
1134a285bdaSBarry Smith   PetscErrorCode ierr;
1145dc0f0a4SBarry Smith   char           buff[8*1024],body[1024];
1154a285bdaSBarry Smith   PetscMPIInt    rank;
1165dc0f0a4SBarry Smith   PetscBool      flg,found;
1174a285bdaSBarry Smith 
1184a285bdaSBarry Smith   PetscFunctionBegin;
1195f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm,&rank));
120dd400576SPatrick Sanan   if (rank == 0) {
1212c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!isatty(fileno(PETSC_STDOUT)),PETSC_COMM_SELF,PETSC_ERR_USER,"Requires users input/output");
1224a285bdaSBarry Smith     ierr = PetscPrintf(comm,"Cut and paste the following into your browser:\n\n"
1234a285bdaSBarry Smith                             "https://www.box.com/api/oauth2/authorize?"
1244a285bdaSBarry Smith                             "response_type=code&"
1254a285bdaSBarry Smith                             "client_id="
1264a285bdaSBarry Smith                             PETSC_BOX_CLIENT_ID
1274a285bdaSBarry Smith                             "&state=PETScState"
1284a285bdaSBarry Smith                             "\n\n");CHKERRQ(ierr);
1295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscBoxStartWebServer_Private());
1305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrbeginswith((const char*)result,"state=PETScState&code=",&flg));
131*28b400f6SJacob Faibussowitsch     PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_LIB,"Did not get expected string from Box got %s",result);
1325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrncpy(buff,(const char*)result+22,sizeof(buff)));
1334a285bdaSBarry Smith 
1345f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSSLInitializeContext(&ctx));
1355f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHTTPSConnect("www.box.com",443,ctx,&sock,&ssl));
1365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcpy(body,"code="));
1375f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,buff));
1385f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,"&client_id="));
1395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,PETSC_BOX_CLIENT_ID));
1405f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,"&client_secret="));
1415f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,PETSC_BOX_CLIENT_ST));
1425f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,"&grant_type=authorization_code"));
1434a285bdaSBarry Smith 
1445f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHTTPSRequest("POST","www.box.com/api/oauth2/token",NULL,"application/x-www-form-urlencoded",body,ssl,buff,sizeof(buff)));
1455f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSSLDestroyContext(ctx));
1464a285bdaSBarry Smith     close(sock);
1474a285bdaSBarry Smith 
1485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPullJSONValue(buff,"access_token",access_token,tokensize,&found));
149*28b400f6SJacob Faibussowitsch     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Box did not return access token");
1505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPullJSONValue(buff,"refresh_token",refresh_token,tokensize,&found));
151*28b400f6SJacob Faibussowitsch     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Box did not return refresh token");
1524a285bdaSBarry Smith 
1535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm,"Here is your Box refresh token, save it in a save place, in the future you can run PETSc\n"));
1545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm,"programs with the option -box_refresh_token %s\n",refresh_token));
1555f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm,"to access Box Drive automatically\n"));
1564a285bdaSBarry Smith   }
1574a285bdaSBarry Smith   PetscFunctionReturn(0);
1584a285bdaSBarry Smith }
159f044a08eSBarry Smith #endif
1604a285bdaSBarry Smith 
1614a285bdaSBarry Smith /*@C
1624a285bdaSBarry Smith      PetscBoxRefresh - Get a new authorization token for accessing Box drive from PETSc from a refresh token
1634a285bdaSBarry Smith 
1644a285bdaSBarry Smith    Not collective, only the first process in the MPI_Comm does anything
1654a285bdaSBarry Smith 
1664a285bdaSBarry Smith    Input Parameters:
1674a285bdaSBarry Smith +   comm - MPI communicator
1684a285bdaSBarry Smith .   refresh token - obtained with PetscBoxAuthorize(), if NULL PETSc will first look for one in the options data
1694a285bdaSBarry Smith                     if not found it will call PetscBoxAuthorize()
1704a285bdaSBarry Smith -   tokensize - size of the output string access_token
1714a285bdaSBarry Smith 
172d8d19677SJose E. Roman    Output Parameters:
1734a285bdaSBarry Smith +   access_token - token that can be passed to PetscBoxUpload()
1744a285bdaSBarry Smith -   new_refresh_token - the old refresh token is no longer valid, not this is different than Google where the same refresh_token is used forever
1754a285bdaSBarry Smith 
1762b26979fSBarry Smith    Level: intermediate
1772b26979fSBarry Smith 
1784a285bdaSBarry Smith .seealso: PetscURLShorten(), PetscBoxAuthorize(), PetscBoxUpload()
1794a285bdaSBarry Smith 
1804a285bdaSBarry Smith @*/
1814a285bdaSBarry Smith PetscErrorCode PetscBoxRefresh(MPI_Comm comm,const char refresh_token[],char access_token[],char new_refresh_token[],size_t tokensize)
1824a285bdaSBarry Smith {
1834a285bdaSBarry Smith   SSL_CTX        *ctx;
1844a285bdaSBarry Smith   SSL            *ssl;
1854a285bdaSBarry Smith   int            sock;
1864a285bdaSBarry Smith   PetscErrorCode ierr;
1875dc0f0a4SBarry Smith   char           buff[8*1024],body[1024];
1884a285bdaSBarry Smith   PetscMPIInt    rank;
1895dc0f0a4SBarry Smith   char           *refreshtoken = (char*)refresh_token;
1905dc0f0a4SBarry Smith   PetscBool      found;
1914a285bdaSBarry Smith 
1924a285bdaSBarry Smith   PetscFunctionBegin;
1935f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm,&rank));
194dd400576SPatrick Sanan   if (rank == 0) {
1954a285bdaSBarry Smith     if (!refresh_token) {
1964a285bdaSBarry Smith       PetscBool set;
1975f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(512,&refreshtoken));
1985f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscOptionsGetString(NULL,NULL,"-box_refresh_token",refreshtoken,sizeof(refreshtoken),&set));
19999374591SBarry Smith #if defined(PETSC_HAVE_SAWS)
2004a285bdaSBarry Smith       if (!set) {
2015f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscBoxAuthorize(comm,access_token,new_refresh_token,512*sizeof(char)));
2025f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFree(refreshtoken));
2034a285bdaSBarry Smith         PetscFunctionReturn(0);
2044a285bdaSBarry Smith       }
20599374591SBarry Smith #else
206*28b400f6SJacob Faibussowitsch       PetscCheck(set,PETSC_COMM_SELF,PETSC_ERR_LIB,"Must provide refresh token with -box_refresh_token XXX");
20799374591SBarry Smith #endif
2084a285bdaSBarry Smith     }
2095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSSLInitializeContext(&ctx));
2105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHTTPSConnect("www.box.com",443,ctx,&sock,&ssl));
2115f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcpy(body,"client_id="));
2125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,PETSC_BOX_CLIENT_ID));
2135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,"&client_secret="));
2145f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,PETSC_BOX_CLIENT_ST));
2155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,"&refresh_token="));
2165f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,refreshtoken));
2175f80ce2aSJacob Faibussowitsch     if (!refresh_token) CHKERRQ(PetscFree(refreshtoken));
2185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,"&grant_type=refresh_token"));
2194a285bdaSBarry Smith 
2205f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHTTPSRequest("POST","www.box.com/api/oauth2/token",NULL,"application/x-www-form-urlencoded",body,ssl,buff,sizeof(buff)));
2215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSSLDestroyContext(ctx));
2224a285bdaSBarry Smith     close(sock);
2234a285bdaSBarry Smith 
2245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPullJSONValue(buff,"access_token",access_token,tokensize,&found));
225*28b400f6SJacob Faibussowitsch     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Box did not return access token");
2265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPullJSONValue(buff,"refresh_token",new_refresh_token,tokensize,&found));
227*28b400f6SJacob Faibussowitsch     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_LIB,"Box did not return refresh token");
22893e1d32fSBarry Smith 
2295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm,"Here is your new Box refresh token, save it in a save place, in the future you can run PETSc\n"));
2305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm,"programs with the option -box_refresh_token %s\n",new_refresh_token));
2315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm,"to access Box Drive automatically\n"));
2324a285bdaSBarry Smith   }
2334a285bdaSBarry Smith   PetscFunctionReturn(0);
2344a285bdaSBarry Smith }
2354a285bdaSBarry Smith 
2364a285bdaSBarry Smith #include <sys/stat.h>
2374a285bdaSBarry Smith 
2384a285bdaSBarry Smith /*@C
2394a285bdaSBarry Smith      PetscBoxUpload - Loads a file to the Box Drive
2404a285bdaSBarry Smith 
24193e1d32fSBarry Smith      This routine has not yet been written; it is just copied from Google Drive
24293e1d32fSBarry Smith 
2434a285bdaSBarry Smith      Not collective, only the first process in the MPI_Comm uploads the file
2444a285bdaSBarry Smith 
2454a285bdaSBarry Smith   Input Parameters:
2464a285bdaSBarry Smith +   comm - MPI communicator
2474a285bdaSBarry Smith .   access_token - obtained with PetscBoxRefresh(), pass NULL to have PETSc generate one
2484a285bdaSBarry Smith -   filename - file to upload; if you upload multiple times it will have different names each time on Box Drive
2494a285bdaSBarry Smith 
2504a285bdaSBarry Smith   Options Database:
25110699b91SBarry Smith .  -box_refresh_token XXX - the token value
2524a285bdaSBarry Smith 
2534a285bdaSBarry Smith   Usage Patterns:
2544a285bdaSBarry Smith     With PETSc option -box_refresh_token XXX given
2554a285bdaSBarry Smith     PetscBoxUpload(comm,NULL,filename);        will upload file with no user interaction
2564a285bdaSBarry Smith 
2574a285bdaSBarry Smith     Without PETSc option -box_refresh_token XXX given
2584a285bdaSBarry Smith     PetscBoxUpload(comm,NULL,filename);        for first use will prompt user to authorize access to Box Drive with their processor
2594a285bdaSBarry Smith 
2604a285bdaSBarry Smith     With PETSc option -box_refresh_token  XXX given
2614a285bdaSBarry Smith     PetscBoxRefresh(comm,NULL,access_token,sizeof(access_token));
2624a285bdaSBarry Smith     PetscBoxUpload(comm,access_token,filename);
2634a285bdaSBarry Smith 
2644a285bdaSBarry Smith     With refresh token entered in some way by the user
2654a285bdaSBarry Smith     PetscBoxRefresh(comm,refresh_token,access_token,sizeof(access_token));
2664a285bdaSBarry Smith     PetscBoxUpload(comm,access_token,filename);
2674a285bdaSBarry Smith 
2684a285bdaSBarry Smith     PetscBoxAuthorize(comm,access_token,refresh_token,sizeof(access_token));
2694a285bdaSBarry Smith     PetscBoxUpload(comm,access_token,filename);
2704a285bdaSBarry Smith 
2712b26979fSBarry Smith    Level: intermediate
2722b26979fSBarry Smith 
2734a285bdaSBarry Smith .seealso: PetscURLShorten(), PetscBoxAuthorize(), PetscBoxRefresh()
2744a285bdaSBarry Smith 
2754a285bdaSBarry Smith @*/
2764a285bdaSBarry Smith PetscErrorCode PetscBoxUpload(MPI_Comm comm,const char access_token[],const char filename[])
2774a285bdaSBarry Smith {
2784a285bdaSBarry Smith   SSL_CTX        *ctx;
2794a285bdaSBarry Smith   SSL            *ssl;
2804a285bdaSBarry Smith   int            sock;
2814a285bdaSBarry Smith   PetscErrorCode ierr;
2824a285bdaSBarry Smith   char           head[1024],buff[8*1024],*body,*title;
2834a285bdaSBarry Smith   PetscMPIInt    rank;
2844a285bdaSBarry Smith   struct stat    sb;
2854a285bdaSBarry Smith   size_t         len,blen,rd;
2864a285bdaSBarry Smith   FILE           *fd;
2872da392ccSBarry Smith   int            err;
2884a285bdaSBarry Smith 
2894a285bdaSBarry Smith   PetscFunctionBegin;
2905f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm,&rank));
291dd400576SPatrick Sanan   if (rank == 0) {
2925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcpy(head,"Authorization: Bearer "));
2935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(head,access_token));
2945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(head,"\r\n"));
2955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(head,"uploadType: multipart\r\n"));
2964a285bdaSBarry Smith 
2972da392ccSBarry Smith     err = stat(filename,&sb);
298*28b400f6SJacob Faibussowitsch     PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to stat file: %s",filename);
2994a285bdaSBarry Smith     len = 1024 + sb.st_size;
3005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(len,&body));
3014a285bdaSBarry Smith     ierr = PetscStrcpy(body,"--foo_bar_baz\r\n"
3024a285bdaSBarry Smith                             "Content-Type: application/json\r\n\r\n"
3035dc0f0a4SBarry Smith                             "{");CHKERRQ(ierr);
3045f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPushJSONValue(body,"title",filename,len));
3055f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,","));
3065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPushJSONValue(body,"mimeType","text.html",len));
3075f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcat(body,","));
3085f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPushJSONValue(body,"description","a file",len));
3095dc0f0a4SBarry Smith     ierr = PetscStrcat(body, "}\r\n\r\n"
3104a285bdaSBarry Smith                              "--foo_bar_baz\r\n"
3115dc0f0a4SBarry Smith                              "Content-Type: text/html\r\n\r\n");CHKERRQ(ierr);
3125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrlen(body,&blen));
3134a285bdaSBarry Smith     fd = fopen (filename, "r");
314*28b400f6SJacob Faibussowitsch     PetscCheck(fd,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file: %s",filename);
3154a285bdaSBarry Smith     rd = fread (body+blen, sizeof (unsigned char), sb.st_size, fd);
3162c71b3e2SJacob Faibussowitsch     PetscCheckFalse(rd != (size_t)sb.st_size,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to read entire file: %s %d %d",filename,(int)rd,(int)sb.st_size);
3174a285bdaSBarry Smith     fclose(fd);
3184a285bdaSBarry Smith     body[blen + rd] = 0;
3194a285bdaSBarry Smith     ierr = PetscStrcat(body,"\r\n\r\n"
320302440fdSBarry Smith                             "--foo_bar_baz\r\n");CHKERRQ(ierr);
3215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSSLInitializeContext(&ctx));
3225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHTTPSConnect("www.boxapis.com",443,ctx,&sock,&ssl));
3235f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHTTPSRequest("POST","www.boxapis.com/upload/drive/v2/files/",head,"multipart/related; boundary=\"foo_bar_baz\"",body,ssl,buff,sizeof(buff)));
3245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(body));
3255f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSSLDestroyContext(ctx));
3264a285bdaSBarry Smith     close(sock);
3275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrstr(buff,"\"title\"",&title));
328*28b400f6SJacob Faibussowitsch     PetscCheck(title,PETSC_COMM_SELF,PETSC_ERR_LIB,"Upload of file %s failed",filename);
3294a285bdaSBarry Smith   }
3304a285bdaSBarry Smith   PetscFunctionReturn(0);
3314a285bdaSBarry Smith }
332