xref: /petsc/src/sys/webclient/client.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
1b967cddfSBarry Smith 
20efc6a03SBarry Smith #include <petscwebclient.h>
3bb04b57dSBarry Smith #pragma clang diagnostic ignored "-Wdeprecated-declarations"
445e40e47SBarry Smith #pragma gcc diagnostic   ignored "-Wdeprecated-declarations"
5b967cddfSBarry Smith 
6b967cddfSBarry Smith static BIO *bio_err = NULL;
7b967cddfSBarry Smith 
8b967cddfSBarry Smith #define PASSWORD "password"
9b967cddfSBarry Smith 
104a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
119371c9d4SSatish Balay static int password_cb(char *buf, int num, int rwflag, void *userdata) {
12b967cddfSBarry Smith   if (num < strlen(PASSWORD) + 1) return (0);
13b967cddfSBarry Smith   strcpy(buf, PASSWORD);
14b967cddfSBarry Smith   return (strlen(PASSWORD));
15b967cddfSBarry Smith }
16b967cddfSBarry Smith #endif
17b967cddfSBarry Smith 
189371c9d4SSatish Balay static void sigpipe_handle(int x) { }
19b967cddfSBarry Smith 
204683183fSBarry Smith /*@C
21b967cddfSBarry Smith     PetscSSLInitializeContext - Set up an SSL context suitable for initiating HTTPS requests.
22b967cddfSBarry Smith 
234683183fSBarry Smith     Output Parameter:
24*811af0c4SBarry Smith .   octx - the SSL_CTX to be passed to `PetscHTTPSConnect90`
25b967cddfSBarry Smith 
264683183fSBarry Smith     Level: advanced
274683183fSBarry Smith 
284683183fSBarry Smith     If PETSc was ./configure -with-ssl-certificate requires the user have created a self-signed certificate with
2968e69593SBarry Smith $    saws/CA.pl  -newcert  (using the passphrase of password)
30b967cddfSBarry Smith $    cat newkey.pem newcert.pem > sslclient.pem
31b967cddfSBarry Smith 
32b967cddfSBarry Smith     and put the resulting file in either the current directory (with the application) or in the home directory. This seems kind of
33b967cddfSBarry Smith     silly but it was all I could figure out.
34b967cddfSBarry Smith 
35db781477SPatrick Sanan .seealso: `PetscSSLDestroyContext()`, `PetscHTTPSConnect()`, `PetscHTTPSRequest()`
364683183fSBarry Smith @*/
379371c9d4SSatish Balay PetscErrorCode PetscSSLInitializeContext(SSL_CTX **octx) {
38b967cddfSBarry Smith   SSL_CTX *ctx;
394a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
40b967cddfSBarry Smith   char      keyfile[PETSC_MAX_PATH_LEN];
41b967cddfSBarry Smith   PetscBool exists;
42b967cddfSBarry Smith #endif
43b967cddfSBarry Smith 
44b967cddfSBarry Smith   PetscFunctionBegin;
45b967cddfSBarry Smith   if (!bio_err) {
46b967cddfSBarry Smith     SSL_library_init();
47b967cddfSBarry Smith     SSL_load_error_strings();
48b967cddfSBarry Smith     bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
49b967cddfSBarry Smith   }
50b967cddfSBarry Smith 
51b967cddfSBarry Smith   /* Set up a SIGPIPE handler */
52b967cddfSBarry Smith   signal(SIGPIPE, sigpipe_handle);
53b967cddfSBarry Smith 
54ecd1d7b8SBarry Smith /* suggested at https://mta.openssl.org/pipermail/openssl-dev/2015-May/001449.html */
55ecd1d7b8SBarry Smith #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
56ecd1d7b8SBarry Smith   ctx = SSL_CTX_new(TLS_client_method());
57ecd1d7b8SBarry Smith #else
58ecd1d7b8SBarry Smith   ctx = SSL_CTX_new(SSLv23_client_method());
59ecd1d7b8SBarry Smith #endif
605dc0f0a4SBarry Smith   SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
61b967cddfSBarry Smith 
624a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
63b967cddfSBarry Smith   /* Locate keyfile */
649566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(keyfile, "sslclient.pem"));
659566063dSJacob Faibussowitsch   PetscCall(PetscTestFile(keyfile, 'r', &exists));
66b967cddfSBarry Smith   if (!exists) {
679566063dSJacob Faibussowitsch     PetscCall(PetscGetHomeDirectory(keyfile, PETSC_MAX_PATH_LEN));
689566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(keyfile, "/"));
699566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(keyfile, "sslclient.pem"));
709566063dSJacob Faibussowitsch     PetscCall(PetscTestFile(keyfile, 'r', &exists));
7128b400f6SJacob Faibussowitsch     PetscCheck(exists, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate sslclient.pem file in current directory or home directory");
72b967cddfSBarry Smith   }
73b967cddfSBarry Smith 
74b967cddfSBarry Smith   /* Load our keys and certificates*/
75cc73adaaSBarry Smith   PetscCheck(SSL_CTX_use_certificate_chain_file(ctx, keyfile), PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot read certificate file");
76b967cddfSBarry Smith 
77b967cddfSBarry Smith   SSL_CTX_set_default_passwd_cb(ctx, password_cb);
78cc73adaaSBarry Smith   PetscCheck(SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM), PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot read key file");
79b967cddfSBarry Smith #endif
80b967cddfSBarry Smith 
81b967cddfSBarry Smith   *octx = ctx;
82b967cddfSBarry Smith   PetscFunctionReturn(0);
83b967cddfSBarry Smith }
84b967cddfSBarry Smith 
854683183fSBarry Smith /*@C
86*811af0c4SBarry Smith      PetscSSLDestroyContext - frees a `SSL_CTX` obtained with `PetscSSLInitializeContext()`
874683183fSBarry Smith 
884683183fSBarry Smith      Input Parameter:
89*811af0c4SBarry Smith .     ctx - the `SSL_CTX`
904683183fSBarry Smith 
914683183fSBarry Smith     Level: advanced
924683183fSBarry Smith 
93db781477SPatrick Sanan .seealso: `PetscSSLInitializeContext()`, `PetscHTTPSConnect()`
944683183fSBarry Smith @*/
959371c9d4SSatish Balay PetscErrorCode PetscSSLDestroyContext(SSL_CTX *ctx) {
96b967cddfSBarry Smith   PetscFunctionBegin;
97b967cddfSBarry Smith   SSL_CTX_free(ctx);
98b967cddfSBarry Smith   PetscFunctionReturn(0);
99b967cddfSBarry Smith }
100b967cddfSBarry Smith 
1019371c9d4SSatish Balay static PetscErrorCode PetscHTTPBuildRequest(const char type[], const char url[], const char header[], const char ctype[], const char body[], char **outrequest) {
102b967cddfSBarry Smith   char     *request = 0;
10393e1d32fSBarry Smith   char      contentlength[40], contenttype[80], *path, *host;
1047a3410edSBarry Smith   size_t    request_len, headlen, bodylen, contentlen, pathlen, hostlen, typelen, contenttypelen = 0;
105b967cddfSBarry Smith   PetscBool flg;
106b967cddfSBarry Smith 
107b967cddfSBarry Smith   PetscFunctionBegin;
1089566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(url, &host));
1099566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(host, '/', &path));
11028b400f6SJacob Faibussowitsch   PetscCheck(path, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "url must contain / it is %s", url);
111c245270aSBarry Smith   *path = 0;
1129566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(host, &hostlen));
11393e1d32fSBarry Smith 
1149566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(url, '/', &path));
1159566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(path, &pathlen));
11693e1d32fSBarry Smith 
117b967cddfSBarry Smith   if (header) {
1189566063dSJacob Faibussowitsch     PetscCall(PetscStrendswith(header, "\r\n", &flg));
119d8174014SToby Isaac     PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "header must end with \\r\\n");
120b967cddfSBarry Smith   }
121b967cddfSBarry Smith 
1229566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(type, &typelen));
123b967cddfSBarry Smith   if (ctype) {
1249566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(contenttype, 80, "Content-Type: %s\r\n", ctype));
1259566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(contenttype, &contenttypelen));
126b967cddfSBarry Smith   }
1279566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(header, &headlen));
1289566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(body, &bodylen));
1299566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(contentlength, 40, "Content-Length: %d\r\n\r\n", (int)bodylen));
1309566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(contentlength, &contentlen));
131b967cddfSBarry Smith 
132b967cddfSBarry Smith   /* Now construct our HTTP request */
13393e1d32fSBarry Smith   request_len = typelen + 1 + pathlen + hostlen + 100 + headlen + contenttypelen + contentlen + bodylen + 1;
1349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(request_len, &request));
1359566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(request, type));
1369566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(request, " "));
1379566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(request, path));
1389566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(request, " HTTP/1.1\r\nHost: "));
1399566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(request, host));
1409566063dSJacob Faibussowitsch   PetscCall(PetscFree(host));
1419566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(request, "\r\nUser-Agent:PETScClient\r\n"));
1429566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(request, header));
1431baa6e33SBarry Smith   if (ctype) PetscCall(PetscStrcat(request, contenttype));
1449566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(request, contentlength));
1459566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(request, body));
1469566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(request, &request_len));
1479566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "HTTPS request follows: \n%s\n", request));
148b967cddfSBarry Smith 
14904102261SBarry Smith   *outrequest = request;
15004102261SBarry Smith   PetscFunctionReturn(0);
15104102261SBarry Smith }
15204102261SBarry Smith 
1534683183fSBarry Smith /*@C
15404102261SBarry Smith      PetscHTTPSRequest - Send a request to an HTTPS server
15504102261SBarry Smith 
15604102261SBarry Smith    Input Parameters:
15704102261SBarry Smith +   type - either "POST" or "GET"
15804102261SBarry Smith .   url -  URL of request host/path
15904102261SBarry Smith .   header - additional header information, may be NULL
16004102261SBarry Smith .   ctype - data type of body, for example application/json
16104102261SBarry Smith .   body - data to send to server
162*811af0c4SBarry Smith .   ssl - obtained with `PetscHTTPSConnect()`
16304102261SBarry Smith -   buffsize - size of buffer
16404102261SBarry Smith 
16504102261SBarry Smith    Output Parameter:
16604102261SBarry Smith .   buff - everything returned from server
1674683183fSBarry Smith 
1684683183fSBarry Smith     Level: advanced
1694683183fSBarry Smith 
170db781477SPatrick Sanan .seealso: `PetscHTTPRequest()`, `PetscHTTPSConnect()`, `PetscSSLInitializeContext()`, `PetscSSLDestroyContext()`, `PetscPullJSONValue()`
1714683183fSBarry Smith @*/
1729371c9d4SSatish Balay PetscErrorCode PetscHTTPSRequest(const char type[], const char url[], const char header[], const char ctype[], const char body[], SSL *ssl, char buff[], size_t buffsize) {
17304102261SBarry Smith   char     *request;
17404102261SBarry Smith   int       r;
17504102261SBarry Smith   size_t    request_len, len;
1765dc0f0a4SBarry Smith   PetscBool foundbody = PETSC_FALSE;
17704102261SBarry Smith 
17804102261SBarry Smith   PetscFunctionBegin;
1799566063dSJacob Faibussowitsch   PetscCall(PetscHTTPBuildRequest(type, url, header, ctype, body, &request));
1809566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(request, &request_len));
18104102261SBarry Smith 
182d8dcb26dSBarry Smith   r = SSL_write(ssl, request, (int)request_len);
183b967cddfSBarry Smith   switch (SSL_get_error(ssl, r)) {
1849371c9d4SSatish Balay   case SSL_ERROR_NONE: PetscCheck(request_len == (size_t)r, PETSC_COMM_SELF, PETSC_ERR_LIB, "Incomplete write to SSL socket"); break;
1859371c9d4SSatish Balay   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "SSL socket write problem");
186b967cddfSBarry Smith   }
187b967cddfSBarry Smith 
1885dc0f0a4SBarry Smith   /* Now read the server's response, globus sends it in two chunks hence must read a second time if needed */
1899566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(buff, buffsize));
1905dc0f0a4SBarry Smith   len       = 0;
1915dc0f0a4SBarry Smith   foundbody = PETSC_FALSE;
1925dc0f0a4SBarry Smith   do {
1935dc0f0a4SBarry Smith     char  *clen;
1945dc0f0a4SBarry Smith     int    cl;
1955dc0f0a4SBarry Smith     size_t nlen;
1965dc0f0a4SBarry Smith 
1975dc0f0a4SBarry Smith     r = SSL_read(ssl, buff + len, (int)buffsize);
1985dc0f0a4SBarry Smith     len += r;
199b967cddfSBarry Smith     switch (SSL_get_error(ssl, r)) {
2009371c9d4SSatish Balay     case SSL_ERROR_NONE: break;
201b967cddfSBarry Smith     case SSL_ERROR_ZERO_RETURN:
2025dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
2035dc0f0a4SBarry Smith       SSL_shutdown(ssl);
204b967cddfSBarry Smith       break;
2059371c9d4SSatish Balay     case SSL_ERROR_SYSCALL: foundbody = PETSC_TRUE; break;
2069371c9d4SSatish Balay     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "SSL read problem");
207b967cddfSBarry Smith     }
2085dc0f0a4SBarry Smith 
2099566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(buff, "Content-Length: ", &clen));
2105dc0f0a4SBarry Smith     if (clen) {
2115dc0f0a4SBarry Smith       clen += 15;
2125dc0f0a4SBarry Smith       sscanf(clen, "%d", &cl);
2135dc0f0a4SBarry Smith       if (!cl) foundbody = PETSC_TRUE;
2145dc0f0a4SBarry Smith       else {
2159566063dSJacob Faibussowitsch         PetscCall(PetscStrstr(buff, "\r\n\r\n", &clen));
2165dc0f0a4SBarry Smith         if (clen) {
2179566063dSJacob Faibussowitsch           PetscCall(PetscStrlen(clen, &nlen));
2185dc0f0a4SBarry Smith           if (nlen - 4 == (size_t)cl) foundbody = PETSC_TRUE;
2195dc0f0a4SBarry Smith         }
2205dc0f0a4SBarry Smith       }
2215dc0f0a4SBarry Smith     } else {
2225dc0f0a4SBarry Smith       /* if no content length than must leave because you don't know if you can read again */
2235dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
2245dc0f0a4SBarry Smith     }
2255dc0f0a4SBarry Smith   } while (!foundbody);
2269566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "HTTPS result follows: \n%s\n", buff));
227b967cddfSBarry Smith 
228b967cddfSBarry Smith   SSL_free(ssl);
2299566063dSJacob Faibussowitsch   PetscCall(PetscFree(request));
230b967cddfSBarry Smith   PetscFunctionReturn(0);
231b967cddfSBarry Smith }
232b967cddfSBarry Smith 
2334683183fSBarry Smith /*@C
23404102261SBarry Smith      PetscHTTPRequest - Send a request to an HTTP server
23504102261SBarry Smith 
23604102261SBarry Smith    Input Parameters:
23704102261SBarry Smith +   type - either "POST" or "GET"
23804102261SBarry Smith .   url -  URL of request host/path
23904102261SBarry Smith .   header - additional header information, may be NULL
24004102261SBarry Smith .   ctype - data type of body, for example application/json
24104102261SBarry Smith .   body - data to send to server
242*811af0c4SBarry Smith .   sock - obtained with `PetscOpenSocket()`
24304102261SBarry Smith -   buffsize - size of buffer
24404102261SBarry Smith 
24504102261SBarry Smith    Output Parameter:
24604102261SBarry Smith .   buff - everything returned from server
2474683183fSBarry Smith 
2484683183fSBarry Smith     Level: advanced
2494683183fSBarry Smith 
250db781477SPatrick Sanan .seealso: `PetscHTTPSRequest()`, `PetscOpenSocket()`, `PetscHTTPSConnect()`, `PetscPullJSONValue()`
2514683183fSBarry Smith @*/
2529371c9d4SSatish Balay PetscErrorCode PetscHTTPRequest(const char type[], const char url[], const char header[], const char ctype[], const char body[], int sock, char buff[], size_t buffsize) {
25304102261SBarry Smith   char  *request;
25404102261SBarry Smith   size_t request_len;
25504102261SBarry Smith 
25604102261SBarry Smith   PetscFunctionBegin;
2579566063dSJacob Faibussowitsch   PetscCall(PetscHTTPBuildRequest(type, url, header, ctype, body, &request));
2589566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(request, &request_len));
25904102261SBarry Smith 
2609566063dSJacob Faibussowitsch   PetscCall(PetscBinaryWrite(sock, request, request_len, PETSC_CHAR));
2619566063dSJacob Faibussowitsch   PetscCall(PetscFree(request));
2629860990eSLisandro Dalcin   PetscBinaryRead(sock, buff, buffsize, NULL, PETSC_CHAR);
26304102261SBarry Smith   buff[buffsize - 1] = 0;
2649566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "HTTP result follows: \n%s\n", buff));
26504102261SBarry Smith   PetscFunctionReturn(0);
26604102261SBarry Smith }
26704102261SBarry Smith 
2684683183fSBarry Smith /*@C
2694683183fSBarry Smith       PetscHTTPSConnect - connect to a HTTPS server
2704683183fSBarry Smith 
2714683183fSBarry Smith     Input Parameters:
2724683183fSBarry Smith +    host - the name of the machine hosting the HTTPS server
2734683183fSBarry Smith .    port - the port number where the server is hosting, usually 443
274*811af0c4SBarry Smith -    ctx - value obtained with `PetscSSLInitializeContext()`
2754683183fSBarry Smith 
2764683183fSBarry Smith     Output Parameters:
2774683183fSBarry Smith +    sock - socket to connect
278*811af0c4SBarry Smith -    ssl - the argument passed to `PetscHTTPSRequest()`
2794683183fSBarry Smith 
2804683183fSBarry Smith     Level: advanced
2814683183fSBarry Smith 
282db781477SPatrick Sanan .seealso: `PetscOpenSocket()`, `PetscHTTPSRequest()`, `PetscSSLInitializeContext()`
2834683183fSBarry Smith @*/
2849371c9d4SSatish Balay PetscErrorCode PetscHTTPSConnect(const char host[], int port, SSL_CTX *ctx, int *sock, SSL **ssl) {
285b967cddfSBarry Smith   BIO *sbio;
286b967cddfSBarry Smith 
287b967cddfSBarry Smith   PetscFunctionBegin;
288b967cddfSBarry Smith   /* Connect the TCP socket*/
2899566063dSJacob Faibussowitsch   PetscCall(PetscOpenSocket(host, port, sock));
290b967cddfSBarry Smith 
291b967cddfSBarry Smith   /* Connect the SSL socket */
292b967cddfSBarry Smith   *ssl = SSL_new(ctx);
293b967cddfSBarry Smith   sbio = BIO_new_socket(*sock, BIO_NOCLOSE);
294b967cddfSBarry Smith   SSL_set_bio(*ssl, sbio, sbio);
29508401ef6SPierre Jolivet   PetscCheck(SSL_connect(*ssl) > 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "SSL connect error");
296b967cddfSBarry Smith   PetscFunctionReturn(0);
297b967cddfSBarry Smith }
298b967cddfSBarry Smith 
2994683183fSBarry Smith /*@C
3004683183fSBarry Smith      PetscPullJSONValue - Given a JSON response containing the substring with "key" : "value"  where there may or not be spaces around the : returns the value.
3014683183fSBarry Smith 
3024683183fSBarry Smith     Input Parameters:
3034683183fSBarry Smith +    buff - the char array containing the possible values
3044683183fSBarry Smith .    key - the key of the requested value
3054683183fSBarry Smith -    valuelen - the length of the array to contain the value associated with the key
3064683183fSBarry Smith 
3074683183fSBarry Smith     Output Parameters:
3084683183fSBarry Smith +    value - the value obtained
3094683183fSBarry Smith -    found - flag indicating if the value was found in the buff
3104683183fSBarry Smith 
3114683183fSBarry Smith     Level: advanced
3124683183fSBarry Smith 
313*811af0c4SBarry Smith .seealso: `PetscOpenSocket()`, `PetscHTTPSRequest()`, `PetscSSLInitializeContext()`, `PetscPushJSONValue()`
3144683183fSBarry Smith @*/
3159371c9d4SSatish Balay PetscErrorCode PetscPullJSONValue(const char buff[], const char key[], char value[], size_t valuelen, PetscBool *found) {
31668e69593SBarry Smith   char  *v, *w;
31768e69593SBarry Smith   char   work[256];
31868e69593SBarry Smith   size_t len;
31968e69593SBarry Smith 
32068e69593SBarry Smith   PetscFunctionBegin;
3219566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(work, "\""));
3229566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(work, key, sizeof(work)));
3239566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(work, "\":"));
3249566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(buff, work, &v));
3259566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(work, &len));
32668e69593SBarry Smith   if (v) {
32768e69593SBarry Smith     v += len;
32868e69593SBarry Smith   } else {
32968e69593SBarry Smith     work[len++ - 1] = 0;
3309566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(work, " :"));
3319566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(buff, work, &v));
33268e69593SBarry Smith     if (!v) {
33368e69593SBarry Smith       *found = PETSC_FALSE;
33468e69593SBarry Smith       PetscFunctionReturn(0);
33568e69593SBarry Smith     }
33668e69593SBarry Smith     v += len;
33768e69593SBarry Smith   }
3389566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(v, '\"', &v));
33968e69593SBarry Smith   if (!v) {
34068e69593SBarry Smith     *found = PETSC_FALSE;
34168e69593SBarry Smith     PetscFunctionReturn(0);
34268e69593SBarry Smith   }
3439566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(v + 1, '\"', &w));
34468e69593SBarry Smith   if (!w) {
34568e69593SBarry Smith     *found = PETSC_FALSE;
34668e69593SBarry Smith     PetscFunctionReturn(0);
34768e69593SBarry Smith   }
34868e69593SBarry Smith   *found = PETSC_TRUE;
3499566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(value, v + 1, PetscMin((size_t)(w - v), valuelen)));
35068e69593SBarry Smith   PetscFunctionReturn(0);
35168e69593SBarry Smith }
3525dc0f0a4SBarry Smith 
3535dc0f0a4SBarry Smith #include <ctype.h>
3545dc0f0a4SBarry Smith 
3554683183fSBarry Smith /*@C
3564683183fSBarry Smith     PetscPushJSONValue -  Puts a "key" : "value" pair onto a string
3575dc0f0a4SBarry Smith 
3584683183fSBarry Smith     Input Parameters:
3594683183fSBarry Smith +   buffer - the char array where the value will be put
3604683183fSBarry Smith .   key - the key value to be set
3614683183fSBarry Smith .   value - the value associated with the key
3624683183fSBarry Smith -   bufflen - the size of the buffer (currently ignored)
3634683183fSBarry Smith 
3644683183fSBarry Smith     Level: advanced
3654683183fSBarry Smith 
366*811af0c4SBarry Smith     Note:
36795452b02SPatrick Sanan     Ignores lengths so can cause buffer overflow
368*811af0c4SBarry Smith 
369*811af0c4SBarry Smith .seealso: `PetscOpenSocket()`, `PetscHTTPSRequest()`, `PetscSSLInitializeContext()`, `PetscPullJSONValue()`
3704683183fSBarry Smith @*/
3719371c9d4SSatish Balay PetscErrorCode PetscPushJSONValue(char buff[], const char key[], const char value[], size_t bufflen) {
3725dc0f0a4SBarry Smith   size_t    len;
3735dc0f0a4SBarry Smith   PetscBool special;
3745dc0f0a4SBarry Smith 
3755dc0f0a4SBarry Smith   PetscFunctionBegin;
3769566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(value, "null", &special));
37748a46eb9SPierre Jolivet   if (!special) PetscCall(PetscStrcmp(value, "true", &special));
37848a46eb9SPierre Jolivet   if (!special) PetscCall(PetscStrcmp(value, "false", &special));
3795dc0f0a4SBarry Smith   if (!special) {
3805dc0f0a4SBarry Smith     PetscInt i;
3815dc0f0a4SBarry Smith 
3829566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(value, &len));
3835dc0f0a4SBarry Smith     special = PETSC_TRUE;
3845dc0f0a4SBarry Smith     for (i = 0; i < (int)len; i++) {
3855dc0f0a4SBarry Smith       if (!isdigit(value[i])) {
3865dc0f0a4SBarry Smith         special = PETSC_FALSE;
3875dc0f0a4SBarry Smith         break;
3885dc0f0a4SBarry Smith       }
3895dc0f0a4SBarry Smith     }
3905dc0f0a4SBarry Smith   }
3915dc0f0a4SBarry Smith 
3929566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(buff, "\""));
3939566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(buff, key));
3949566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(buff, "\":"));
39548a46eb9SPierre Jolivet   if (!special) PetscCall(PetscStrcat(buff, "\""));
3969566063dSJacob Faibussowitsch   PetscCall(PetscStrcat(buff, value));
39748a46eb9SPierre Jolivet   if (!special) PetscCall(PetscStrcat(buff, "\""));
3985dc0f0a4SBarry Smith   PetscFunctionReturn(0);
3995dc0f0a4SBarry Smith }
400