14a285bdaSBarry Smith 24a285bdaSBarry Smith #include <petscwebclient.h> 31c7e414eSJacob Faibussowitsch PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wdeprecated-declarations") 44a285bdaSBarry Smith 54a285bdaSBarry Smith /* 64a285bdaSBarry Smith These variables identify the code as a PETSc application to Box. 74a285bdaSBarry Smith 8a8d69d7bSBarry Smith See - https://stackoverflow.com/questions/4616553/using-oauth-in-free-open-source-software 9a8d69d7bSBarry Smith Users can get their own application IDs - goto https://developer.box.com 104a285bdaSBarry Smith 114a285bdaSBarry Smith */ 124a285bdaSBarry Smith #define PETSC_BOX_CLIENT_ID "sse42nygt4zqgrdwi0luv79q1u1f0xza" 134a285bdaSBarry Smith #define PETSC_BOX_CLIENT_ST "A0Dy4KgOYLB2JIYZqpbze4EzjeIiX5k4" 144a285bdaSBarry Smith 15f044a08eSBarry Smith #if defined(PETSC_HAVE_SAWS) 164a285bdaSBarry Smith #include <mongoose.h> 174a285bdaSBarry Smith 184a285bdaSBarry Smith static volatile char *result = NULL; 194a285bdaSBarry Smith 20d71ae5a4SJacob Faibussowitsch static int PetscBoxWebServer_Private(struct mg_connection *conn) 21d71ae5a4SJacob Faibussowitsch { 224a285bdaSBarry Smith const struct mg_request_info *request_info = mg_get_request_info(conn); 234a285bdaSBarry Smith result = (char *)request_info->query_string; 24f044a08eSBarry Smith return 1; /* Mongoose will now not handle the request */ 254a285bdaSBarry Smith } 264a285bdaSBarry Smith 27f044a08eSBarry Smith /* 28f044a08eSBarry Smith Box can only return an authorization code to a Webserver, hence we need to start one up and wait for 29f044a08eSBarry Smith the authorization code to arrive from Box 30f044a08eSBarry Smith */ 31d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscBoxStartWebServer_Private(void) 32d71ae5a4SJacob Faibussowitsch { 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 44c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(keyfile, "sslclient.pem", sizeof(keyfile))); 459566063dSJacob Faibussowitsch PetscCall(PetscTestFile(keyfile, 'r', &exists)); 4668e69593SBarry Smith if (!exists) { 479566063dSJacob Faibussowitsch PetscCall(PetscGetHomeDirectory(keyfile, PETSC_MAX_PATH_LEN)); 48c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(keyfile, "/", sizeof(keyfile))); 49c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(keyfile, "sslclient.pem", sizeof(keyfile))); 509566063dSJacob Faibussowitsch PetscCall(PetscTestFile(keyfile, 'r', &exists)); 5128b400f6SJacob Faibussowitsch PetscCheck(exists, 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. */ 599566063dSJacob Faibussowitsch PetscCall(PetscMemzero(&callbacks, sizeof(callbacks))); 604a285bdaSBarry Smith callbacks.begin_request = PetscBoxWebServer_Private; 614a285bdaSBarry Smith ctx = mg_start(&callbacks, NULL, options); 6228b400f6SJacob Faibussowitsch PetscCheck(ctx, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to start up webserver"); 634a285bdaSBarry Smith while (!result) { }; 643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 654a285bdaSBarry Smith } 664a285bdaSBarry Smith 6768e69593SBarry Smith #if defined(PETSC_HAVE_UNISTD_H) 6868e69593SBarry Smith #include <unistd.h> 6968e69593SBarry Smith #endif 7068e69593SBarry Smith 714a285bdaSBarry Smith /*@C 724a285bdaSBarry Smith PetscBoxAuthorize - Get authorization and refresh token for accessing Box drive from PETSc 734a285bdaSBarry Smith 7420f4b53cSBarry Smith Not Collective, only the first rank in `MPI_Comm` does anything 754a285bdaSBarry Smith 764a285bdaSBarry Smith Input Parameters: 774a285bdaSBarry Smith + comm - the MPI communicator 784a285bdaSBarry Smith - tokensize - size of the token arrays 794a285bdaSBarry Smith 804a285bdaSBarry Smith Output Parameters: 81811af0c4SBarry Smith + access_token - can be used with `PetscBoxUpload()` for this one session 82*10450e9eSJacob Faibussowitsch - refresh_token - can be used for ever to obtain new access_tokens with `PetscBoxRefresh()`, 83*10450e9eSJacob Faibussowitsch guard this like a password it gives access to your Box Drive 844a285bdaSBarry Smith 8520f4b53cSBarry Smith Level: intermediate 8620f4b53cSBarry Smith 8795452b02SPatrick Sanan Notes: 8820f4b53cSBarry Smith This call requires `stdout` and `stdin` access from process 0 on the MPI communicator 894a285bdaSBarry Smith 90*10450e9eSJacob Faibussowitsch You can run src/sys/webclient/tutorials/boxobtainrefreshtoken to get a refresh token and then 91*10450e9eSJacob Faibussowitsch in the future pass it to PETSc programs with `-box_refresh_token XXX` 924a285bdaSBarry Smith 9320f4b53cSBarry 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 9620f4b53cSBarry Smith .vb 9720f4b53cSBarry Smith saws/CA.pl -newcert (using the passphrase of password) 9820f4b53cSBarry Smith cat newkey.pem newcert.pem > sslclient.pem 9920f4b53cSBarry Smith .ve 100*10450e9eSJacob Faibussowitsch and put the resulting file in either the current directory (with the application) or in the 101*10450e9eSJacob Faibussowitsch home directory. This seems kind of silly but it was all I could figure out. 10268e69593SBarry Smith 103c30dda00SJacob Faibussowitsch .seealso: `PetscBoxRefresh()`, `PetscBoxUpload()` 1044a285bdaSBarry Smith @*/ 105d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBoxAuthorize(MPI_Comm comm, char access_token[], char refresh_token[], size_t tokensize) 106d71ae5a4SJacob Faibussowitsch { 1074a285bdaSBarry Smith SSL_CTX *ctx; 1084a285bdaSBarry Smith SSL *ssl; 1094a285bdaSBarry Smith int sock; 1105dc0f0a4SBarry Smith char buff[8 * 1024], body[1024]; 1114a285bdaSBarry Smith PetscMPIInt rank; 1125dc0f0a4SBarry Smith PetscBool flg, found; 1134a285bdaSBarry Smith 1144a285bdaSBarry Smith PetscFunctionBegin; 1159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 116dd400576SPatrick Sanan if (rank == 0) { 117cc73adaaSBarry Smith PetscCheck(isatty(fileno(PETSC_STDOUT)), PETSC_COMM_SELF, PETSC_ERR_USER, "Requires users input/output"); 118d0609cedSBarry Smith PetscCall(PetscPrintf(comm, "Cut and paste the following into your browser:\n\n" 1194a285bdaSBarry Smith "https://www.box.com/api/oauth2/authorize?" 1204a285bdaSBarry Smith "response_type=code&" 1219371c9d4SSatish Balay "client_id=" PETSC_BOX_CLIENT_ID "&state=PETScState" 122d0609cedSBarry Smith "\n\n")); 1239566063dSJacob Faibussowitsch PetscCall(PetscBoxStartWebServer_Private()); 1249566063dSJacob Faibussowitsch PetscCall(PetscStrbeginswith((const char *)result, "state=PETScState&code=", &flg)); 12528b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_LIB, "Did not get expected string from Box got %s", result); 1269566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(buff, (const char *)result + 22, sizeof(buff))); 1274a285bdaSBarry Smith 1289566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 1299566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("www.box.com", 443, ctx, &sock, &ssl)); 130c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(body, "code=", sizeof(body))); 131c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, buff, sizeof(body))); 132c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&client_id=", sizeof(body))); 133c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, PETSC_BOX_CLIENT_ID, sizeof(body))); 134c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&client_secret=", sizeof(body))); 135c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, PETSC_BOX_CLIENT_ST, sizeof(body))); 136c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&grant_type=authorization_code", sizeof(body))); 1374a285bdaSBarry Smith 1389566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("POST", "www.box.com/api/oauth2/token", NULL, "application/x-www-form-urlencoded", body, ssl, buff, sizeof(buff))); 1399566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 1404a285bdaSBarry Smith close(sock); 1414a285bdaSBarry Smith 1429566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "access_token", access_token, tokensize, &found)); 14328b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Box did not return access token"); 1449566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "refresh_token", refresh_token, tokensize, &found)); 14528b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Box did not return refresh token"); 1464a285bdaSBarry Smith 1479566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Here is your Box refresh token, save it in a save place, in the future you can run PETSc\n")); 1489566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "programs with the option -box_refresh_token %s\n", refresh_token)); 1499566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "to access Box Drive automatically\n")); 1504a285bdaSBarry Smith } 1513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1524a285bdaSBarry Smith } 153f044a08eSBarry Smith #endif 1544a285bdaSBarry Smith 1554a285bdaSBarry Smith /*@C 1564a285bdaSBarry Smith PetscBoxRefresh - Get a new authorization token for accessing Box drive from PETSc from a refresh token 1574a285bdaSBarry Smith 15820f4b53cSBarry Smith Not Collective, only the first process in the `MPI_Comm` does anything 1594a285bdaSBarry Smith 1604a285bdaSBarry Smith Input Parameters: 1614a285bdaSBarry Smith + comm - MPI communicator 162aec76313SJacob Faibussowitsch . refresh_token - obtained with `PetscBoxAuthorize()`, if `NULL` PETSc will first look for one in the options data 163811af0c4SBarry Smith if not found it will call `PetscBoxAuthorize()` 1644a285bdaSBarry Smith - tokensize - size of the output string access_token 1654a285bdaSBarry Smith 166d8d19677SJose E. Roman Output Parameters: 167811af0c4SBarry Smith + access_token - token that can be passed to `PetscBoxUpload()` 1684a285bdaSBarry 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 1694a285bdaSBarry Smith 1702b26979fSBarry Smith Level: intermediate 1712b26979fSBarry Smith 172c30dda00SJacob Faibussowitsch .seealso: `PetscBoxAuthorize()`, `PetscBoxUpload()` 1734a285bdaSBarry Smith @*/ 174d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBoxRefresh(MPI_Comm comm, const char refresh_token[], char access_token[], char new_refresh_token[], size_t tokensize) 175d71ae5a4SJacob Faibussowitsch { 1764a285bdaSBarry Smith SSL_CTX *ctx; 1774a285bdaSBarry Smith SSL *ssl; 1784a285bdaSBarry Smith int sock; 1795dc0f0a4SBarry Smith char buff[8 * 1024], body[1024]; 1804a285bdaSBarry Smith PetscMPIInt rank; 1815dc0f0a4SBarry Smith char *refreshtoken = (char *)refresh_token; 1825dc0f0a4SBarry Smith PetscBool found; 1834a285bdaSBarry Smith 1844a285bdaSBarry Smith PetscFunctionBegin; 1859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 186dd400576SPatrick Sanan if (rank == 0) { 1874a285bdaSBarry Smith if (!refresh_token) { 1884a285bdaSBarry Smith PetscBool set; 1899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(512, &refreshtoken)); 1909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-box_refresh_token", refreshtoken, sizeof(refreshtoken), &set)); 19199374591SBarry Smith #if defined(PETSC_HAVE_SAWS) 1924a285bdaSBarry Smith if (!set) { 1939566063dSJacob Faibussowitsch PetscCall(PetscBoxAuthorize(comm, access_token, new_refresh_token, 512 * sizeof(char))); 1949566063dSJacob Faibussowitsch PetscCall(PetscFree(refreshtoken)); 1953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1964a285bdaSBarry Smith } 19799374591SBarry Smith #else 19828b400f6SJacob Faibussowitsch PetscCheck(set, PETSC_COMM_SELF, PETSC_ERR_LIB, "Must provide refresh token with -box_refresh_token XXX"); 19999374591SBarry Smith #endif 2004a285bdaSBarry Smith } 2019566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 2029566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("www.box.com", 443, ctx, &sock, &ssl)); 203c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(body, "client_id=", sizeof(body))); 204c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, PETSC_BOX_CLIENT_ID, sizeof(body))); 205c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&client_secret=", sizeof(body))); 206c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, PETSC_BOX_CLIENT_ST, sizeof(body))); 207c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&refresh_token=", sizeof(body))); 208c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, refreshtoken, sizeof(body))); 2099566063dSJacob Faibussowitsch if (!refresh_token) PetscCall(PetscFree(refreshtoken)); 210c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&grant_type=refresh_token", sizeof(body))); 2114a285bdaSBarry Smith 2129566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("POST", "www.box.com/api/oauth2/token", NULL, "application/x-www-form-urlencoded", body, ssl, buff, sizeof(buff))); 2139566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 2144a285bdaSBarry Smith close(sock); 2154a285bdaSBarry Smith 2169566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "access_token", access_token, tokensize, &found)); 21728b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Box did not return access token"); 2189566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "refresh_token", new_refresh_token, tokensize, &found)); 21928b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Box did not return refresh token"); 22093e1d32fSBarry Smith 2219566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Here is your new Box refresh token, save it in a save place, in the future you can run PETSc\n")); 2229566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "programs with the option -box_refresh_token %s\n", new_refresh_token)); 2239566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "to access Box Drive automatically\n")); 2244a285bdaSBarry Smith } 2253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2264a285bdaSBarry Smith } 2274a285bdaSBarry Smith 2284a285bdaSBarry Smith #include <sys/stat.h> 2294a285bdaSBarry Smith 2304a285bdaSBarry Smith /*@C 2314a285bdaSBarry Smith PetscBoxUpload - Loads a file to the Box Drive 2324a285bdaSBarry Smith 23393e1d32fSBarry Smith This routine has not yet been written; it is just copied from Google Drive 23493e1d32fSBarry Smith 235811af0c4SBarry Smith Not collective, only the first process in the `MPI_Comm` uploads the file 2364a285bdaSBarry Smith 2374a285bdaSBarry Smith Input Parameters: 2384a285bdaSBarry Smith + comm - MPI communicator 23920f4b53cSBarry Smith . access_token - obtained with `PetscBoxRefresh()`, pass `NULL` to have PETSc generate one 2404a285bdaSBarry Smith - filename - file to upload; if you upload multiple times it will have different names each time on Box Drive 2414a285bdaSBarry Smith 242811af0c4SBarry Smith Options Database Key: 24310699b91SBarry Smith . -box_refresh_token XXX - the token value 2444a285bdaSBarry Smith 245*10450e9eSJacob Faibussowitsch Example Usage: 246811af0c4SBarry Smith .vb 2474a285bdaSBarry Smith With PETSc option -box_refresh_token XXX given 2484a285bdaSBarry Smith PetscBoxUpload(comm,NULL,filename); will upload file with no user interaction 2494a285bdaSBarry Smith 2504a285bdaSBarry Smith Without PETSc option -box_refresh_token XXX given 2514a285bdaSBarry Smith PetscBoxUpload(comm,NULL,filename); for first use will prompt user to authorize access to Box Drive with their processor 2524a285bdaSBarry Smith 2534a285bdaSBarry Smith With PETSc option -box_refresh_token XXX given 2544a285bdaSBarry Smith PetscBoxRefresh(comm,NULL,access_token,sizeof(access_token)); 2554a285bdaSBarry Smith PetscBoxUpload(comm,access_token,filename); 2564a285bdaSBarry Smith 2574a285bdaSBarry Smith With refresh token entered in some way by the user 2584a285bdaSBarry Smith PetscBoxRefresh(comm,refresh_token,access_token,sizeof(access_token)); 2594a285bdaSBarry Smith PetscBoxUpload(comm,access_token,filename); 2604a285bdaSBarry Smith 2614a285bdaSBarry Smith PetscBoxAuthorize(comm,access_token,refresh_token,sizeof(access_token)); 2624a285bdaSBarry Smith PetscBoxUpload(comm,access_token,filename); 263811af0c4SBarry Smith .ve 2644a285bdaSBarry Smith 2652b26979fSBarry Smith Level: intermediate 2662b26979fSBarry Smith 267c30dda00SJacob Faibussowitsch .seealso: `PetscBoxAuthorize()`, `PetscBoxRefresh()` 2684a285bdaSBarry Smith @*/ 269d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBoxUpload(MPI_Comm comm, const char access_token[], const char filename[]) 270d71ae5a4SJacob Faibussowitsch { 2714a285bdaSBarry Smith SSL_CTX *ctx; 2724a285bdaSBarry Smith SSL *ssl; 2734a285bdaSBarry Smith int sock; 2744a285bdaSBarry Smith char head[1024], buff[8 * 1024], *body, *title; 2754a285bdaSBarry Smith PetscMPIInt rank; 2764a285bdaSBarry Smith struct stat sb; 2774a285bdaSBarry Smith size_t len, blen, rd; 2784a285bdaSBarry Smith FILE *fd; 2792da392ccSBarry Smith int err; 2804a285bdaSBarry Smith 2814a285bdaSBarry Smith PetscFunctionBegin; 2829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 283dd400576SPatrick Sanan if (rank == 0) { 284c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(head, "Authorization: Bearer ", sizeof(head))); 285c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, access_token, sizeof(head))); 286c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, "\r\n", sizeof(head))); 287c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, "uploadType: multipart\r\n", sizeof(head))); 2884a285bdaSBarry Smith 2892da392ccSBarry Smith err = stat(filename, &sb); 29028b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to stat file: %s", filename); 2914a285bdaSBarry Smith len = 1024 + sb.st_size; 2929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len, &body)); 293c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(body, 2944a285bdaSBarry Smith "--foo_bar_baz\r\n" 295c6a7a370SJeremy L Thompson "Content-Type: application/json\r\n\r\n" 296c6a7a370SJeremy L Thompson "{", 297c6a7a370SJeremy L Thompson len)); 298c6a7a370SJeremy L Thompson PetscCall(PetscPushJSONValue(body, "title", filename, len)); 299c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", len)); 300c6a7a370SJeremy L Thompson PetscCall(PetscPushJSONValue(body, "mimeType", "text.html", len)); 301c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", len)); 302c6a7a370SJeremy L Thompson PetscCall(PetscPushJSONValue(body, "description", "a file", len)); 303c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, 304c6a7a370SJeremy L Thompson "}\r\n\r\n" 305c6a7a370SJeremy L Thompson "--foo_bar_baz\r\n" 306c6a7a370SJeremy L Thompson "Content-Type: text/html\r\n\r\n", 307c6a7a370SJeremy L Thompson len)); 3089566063dSJacob Faibussowitsch PetscCall(PetscStrlen(body, &blen)); 3094a285bdaSBarry Smith fd = fopen(filename, "r"); 31028b400f6SJacob Faibussowitsch PetscCheck(fd, 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); 312cc73adaaSBarry Smith PetscCheck(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); 3134a285bdaSBarry Smith fclose(fd); 3144a285bdaSBarry Smith body[blen + rd] = 0; 315c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, 316c6a7a370SJeremy L Thompson "\r\n\r\n" 317c6a7a370SJeremy L Thompson "--foo_bar_baz\r\n", 318c6a7a370SJeremy L Thompson len)); 3199566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx)); 3209566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("www.boxapis.com", 443, ctx, &sock, &ssl)); 3219566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("POST", "www.boxapis.com/upload/drive/v2/files/", head, "multipart/related; boundary=\"foo_bar_baz\"", body, ssl, buff, sizeof(buff))); 3229566063dSJacob Faibussowitsch PetscCall(PetscFree(body)); 3239566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx)); 3244a285bdaSBarry Smith close(sock); 3259566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buff, "\"title\"", &title)); 32628b400f6SJacob Faibussowitsch PetscCheck(title, PETSC_COMM_SELF, PETSC_ERR_LIB, "Upload of file %s failed", filename); 3274a285bdaSBarry Smith } 3283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3294a285bdaSBarry Smith } 330