14a285bdaSBarry Smith 24a285bdaSBarry Smith #include <petscwebclient.h> 34a285bdaSBarry Smith 44a285bdaSBarry Smith /* 54a285bdaSBarry Smith These variables identify the code as a PETSc application to Box. 64a285bdaSBarry Smith 74a285bdaSBarry Smith See - http://stackoverflow.com/questions/4616553/using-oauth-in-free-open-source-software 84a285bdaSBarry Smith Users can get their own application IDs - goto https://developers.box.com 94a285bdaSBarry Smith 104a285bdaSBarry Smith */ 114a285bdaSBarry Smith #define PETSC_BOX_CLIENT_ID "sse42nygt4zqgrdwi0luv79q1u1f0xza" 124a285bdaSBarry Smith #define PETSC_BOX_CLIENT_ST "A0Dy4KgOYLB2JIYZqpbze4EzjeIiX5k4" 134a285bdaSBarry Smith 14f044a08eSBarry Smith #if defined(PETSC_HAVE_SAWS) 154a285bdaSBarry Smith #include <mongoose.h> 164a285bdaSBarry Smith 174a285bdaSBarry Smith static volatile char *result = NULL; 184a285bdaSBarry Smith 194a285bdaSBarry Smith static int PetscBoxWebServer_Private(struct mg_connection *conn) 204a285bdaSBarry Smith { 214a285bdaSBarry Smith const struct mg_request_info *request_info = mg_get_request_info(conn); 224a285bdaSBarry Smith result = (char*) request_info->query_string; 23f044a08eSBarry Smith return 1; /* Mongoose will now not handle the request */ 244a285bdaSBarry Smith } 254a285bdaSBarry Smith 26f044a08eSBarry Smith /* 27f044a08eSBarry Smith Box can only return an authorization code to a Webserver, hence we need to start one up and wait for 28f044a08eSBarry Smith the authorization code to arrive from Box 29f044a08eSBarry Smith */ 304a285bdaSBarry Smith static PetscErrorCode PetscBoxStartWebServer_Private(void) 314a285bdaSBarry Smith { 324a285bdaSBarry Smith PetscErrorCode ierr; 334a285bdaSBarry Smith int optionsLen = 5; 344a285bdaSBarry Smith const char *options[optionsLen]; 354a285bdaSBarry Smith struct mg_callbacks callbacks; 364a285bdaSBarry Smith struct mg_context *ctx; 3768e69593SBarry Smith char keyfile[PETSC_MAX_PATH_LEN]; 3868e69593SBarry Smith PetscBool exists; 394a285bdaSBarry Smith 404a285bdaSBarry Smith PetscFunctionBegin; 414a285bdaSBarry Smith options[0] = "listening_ports"; 424a285bdaSBarry Smith options[1] = "8081s"; 4368e69593SBarry Smith 4468e69593SBarry Smith ierr = PetscStrcpy(keyfile,"sslclient.pem");CHKERRQ(ierr); 4568e69593SBarry Smith ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr); 4668e69593SBarry Smith if (!exists) { 4768e69593SBarry Smith ierr = PetscGetHomeDirectory(keyfile,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 4868e69593SBarry Smith ierr = PetscStrcat(keyfile,"/");CHKERRQ(ierr); 4968e69593SBarry Smith ierr = PetscStrcat(keyfile,"sslclient.pem");CHKERRQ(ierr); 5068e69593SBarry Smith ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr); 5168e69593SBarry Smith if (!exists) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate sslclient.pem file in current directory or home directory"); 5268e69593SBarry Smith } 5368e69593SBarry Smith 544a285bdaSBarry Smith options[2] = "ssl_certificate"; 5568e69593SBarry Smith options[3] = keyfile; 564a285bdaSBarry Smith options[4] = NULL; 574a285bdaSBarry Smith 584a285bdaSBarry Smith /* Prepare callbacks structure. We have only one callback, the rest are NULL. */ 594a285bdaSBarry Smith ierr = PetscMemzero(&callbacks, sizeof(callbacks));CHKERRQ(ierr); 604a285bdaSBarry Smith callbacks.begin_request = PetscBoxWebServer_Private; 614a285bdaSBarry Smith ctx = mg_start(&callbacks, NULL, options); 624a285bdaSBarry Smith if (!ctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to start up webserver"); 634a285bdaSBarry Smith while (!result) {}; 644a285bdaSBarry Smith PetscFunctionReturn(0); 654a285bdaSBarry Smith } 664a285bdaSBarry Smith 6768e69593SBarry Smith #if defined(PETSC_HAVE_UNISTD_H) 6868e69593SBarry Smith #include <unistd.h> 6968e69593SBarry Smith #endif 7068e69593SBarry Smith 714a285bdaSBarry Smith #undef __FUNCT__ 724a285bdaSBarry Smith #define __FUNCT__ "PetscBoxAuthorize" 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 874a285bdaSBarry Smith Notes: This call requires stdout and stdin access from process 0 on the MPI communicator 884a285bdaSBarry Smith 89f044a08eSBarry Smith You can run src/sys/webclient/examples/tutorials/boxobtainrefreshtoken to get a refresh token and then in the future pass it to 904a285bdaSBarry Smith PETSc programs with -box_refresh_token XXX 914a285bdaSBarry Smith 92f044a08eSBarry Smith This requires PETSc be installed using --with-saws or --download-saws 93f044a08eSBarry Smith 9468e69593SBarry Smith Requires the user have created a self-signed ssl certificate with 9568e69593SBarry Smith 9668e69593SBarry Smith $ saws/CA.pl -newcert (using the passphrase of password) 9768e69593SBarry Smith $ cat newkey.pem newcert.pem > sslclient.pem 9868e69593SBarry Smith 9968e69593SBarry Smith and put the resulting file in either the current directory (with the application) or in the home directory. This seems kind of 10068e69593SBarry Smith silly but it was all I could figure out. 10168e69593SBarry Smith 1024a285bdaSBarry Smith .seealso: PetscBoxRefresh(), PetscBoxUpload(), PetscURLShorten() 1034a285bdaSBarry Smith 1044a285bdaSBarry Smith @*/ 1054a285bdaSBarry Smith PetscErrorCode PetscBoxAuthorize(MPI_Comm comm,char access_token[],char refresh_token[],size_t tokensize) 1064a285bdaSBarry Smith { 1074a285bdaSBarry Smith SSL_CTX *ctx; 1084a285bdaSBarry Smith SSL *ssl; 1094a285bdaSBarry Smith int sock; 1104a285bdaSBarry Smith PetscErrorCode ierr; 111*5dc0f0a4SBarry Smith char buff[8*1024],body[1024]; 1124a285bdaSBarry Smith PetscMPIInt rank; 113*5dc0f0a4SBarry Smith PetscBool flg,found; 1144a285bdaSBarry Smith 1154a285bdaSBarry Smith PetscFunctionBegin; 1164a285bdaSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1174a285bdaSBarry Smith if (!rank) { 11868e69593SBarry Smith if (!isatty(fileno(PETSC_STDOUT))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Requires users input/output"); 1194a285bdaSBarry Smith ierr = PetscPrintf(comm,"Cut and paste the following into your browser:\n\n" 1204a285bdaSBarry Smith "https://www.box.com/api/oauth2/authorize?" 1214a285bdaSBarry Smith "response_type=code&" 1224a285bdaSBarry Smith "client_id=" 1234a285bdaSBarry Smith PETSC_BOX_CLIENT_ID 1244a285bdaSBarry Smith "&state=PETScState" 1254a285bdaSBarry Smith "\n\n");CHKERRQ(ierr); 1264a285bdaSBarry Smith ierr = PetscBoxStartWebServer_Private();CHKERRQ(ierr); 1274a285bdaSBarry Smith ierr = PetscStrbeginswith((const char*)result,"state=PETScState&code=",&flg);CHKERRQ(ierr); 1284a285bdaSBarry Smith if (!flg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Did not get expected string from Box got %s",result); 1294a285bdaSBarry Smith ierr = PetscStrncpy(buff,(const char*)result+22,sizeof(buff));CHKERRQ(ierr); 1304a285bdaSBarry Smith 1314a285bdaSBarry Smith ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 1324a285bdaSBarry Smith ierr = PetscHTTPSConnect("www.box.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 1334a285bdaSBarry Smith ierr = PetscStrcpy(body,"code=");CHKERRQ(ierr); 1344a285bdaSBarry Smith ierr = PetscStrcat(body,buff);CHKERRQ(ierr); 1354a285bdaSBarry Smith ierr = PetscStrcat(body,"&client_id=");CHKERRQ(ierr); 1364a285bdaSBarry Smith ierr = PetscStrcat(body,PETSC_BOX_CLIENT_ID);CHKERRQ(ierr); 1374a285bdaSBarry Smith ierr = PetscStrcat(body,"&client_secret=");CHKERRQ(ierr); 1384a285bdaSBarry Smith ierr = PetscStrcat(body,PETSC_BOX_CLIENT_ST);CHKERRQ(ierr); 1394a285bdaSBarry Smith ierr = PetscStrcat(body,"&grant_type=authorization_code");CHKERRQ(ierr); 1404a285bdaSBarry Smith 14193e1d32fSBarry Smith ierr = PetscHTTPSRequest("POST","www.box.com/api/oauth2/token",NULL,"application/x-www-form-urlencoded",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 1424a285bdaSBarry Smith ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 1434a285bdaSBarry Smith close(sock); 1444a285bdaSBarry Smith 145*5dc0f0a4SBarry Smith ierr = PetscPullJSONValue(buff,"access_token",access_token,tokensize,&found);CHKERRQ(ierr); 146*5dc0f0a4SBarry Smith if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Box did not return access token"); 147*5dc0f0a4SBarry Smith ierr = PetscPullJSONValue(buff,"refresh_token",refresh_token,tokensize,&found);CHKERRQ(ierr); 148*5dc0f0a4SBarry Smith if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Box did not return refresh token"); 1494a285bdaSBarry Smith 1504a285bdaSBarry Smith ierr = PetscPrintf(comm,"Here is your Box refresh token, save it in a save place, in the future you can run PETSc\n");CHKERRQ(ierr); 151*5dc0f0a4SBarry Smith ierr = PetscPrintf(comm,"programs with the option -box_refresh_token %s\n",refresh_token);CHKERRQ(ierr); 1524a285bdaSBarry Smith ierr = PetscPrintf(comm,"to access Box Drive automatically\n");CHKERRQ(ierr); 1534a285bdaSBarry Smith } 1544a285bdaSBarry Smith PetscFunctionReturn(0); 1554a285bdaSBarry Smith } 156f044a08eSBarry Smith #endif 1574a285bdaSBarry Smith 1584a285bdaSBarry Smith #undef __FUNCT__ 1594a285bdaSBarry Smith #define __FUNCT__ "PetscBoxRefresh" 1604a285bdaSBarry Smith /*@C 1614a285bdaSBarry Smith PetscBoxRefresh - Get a new authorization token for accessing Box drive from PETSc from a refresh token 1624a285bdaSBarry Smith 1634a285bdaSBarry Smith Not collective, only the first process in the MPI_Comm does anything 1644a285bdaSBarry Smith 1654a285bdaSBarry Smith Input Parameters: 1664a285bdaSBarry Smith + comm - MPI communicator 1674a285bdaSBarry Smith . refresh token - obtained with PetscBoxAuthorize(), if NULL PETSc will first look for one in the options data 1684a285bdaSBarry Smith if not found it will call PetscBoxAuthorize() 1694a285bdaSBarry Smith - tokensize - size of the output string access_token 1704a285bdaSBarry Smith 1714a285bdaSBarry Smith Output Parameter: 1724a285bdaSBarry Smith + access_token - token that can be passed to PetscBoxUpload() 1734a285bdaSBarry 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 1744a285bdaSBarry Smith 1754a285bdaSBarry Smith .seealso: PetscURLShorten(), PetscBoxAuthorize(), PetscBoxUpload() 1764a285bdaSBarry Smith 1774a285bdaSBarry Smith @*/ 1784a285bdaSBarry Smith PetscErrorCode PetscBoxRefresh(MPI_Comm comm,const char refresh_token[],char access_token[],char new_refresh_token[],size_t tokensize) 1794a285bdaSBarry Smith { 1804a285bdaSBarry Smith SSL_CTX *ctx; 1814a285bdaSBarry Smith SSL *ssl; 1824a285bdaSBarry Smith int sock; 1834a285bdaSBarry Smith PetscErrorCode ierr; 184*5dc0f0a4SBarry Smith char buff[8*1024],body[1024]; 1854a285bdaSBarry Smith PetscMPIInt rank; 186*5dc0f0a4SBarry Smith char *refreshtoken = (char*)refresh_token; 187*5dc0f0a4SBarry Smith PetscBool found; 1884a285bdaSBarry Smith 1894a285bdaSBarry Smith PetscFunctionBegin; 1904a285bdaSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1914a285bdaSBarry Smith if (!rank) { 1924a285bdaSBarry Smith if (!refresh_token) { 1934a285bdaSBarry Smith PetscBool set; 1944a285bdaSBarry Smith ierr = PetscMalloc1(512,&refreshtoken);CHKERRQ(ierr); 1954a285bdaSBarry Smith ierr = PetscOptionsGetString(NULL,"-box_refresh_token",refreshtoken,512,&set);CHKERRQ(ierr); 19699374591SBarry Smith #if defined(PETSC_HAVE_SAWS) 1974a285bdaSBarry Smith if (!set) { 19899374591SBarry Smith ierr = PetscBoxAuthorize(comm,access_token,new_refresh_token,512*sizeof(char));CHKERRQ(ierr); 1994a285bdaSBarry Smith ierr = PetscFree(refreshtoken);CHKERRQ(ierr); 2004a285bdaSBarry Smith PetscFunctionReturn(0); 2014a285bdaSBarry Smith } 20299374591SBarry Smith #else 20399374591SBarry Smith if (!set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Must provide refresh token with -box_refresh_token XXX"); 20499374591SBarry Smith #endif 2054a285bdaSBarry Smith } 2064a285bdaSBarry Smith ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 2074a285bdaSBarry Smith ierr = PetscHTTPSConnect("www.box.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 2084a285bdaSBarry Smith ierr = PetscStrcpy(body,"client_id=");CHKERRQ(ierr); 2094a285bdaSBarry Smith ierr = PetscStrcat(body,PETSC_BOX_CLIENT_ID);CHKERRQ(ierr); 2104a285bdaSBarry Smith ierr = PetscStrcat(body,"&client_secret=");CHKERRQ(ierr); 2114a285bdaSBarry Smith ierr = PetscStrcat(body,PETSC_BOX_CLIENT_ST);CHKERRQ(ierr); 2124a285bdaSBarry Smith ierr = PetscStrcat(body,"&refresh_token=");CHKERRQ(ierr); 2134a285bdaSBarry Smith ierr = PetscStrcat(body,refreshtoken);CHKERRQ(ierr); 2144a285bdaSBarry Smith if (!refresh_token) {ierr = PetscFree(refreshtoken);CHKERRQ(ierr);} 2154a285bdaSBarry Smith ierr = PetscStrcat(body,"&grant_type=refresh_token");CHKERRQ(ierr); 2164a285bdaSBarry Smith 21793e1d32fSBarry Smith ierr = PetscHTTPSRequest("POST","www.box.com/api/oauth2/token",NULL,"application/x-www-form-urlencoded",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 2184a285bdaSBarry Smith ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 2194a285bdaSBarry Smith close(sock); 2204a285bdaSBarry Smith 221*5dc0f0a4SBarry Smith ierr = PetscPullJSONValue(buff,"access_token",access_token,tokensize,&found);CHKERRQ(ierr); 222*5dc0f0a4SBarry Smith if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Box did not return access token"); 223*5dc0f0a4SBarry Smith ierr = PetscPullJSONValue(buff,"refresh_token",new_refresh_token,tokensize,&found);CHKERRQ(ierr); 224*5dc0f0a4SBarry Smith if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Box did not return refresh token"); 22593e1d32fSBarry Smith 22693e1d32fSBarry Smith ierr = PetscPrintf(comm,"Here is your new Box refresh token, save it in a save place, in the future you can run PETSc\n");CHKERRQ(ierr); 227*5dc0f0a4SBarry Smith ierr = PetscPrintf(comm,"programs with the option -box_refresh_token %s\n",new_refresh_token);CHKERRQ(ierr); 22893e1d32fSBarry Smith ierr = PetscPrintf(comm,"to access Box Drive automatically\n");CHKERRQ(ierr); 2294a285bdaSBarry Smith } 2304a285bdaSBarry Smith PetscFunctionReturn(0); 2314a285bdaSBarry Smith } 2324a285bdaSBarry Smith 2334a285bdaSBarry Smith #include <sys/stat.h> 2344a285bdaSBarry Smith 2354a285bdaSBarry Smith #undef __FUNCT__ 2364a285bdaSBarry Smith #define __FUNCT__ "PetscBoxUpload" 2374a285bdaSBarry Smith /*@C 2384a285bdaSBarry Smith PetscBoxUpload - Loads a file to the Box Drive 2394a285bdaSBarry Smith 24093e1d32fSBarry Smith This routine has not yet been written; it is just copied from Google Drive 24193e1d32fSBarry Smith 2424a285bdaSBarry Smith Not collective, only the first process in the MPI_Comm uploads the file 2434a285bdaSBarry Smith 2444a285bdaSBarry Smith Input Parameters: 2454a285bdaSBarry Smith + comm - MPI communicator 2464a285bdaSBarry Smith . access_token - obtained with PetscBoxRefresh(), pass NULL to have PETSc generate one 2474a285bdaSBarry Smith - filename - file to upload; if you upload multiple times it will have different names each time on Box Drive 2484a285bdaSBarry Smith 2494a285bdaSBarry Smith Options Database: 2504a285bdaSBarry Smith . -box_refresh_token XXX 2514a285bdaSBarry Smith 2524a285bdaSBarry Smith Usage Patterns: 2534a285bdaSBarry Smith With PETSc option -box_refresh_token XXX given 2544a285bdaSBarry Smith PetscBoxUpload(comm,NULL,filename); will upload file with no user interaction 2554a285bdaSBarry Smith 2564a285bdaSBarry Smith Without PETSc option -box_refresh_token XXX given 2574a285bdaSBarry Smith PetscBoxUpload(comm,NULL,filename); for first use will prompt user to authorize access to Box Drive with their processor 2584a285bdaSBarry Smith 2594a285bdaSBarry Smith With PETSc option -box_refresh_token XXX given 2604a285bdaSBarry Smith PetscBoxRefresh(comm,NULL,access_token,sizeof(access_token)); 2614a285bdaSBarry Smith PetscBoxUpload(comm,access_token,filename); 2624a285bdaSBarry Smith 2634a285bdaSBarry Smith With refresh token entered in some way by the user 2644a285bdaSBarry Smith PetscBoxRefresh(comm,refresh_token,access_token,sizeof(access_token)); 2654a285bdaSBarry Smith PetscBoxUpload(comm,access_token,filename); 2664a285bdaSBarry Smith 2674a285bdaSBarry Smith PetscBoxAuthorize(comm,access_token,refresh_token,sizeof(access_token)); 2684a285bdaSBarry Smith PetscBoxUpload(comm,access_token,filename); 2694a285bdaSBarry Smith 2704a285bdaSBarry Smith .seealso: PetscURLShorten(), PetscBoxAuthorize(), PetscBoxRefresh() 2714a285bdaSBarry Smith 2724a285bdaSBarry Smith @*/ 2734a285bdaSBarry Smith PetscErrorCode PetscBoxUpload(MPI_Comm comm,const char access_token[],const char filename[]) 2744a285bdaSBarry Smith { 2754a285bdaSBarry Smith SSL_CTX *ctx; 2764a285bdaSBarry Smith SSL *ssl; 2774a285bdaSBarry Smith int sock; 2784a285bdaSBarry Smith PetscErrorCode ierr; 2794a285bdaSBarry Smith char head[1024],buff[8*1024],*body,*title; 2804a285bdaSBarry Smith PetscMPIInt rank; 2814a285bdaSBarry Smith struct stat sb; 2824a285bdaSBarry Smith size_t len,blen,rd; 2834a285bdaSBarry Smith FILE *fd; 2844a285bdaSBarry Smith 2854a285bdaSBarry Smith PetscFunctionBegin; 2864a285bdaSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 2874a285bdaSBarry Smith if (!rank) { 2884a285bdaSBarry Smith ierr = PetscStrcpy(head,"Authorization: Bearer ");CHKERRQ(ierr); 2894a285bdaSBarry Smith ierr = PetscStrcat(head,access_token);CHKERRQ(ierr); 2904a285bdaSBarry Smith ierr = PetscStrcat(head,"\r\n");CHKERRQ(ierr); 2914a285bdaSBarry Smith ierr = PetscStrcat(head,"uploadType: multipart\r\n");CHKERRQ(ierr); 2924a285bdaSBarry Smith 2934a285bdaSBarry Smith ierr = stat(filename,&sb); 2944a285bdaSBarry Smith if (ierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to stat file: %s",filename); 2954a285bdaSBarry Smith len = 1024 + sb.st_size; 2964a285bdaSBarry Smith ierr = PetscMalloc1(len,&body);CHKERRQ(ierr); 2974a285bdaSBarry Smith ierr = PetscStrcpy(body,"--foo_bar_baz\r\n" 2984a285bdaSBarry Smith "Content-Type: application/json\r\n\r\n" 299*5dc0f0a4SBarry Smith "{");CHKERRQ(ierr); 300*5dc0f0a4SBarry Smith ierr = PetscPushJSONValue(body,"title",filename,len);CHKERRQ(ierr); 301*5dc0f0a4SBarry Smith ierr = PetscStrcat(body,",");CHKERRQ(ierr); 302*5dc0f0a4SBarry Smith ierr = PetscPushJSONValue(body,"mimeType","text.html",len);CHKERRQ(ierr); 303*5dc0f0a4SBarry Smith ierr = PetscStrcat(body,",");CHKERRQ(ierr); 304*5dc0f0a4SBarry Smith ierr = PetscPushJSONValue(body,"description","a file",len);CHKERRQ(ierr); 305*5dc0f0a4SBarry Smith ierr = PetscStrcat(body, "}\r\n\r\n" 3064a285bdaSBarry Smith "--foo_bar_baz\r\n" 307*5dc0f0a4SBarry Smith "Content-Type: text/html\r\n\r\n");CHKERRQ(ierr); 3084a285bdaSBarry Smith ierr = PetscStrlen(body,&blen);CHKERRQ(ierr); 3094a285bdaSBarry Smith fd = fopen (filename, "r"); 3104a285bdaSBarry Smith if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file: %s",filename); 3114a285bdaSBarry Smith rd = fread (body+blen, sizeof (unsigned char), sb.st_size, fd); 3127a3410edSBarry Smith if (rd != (size_t)sb.st_size) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to read entire file: %s %d %d",filename,(int)rd,(int)sb.st_size); 3134a285bdaSBarry Smith fclose(fd); 3144a285bdaSBarry Smith body[blen + rd] = 0; 3154a285bdaSBarry Smith ierr = PetscStrcat(body,"\r\n\r\n" 3164a285bdaSBarry Smith "--foo_bar_baz\r\n"); 3174a285bdaSBarry Smith ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 3184a285bdaSBarry Smith ierr = PetscHTTPSConnect("www.boxapis.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 31993e1d32fSBarry Smith ierr = PetscHTTPSRequest("POST","www.boxapis.com/upload/drive/v2/files/",head,"multipart/related; boundary=\"foo_bar_baz\"",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 3204a285bdaSBarry Smith ierr = PetscFree(body);CHKERRQ(ierr); 3214a285bdaSBarry Smith ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 3224a285bdaSBarry Smith close(sock); 3234a285bdaSBarry Smith ierr = PetscStrstr(buff,"\"title\"",&title);CHKERRQ(ierr); 3244a285bdaSBarry Smith if (!title) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Upload of file %s failed",filename); 3254a285bdaSBarry Smith } 3264a285bdaSBarry Smith PetscFunctionReturn(0); 3274a285bdaSBarry Smith } 3284a285bdaSBarry Smith 3294a285bdaSBarry Smith 330