14a285bdaSBarry Smith #include <petscwebclient.h>
21c7e414eSJacob Faibussowitsch PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wdeprecated-declarations")
34a285bdaSBarry Smith
44a285bdaSBarry Smith /*
54a285bdaSBarry Smith These variables identify the code as a PETSc application to Box.
64a285bdaSBarry Smith
7a8d69d7bSBarry Smith See - https://stackoverflow.com/questions/4616553/using-oauth-in-free-open-source-software
8a8d69d7bSBarry Smith Users can get their own application IDs - goto https://developer.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
PetscBoxWebServer_Private(struct mg_connection * conn)19d71ae5a4SJacob Faibussowitsch static int PetscBoxWebServer_Private(struct mg_connection *conn)
20d71ae5a4SJacob Faibussowitsch {
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 */
PetscBoxStartWebServer_Private(void)30d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscBoxStartWebServer_Private(void)
31d71ae5a4SJacob Faibussowitsch {
324a285bdaSBarry Smith int optionsLen = 5;
334a285bdaSBarry Smith const char *options[optionsLen];
344a285bdaSBarry Smith struct mg_callbacks callbacks;
354a285bdaSBarry Smith struct mg_context *ctx;
3668e69593SBarry Smith char keyfile[PETSC_MAX_PATH_LEN];
3768e69593SBarry Smith PetscBool exists;
384a285bdaSBarry Smith
394a285bdaSBarry Smith PetscFunctionBegin;
404a285bdaSBarry Smith options[0] = "listening_ports";
414a285bdaSBarry Smith options[1] = "8081s";
4268e69593SBarry Smith
43c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(keyfile, "sslclient.pem", sizeof(keyfile)));
449566063dSJacob Faibussowitsch PetscCall(PetscTestFile(keyfile, 'r', &exists));
4568e69593SBarry Smith if (!exists) {
469566063dSJacob Faibussowitsch PetscCall(PetscGetHomeDirectory(keyfile, PETSC_MAX_PATH_LEN));
47c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(keyfile, "/", sizeof(keyfile)));
48c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(keyfile, "sslclient.pem", sizeof(keyfile)));
499566063dSJacob Faibussowitsch PetscCall(PetscTestFile(keyfile, 'r', &exists));
5028b400f6SJacob Faibussowitsch PetscCheck(exists, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate sslclient.pem file in current directory or home directory");
5168e69593SBarry Smith }
5268e69593SBarry Smith
534a285bdaSBarry Smith options[2] = "ssl_certificate";
5468e69593SBarry Smith options[3] = keyfile;
554a285bdaSBarry Smith options[4] = NULL;
564a285bdaSBarry Smith
574a285bdaSBarry Smith /* Prepare callbacks structure. We have only one callback, the rest are NULL. */
589566063dSJacob Faibussowitsch PetscCall(PetscMemzero(&callbacks, sizeof(callbacks)));
594a285bdaSBarry Smith callbacks.begin_request = PetscBoxWebServer_Private;
604a285bdaSBarry Smith ctx = mg_start(&callbacks, NULL, options);
6128b400f6SJacob Faibussowitsch PetscCheck(ctx, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to start up webserver");
624a285bdaSBarry Smith while (!result) { };
633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
644a285bdaSBarry Smith }
654a285bdaSBarry Smith
6668e69593SBarry Smith #if defined(PETSC_HAVE_UNISTD_H)
6768e69593SBarry Smith #include <unistd.h>
6868e69593SBarry Smith #endif
6968e69593SBarry Smith
704a285bdaSBarry Smith /*@C
714a285bdaSBarry Smith PetscBoxAuthorize - Get authorization and refresh token for accessing Box drive from PETSc
724a285bdaSBarry Smith
7320f4b53cSBarry Smith Not Collective, only the first rank in `MPI_Comm` does anything
744a285bdaSBarry Smith
754a285bdaSBarry Smith Input Parameters:
764a285bdaSBarry Smith + comm - the MPI communicator
774a285bdaSBarry Smith - tokensize - size of the token arrays
784a285bdaSBarry Smith
794a285bdaSBarry Smith Output Parameters:
80811af0c4SBarry Smith + access_token - can be used with `PetscBoxUpload()` for this one session
8110450e9eSJacob Faibussowitsch - refresh_token - can be used for ever to obtain new access_tokens with `PetscBoxRefresh()`,
8210450e9eSJacob Faibussowitsch guard this like a password it gives access to your Box Drive
834a285bdaSBarry Smith
8420f4b53cSBarry Smith Level: intermediate
8520f4b53cSBarry Smith
8695452b02SPatrick Sanan Notes:
8720f4b53cSBarry Smith This call requires `stdout` and `stdin` access from process 0 on the MPI communicator
884a285bdaSBarry Smith
8910450e9eSJacob Faibussowitsch You can run src/sys/webclient/tutorials/boxobtainrefreshtoken to get a refresh token and then
9010450e9eSJacob Faibussowitsch in the future pass it to PETSc programs with `-box_refresh_token XXX`
914a285bdaSBarry Smith
9220f4b53cSBarry 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
9520f4b53cSBarry Smith .vb
9620f4b53cSBarry Smith saws/CA.pl -newcert (using the passphrase of password)
9720f4b53cSBarry Smith cat newkey.pem newcert.pem > sslclient.pem
9820f4b53cSBarry Smith .ve
9910450e9eSJacob Faibussowitsch and put the resulting file in either the current directory (with the application) or in the
10010450e9eSJacob Faibussowitsch home directory. This seems kind of silly but it was all I could figure out.
10168e69593SBarry Smith
102c30dda00SJacob Faibussowitsch .seealso: `PetscBoxRefresh()`, `PetscBoxUpload()`
1034a285bdaSBarry Smith @*/
PetscBoxAuthorize(MPI_Comm comm,char access_token[],char refresh_token[],size_t tokensize)104*ce78bad3SBarry Smith PetscErrorCode PetscBoxAuthorize(MPI_Comm comm, char access_token[], char refresh_token[], size_t tokensize) PeNS
105d71ae5a4SJacob Faibussowitsch {
1064a285bdaSBarry Smith SSL_CTX *ctx;
1074a285bdaSBarry Smith SSL *ssl;
1084a285bdaSBarry Smith int sock;
1095dc0f0a4SBarry Smith char buff[8 * 1024], body[1024];
1104a285bdaSBarry Smith PetscMPIInt rank;
1115dc0f0a4SBarry Smith PetscBool flg, found;
1124a285bdaSBarry Smith
1134a285bdaSBarry Smith PetscFunctionBegin;
1149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
115dd400576SPatrick Sanan if (rank == 0) {
116cc73adaaSBarry Smith PetscCheck(isatty(fileno(PETSC_STDOUT)), PETSC_COMM_SELF, PETSC_ERR_USER, "Requires users input/output");
117d0609cedSBarry Smith PetscCall(PetscPrintf(comm, "Cut and paste the following into your browser:\n\n"
1184a285bdaSBarry Smith "https://www.box.com/api/oauth2/authorize?"
1194a285bdaSBarry Smith "response_type=code&"
1209371c9d4SSatish Balay "client_id=" PETSC_BOX_CLIENT_ID "&state=PETScState"
121d0609cedSBarry Smith "\n\n"));
1229566063dSJacob Faibussowitsch PetscCall(PetscBoxStartWebServer_Private());
1239566063dSJacob Faibussowitsch PetscCall(PetscStrbeginswith((const char *)result, "state=PETScState&code=", &flg));
12428b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_LIB, "Did not get expected string from Box got %s", result);
1259566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(buff, (const char *)result + 22, sizeof(buff)));
1264a285bdaSBarry Smith
1279566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx));
1289566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("www.box.com", 443, ctx, &sock, &ssl));
129c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(body, "code=", sizeof(body)));
130c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, buff, sizeof(body)));
131c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&client_id=", sizeof(body)));
132c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, PETSC_BOX_CLIENT_ID, sizeof(body)));
133c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&client_secret=", sizeof(body)));
134c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, PETSC_BOX_CLIENT_ST, sizeof(body)));
135c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&grant_type=authorization_code", sizeof(body)));
1364a285bdaSBarry Smith
1379566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("POST", "www.box.com/api/oauth2/token", NULL, "application/x-www-form-urlencoded", body, ssl, buff, sizeof(buff)));
1389566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx));
1394a285bdaSBarry Smith close(sock);
1404a285bdaSBarry Smith
1419566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "access_token", access_token, tokensize, &found));
14228b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Box did not return access token");
1439566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "refresh_token", refresh_token, tokensize, &found));
14428b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Box did not return refresh token");
1454a285bdaSBarry Smith
1469566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Here is your Box refresh token, save it in a save place, in the future you can run PETSc\n"));
1479566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "programs with the option -box_refresh_token %s\n", refresh_token));
1489566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "to access Box Drive automatically\n"));
1494a285bdaSBarry Smith }
1503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1514a285bdaSBarry Smith }
152f044a08eSBarry Smith #endif
1534a285bdaSBarry Smith
1544a285bdaSBarry Smith /*@C
1554a285bdaSBarry Smith PetscBoxRefresh - Get a new authorization token for accessing Box drive from PETSc from a refresh token
1564a285bdaSBarry Smith
15720f4b53cSBarry Smith Not Collective, only the first process in the `MPI_Comm` does anything
1584a285bdaSBarry Smith
1594a285bdaSBarry Smith Input Parameters:
1604a285bdaSBarry Smith + comm - MPI communicator
161aec76313SJacob Faibussowitsch . refresh_token - obtained with `PetscBoxAuthorize()`, if `NULL` PETSc will first look for one in the options data
162811af0c4SBarry Smith if not found it will call `PetscBoxAuthorize()`
1634a285bdaSBarry Smith - tokensize - size of the output string access_token
1644a285bdaSBarry Smith
165d8d19677SJose E. Roman Output Parameters:
166811af0c4SBarry Smith + access_token - token that can be passed to `PetscBoxUpload()`
1674a285bdaSBarry 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
1684a285bdaSBarry Smith
1692b26979fSBarry Smith Level: intermediate
1702b26979fSBarry Smith
171c30dda00SJacob Faibussowitsch .seealso: `PetscBoxAuthorize()`, `PetscBoxUpload()`
1724a285bdaSBarry Smith @*/
PetscBoxRefresh(MPI_Comm comm,const char refresh_token[],char access_token[],char new_refresh_token[],size_t tokensize)173d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBoxRefresh(MPI_Comm comm, const char refresh_token[], char access_token[], char new_refresh_token[], size_t tokensize)
174d71ae5a4SJacob Faibussowitsch {
1754a285bdaSBarry Smith SSL_CTX *ctx;
1764a285bdaSBarry Smith SSL *ssl;
1774a285bdaSBarry Smith int sock;
1785dc0f0a4SBarry Smith char buff[8 * 1024], body[1024];
1794a285bdaSBarry Smith PetscMPIInt rank;
1805dc0f0a4SBarry Smith char *refreshtoken = (char *)refresh_token;
1815dc0f0a4SBarry Smith PetscBool found;
1824a285bdaSBarry Smith
1834a285bdaSBarry Smith PetscFunctionBegin;
1849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
185dd400576SPatrick Sanan if (rank == 0) {
1864a285bdaSBarry Smith if (!refresh_token) {
1874a285bdaSBarry Smith PetscBool set;
1889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(512, &refreshtoken));
1899566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-box_refresh_token", refreshtoken, sizeof(refreshtoken), &set));
19099374591SBarry Smith #if defined(PETSC_HAVE_SAWS)
1914a285bdaSBarry Smith if (!set) {
1929566063dSJacob Faibussowitsch PetscCall(PetscBoxAuthorize(comm, access_token, new_refresh_token, 512 * sizeof(char)));
1939566063dSJacob Faibussowitsch PetscCall(PetscFree(refreshtoken));
1943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1954a285bdaSBarry Smith }
19699374591SBarry Smith #else
19728b400f6SJacob Faibussowitsch PetscCheck(set, PETSC_COMM_SELF, PETSC_ERR_LIB, "Must provide refresh token with -box_refresh_token XXX");
19899374591SBarry Smith #endif
1994a285bdaSBarry Smith }
2009566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx));
2019566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("www.box.com", 443, ctx, &sock, &ssl));
202c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(body, "client_id=", sizeof(body)));
203c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, PETSC_BOX_CLIENT_ID, sizeof(body)));
204c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&client_secret=", sizeof(body)));
205c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, PETSC_BOX_CLIENT_ST, sizeof(body)));
206c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&refresh_token=", sizeof(body)));
207c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, refreshtoken, sizeof(body)));
2089566063dSJacob Faibussowitsch if (!refresh_token) PetscCall(PetscFree(refreshtoken));
209c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, "&grant_type=refresh_token", sizeof(body)));
2104a285bdaSBarry Smith
2119566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("POST", "www.box.com/api/oauth2/token", NULL, "application/x-www-form-urlencoded", body, ssl, buff, sizeof(buff)));
2129566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx));
2134a285bdaSBarry Smith close(sock);
2144a285bdaSBarry Smith
2159566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "access_token", access_token, tokensize, &found));
21628b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Box did not return access token");
2179566063dSJacob Faibussowitsch PetscCall(PetscPullJSONValue(buff, "refresh_token", new_refresh_token, tokensize, &found));
21828b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_LIB, "Box did not return refresh token");
21993e1d32fSBarry Smith
2209566063dSJacob 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"));
2219566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "programs with the option -box_refresh_token %s\n", new_refresh_token));
2229566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "to access Box Drive automatically\n"));
2234a285bdaSBarry Smith }
2243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2254a285bdaSBarry Smith }
2264a285bdaSBarry Smith
2274a285bdaSBarry Smith #include <sys/stat.h>
2284a285bdaSBarry Smith
2294a285bdaSBarry Smith /*@C
2304a285bdaSBarry Smith PetscBoxUpload - Loads a file to the Box Drive
2314a285bdaSBarry Smith
23293e1d32fSBarry Smith This routine has not yet been written; it is just copied from Google Drive
23393e1d32fSBarry Smith
234811af0c4SBarry Smith Not collective, only the first process in the `MPI_Comm` uploads the file
2354a285bdaSBarry Smith
2364a285bdaSBarry Smith Input Parameters:
2374a285bdaSBarry Smith + comm - MPI communicator
23820f4b53cSBarry Smith . access_token - obtained with `PetscBoxRefresh()`, pass `NULL` to have PETSc generate one
2394a285bdaSBarry Smith - filename - file to upload; if you upload multiple times it will have different names each time on Box Drive
2404a285bdaSBarry Smith
241811af0c4SBarry Smith Options Database Key:
24210699b91SBarry Smith . -box_refresh_token XXX - the token value
2434a285bdaSBarry Smith
24410450e9eSJacob Faibussowitsch Example Usage:
245811af0c4SBarry Smith .vb
2464a285bdaSBarry Smith With PETSc option -box_refresh_token XXX given
2474a285bdaSBarry Smith PetscBoxUpload(comm,NULL,filename); will upload file with no user interaction
2484a285bdaSBarry Smith
2494a285bdaSBarry Smith Without PETSc option -box_refresh_token XXX given
2504a285bdaSBarry Smith PetscBoxUpload(comm,NULL,filename); for first use will prompt user to authorize access to Box Drive with their processor
2514a285bdaSBarry Smith
2524a285bdaSBarry Smith With PETSc option -box_refresh_token XXX given
2534a285bdaSBarry Smith PetscBoxRefresh(comm,NULL,access_token,sizeof(access_token));
2544a285bdaSBarry Smith PetscBoxUpload(comm,access_token,filename);
2554a285bdaSBarry Smith
2564a285bdaSBarry Smith With refresh token entered in some way by the user
2574a285bdaSBarry Smith PetscBoxRefresh(comm,refresh_token,access_token,sizeof(access_token));
2584a285bdaSBarry Smith PetscBoxUpload(comm,access_token,filename);
2594a285bdaSBarry Smith
2604a285bdaSBarry Smith PetscBoxAuthorize(comm,access_token,refresh_token,sizeof(access_token));
2614a285bdaSBarry Smith PetscBoxUpload(comm,access_token,filename);
262811af0c4SBarry Smith .ve
2634a285bdaSBarry Smith
2642b26979fSBarry Smith Level: intermediate
2652b26979fSBarry Smith
266c30dda00SJacob Faibussowitsch .seealso: `PetscBoxAuthorize()`, `PetscBoxRefresh()`
2674a285bdaSBarry Smith @*/
PetscBoxUpload(MPI_Comm comm,const char access_token[],const char filename[])268d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBoxUpload(MPI_Comm comm, const char access_token[], const char filename[])
269d71ae5a4SJacob Faibussowitsch {
2704a285bdaSBarry Smith SSL_CTX *ctx;
2714a285bdaSBarry Smith SSL *ssl;
2724a285bdaSBarry Smith int sock;
2734a285bdaSBarry Smith char head[1024], buff[8 * 1024], *body, *title;
2744a285bdaSBarry Smith PetscMPIInt rank;
2754a285bdaSBarry Smith struct stat sb;
2764a285bdaSBarry Smith size_t len, blen, rd;
2774a285bdaSBarry Smith FILE *fd;
2782da392ccSBarry Smith int err;
2794a285bdaSBarry Smith
2804a285bdaSBarry Smith PetscFunctionBegin;
2819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
282dd400576SPatrick Sanan if (rank == 0) {
283c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(head, "Authorization: Bearer ", sizeof(head)));
284c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, access_token, sizeof(head)));
285c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, "\r\n", sizeof(head)));
286c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(head, "uploadType: multipart\r\n", sizeof(head)));
2874a285bdaSBarry Smith
2882da392ccSBarry Smith err = stat(filename, &sb);
28928b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to stat file: %s", filename);
2904a285bdaSBarry Smith len = 1024 + sb.st_size;
2919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len, &body));
292c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(body,
2934a285bdaSBarry Smith "--foo_bar_baz\r\n"
294c6a7a370SJeremy L Thompson "Content-Type: application/json\r\n\r\n"
295c6a7a370SJeremy L Thompson "{",
296c6a7a370SJeremy L Thompson len));
297c6a7a370SJeremy L Thompson PetscCall(PetscPushJSONValue(body, "title", filename, len));
298c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", len));
299c6a7a370SJeremy L Thompson PetscCall(PetscPushJSONValue(body, "mimeType", "text.html", len));
300c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body, ",", len));
301c6a7a370SJeremy L Thompson PetscCall(PetscPushJSONValue(body, "description", "a file", len));
302c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body,
303c6a7a370SJeremy L Thompson "}\r\n\r\n"
304c6a7a370SJeremy L Thompson "--foo_bar_baz\r\n"
305c6a7a370SJeremy L Thompson "Content-Type: text/html\r\n\r\n",
306c6a7a370SJeremy L Thompson len));
3079566063dSJacob Faibussowitsch PetscCall(PetscStrlen(body, &blen));
3084a285bdaSBarry Smith fd = fopen(filename, "r");
30928b400f6SJacob Faibussowitsch PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open file: %s", filename);
3104a285bdaSBarry Smith rd = fread(body + blen, sizeof(unsigned char), sb.st_size, fd);
311cc73adaaSBarry 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);
3124a285bdaSBarry Smith fclose(fd);
3134a285bdaSBarry Smith body[blen + rd] = 0;
314c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(body,
315c6a7a370SJeremy L Thompson "\r\n\r\n"
316c6a7a370SJeremy L Thompson "--foo_bar_baz\r\n",
317c6a7a370SJeremy L Thompson len));
3189566063dSJacob Faibussowitsch PetscCall(PetscSSLInitializeContext(&ctx));
3199566063dSJacob Faibussowitsch PetscCall(PetscHTTPSConnect("www.boxapis.com", 443, ctx, &sock, &ssl));
3209566063dSJacob Faibussowitsch PetscCall(PetscHTTPSRequest("POST", "www.boxapis.com/upload/drive/v2/files/", head, "multipart/related; boundary=\"foo_bar_baz\"", body, ssl, buff, sizeof(buff)));
3219566063dSJacob Faibussowitsch PetscCall(PetscFree(body));
3229566063dSJacob Faibussowitsch PetscCall(PetscSSLDestroyContext(ctx));
3234a285bdaSBarry Smith close(sock);
3249566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buff, "\"title\"", &title));
32528b400f6SJacob Faibussowitsch PetscCheck(title, PETSC_COMM_SELF, PETSC_ERR_LIB, "Upload of file %s failed", filename);
3264a285bdaSBarry Smith }
3273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3284a285bdaSBarry Smith }
329