xref: /petsc/src/sys/webclient/client.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
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)
11b967cddfSBarry Smith static int password_cb(char *buf,int num, int rwflag,void *userdata)
12b967cddfSBarry Smith {
13b967cddfSBarry Smith   if (num < strlen(PASSWORD)+1) return(0);
14b967cddfSBarry Smith   strcpy(buf,PASSWORD);
15b967cddfSBarry Smith   return(strlen(PASSWORD));
16b967cddfSBarry Smith }
17b967cddfSBarry Smith #endif
18b967cddfSBarry Smith 
19b967cddfSBarry Smith static void sigpipe_handle(int x)
20b967cddfSBarry Smith {
21b967cddfSBarry Smith }
22b967cddfSBarry Smith 
234683183fSBarry Smith /*@C
24b967cddfSBarry Smith     PetscSSLInitializeContext - Set up an SSL context suitable for initiating HTTPS requests.
25b967cddfSBarry Smith 
264683183fSBarry Smith     Output Parameter:
274683183fSBarry Smith .   octx - the SSL_CTX to be passed to PetscHTTPSConnect
28b967cddfSBarry Smith 
294683183fSBarry Smith     Level: advanced
304683183fSBarry Smith 
314683183fSBarry Smith     If PETSc was ./configure -with-ssl-certificate requires the user have created a self-signed certificate with
3268e69593SBarry Smith $    saws/CA.pl  -newcert  (using the passphrase of password)
33b967cddfSBarry Smith $    cat newkey.pem newcert.pem > sslclient.pem
34b967cddfSBarry Smith 
35b967cddfSBarry Smith     and put the resulting file in either the current directory (with the application) or in the home directory. This seems kind of
36b967cddfSBarry Smith     silly but it was all I could figure out.
37b967cddfSBarry Smith 
384683183fSBarry Smith .seealso: PetscSSLDestroyContext(), PetscHTTPSConnect(), PetscHTTPSRequest()
394683183fSBarry Smith 
404683183fSBarry Smith @*/
41b967cddfSBarry Smith PetscErrorCode PetscSSLInitializeContext(SSL_CTX **octx)
42b967cddfSBarry Smith {
43b967cddfSBarry Smith     SSL_CTX        *ctx;
444a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
45b967cddfSBarry Smith     char           keyfile[PETSC_MAX_PATH_LEN];
46b967cddfSBarry Smith     PetscBool      exists;
47b967cddfSBarry Smith     PetscErrorCode ierr;
48b967cddfSBarry Smith #endif
49b967cddfSBarry Smith 
50b967cddfSBarry Smith     PetscFunctionBegin;
51b967cddfSBarry Smith     if (!bio_err) {
52b967cddfSBarry Smith       SSL_library_init();
53b967cddfSBarry Smith       SSL_load_error_strings();
54b967cddfSBarry Smith       bio_err = BIO_new_fp(stderr,BIO_NOCLOSE);
55b967cddfSBarry Smith     }
56b967cddfSBarry Smith 
57b967cddfSBarry Smith     /* Set up a SIGPIPE handler */
58b967cddfSBarry Smith     signal(SIGPIPE,sigpipe_handle);
59b967cddfSBarry Smith 
60ecd1d7b8SBarry Smith /* suggested at https://mta.openssl.org/pipermail/openssl-dev/2015-May/001449.html */
61ecd1d7b8SBarry Smith #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
62ecd1d7b8SBarry Smith     ctx  = SSL_CTX_new(TLS_client_method());
63ecd1d7b8SBarry Smith #else
64ecd1d7b8SBarry Smith     ctx  = SSL_CTX_new(SSLv23_client_method());
65ecd1d7b8SBarry Smith #endif
665dc0f0a4SBarry Smith     SSL_CTX_set_mode(ctx,SSL_MODE_AUTO_RETRY);
67b967cddfSBarry Smith 
684a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
69b967cddfSBarry Smith     /* Locate keyfile */
70b967cddfSBarry Smith     ierr = PetscStrcpy(keyfile,"sslclient.pem");CHKERRQ(ierr);
71b967cddfSBarry Smith     ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr);
72b967cddfSBarry Smith     if (!exists) {
73b967cddfSBarry Smith       ierr = PetscGetHomeDirectory(keyfile,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
74b967cddfSBarry Smith       ierr = PetscStrcat(keyfile,"/");CHKERRQ(ierr);
75b967cddfSBarry Smith       ierr = PetscStrcat(keyfile,"sslclient.pem");CHKERRQ(ierr);
76b967cddfSBarry Smith       ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr);
77*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!exists,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate sslclient.pem file in current directory or home directory");
78b967cddfSBarry Smith     }
79b967cddfSBarry Smith 
80b967cddfSBarry Smith     /* Load our keys and certificates*/
81*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!(SSL_CTX_use_certificate_chain_file(ctx,keyfile)),PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read certificate file");
82b967cddfSBarry Smith 
83b967cddfSBarry Smith     SSL_CTX_set_default_passwd_cb(ctx,password_cb);
84*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!(SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM)),PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read key file");
85b967cddfSBarry Smith #endif
86b967cddfSBarry Smith 
87b967cddfSBarry Smith     *octx = ctx;
88b967cddfSBarry Smith     PetscFunctionReturn(0);
89b967cddfSBarry Smith }
90b967cddfSBarry Smith 
914683183fSBarry Smith /*@C
924683183fSBarry Smith      PetscSSLDestroyContext - frees a SSL_CTX obtained with PetscSSLInitializeContext()
934683183fSBarry Smith 
944683183fSBarry Smith      Input Parameter:
954683183fSBarry Smith .     ctx - the SSL_CTX
964683183fSBarry Smith 
974683183fSBarry Smith     Level: advanced
984683183fSBarry Smith 
994683183fSBarry Smith .seealso: PetscSSLInitializeContext(), PetscHTTPSConnect()
1004683183fSBarry Smith @*/
101b967cddfSBarry Smith PetscErrorCode PetscSSLDestroyContext(SSL_CTX *ctx)
102b967cddfSBarry Smith {
103b967cddfSBarry Smith   PetscFunctionBegin;
104b967cddfSBarry Smith   SSL_CTX_free(ctx);
105b967cddfSBarry Smith   PetscFunctionReturn(0);
106b967cddfSBarry Smith }
107b967cddfSBarry Smith 
1084683183fSBarry Smith static PetscErrorCode PetscHTTPBuildRequest(const char type[],const char url[],const char header[],const char ctype[],const char body[],char **outrequest)
109b967cddfSBarry Smith {
110b967cddfSBarry Smith   char           *request=0;
11193e1d32fSBarry Smith   char           contentlength[40],contenttype[80],*path,*host;
1127a3410edSBarry Smith   size_t         request_len,headlen,bodylen,contentlen,pathlen,hostlen,typelen,contenttypelen = 0;
113b967cddfSBarry Smith   PetscErrorCode ierr;
114b967cddfSBarry Smith   PetscBool      flg;
115b967cddfSBarry Smith 
116b967cddfSBarry Smith   PetscFunctionBegin;
11793e1d32fSBarry Smith   ierr = PetscStrallocpy(url,&host);CHKERRQ(ierr);
11893e1d32fSBarry Smith   ierr = PetscStrchr(host,'/',&path);CHKERRQ(ierr);
119*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!path,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"url must contain / it is %s",url);
120c245270aSBarry Smith   *path = 0;
12193e1d32fSBarry Smith   ierr  = PetscStrlen(host,&hostlen);CHKERRQ(ierr);
12293e1d32fSBarry Smith 
12393e1d32fSBarry Smith   ierr = PetscStrchr(url,'/',&path);CHKERRQ(ierr);
12493e1d32fSBarry Smith   ierr = PetscStrlen(path,&pathlen);CHKERRQ(ierr);
12593e1d32fSBarry Smith 
126b967cddfSBarry Smith   if (header) {
127b967cddfSBarry Smith     ierr = PetscStrendswith(header,"\r\n",&flg);CHKERRQ(ierr);
128*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"header must end with \\r\");
129b967cddfSBarry Smith   }
130b967cddfSBarry Smith 
131b967cddfSBarry Smith   ierr = PetscStrlen(type,&typelen);CHKERRQ(ierr);
132b967cddfSBarry Smith   if (ctype) {
133b967cddfSBarry Smith     ierr = PetscSNPrintf(contenttype,80,"Content-Type: %s\r\n",ctype);CHKERRQ(ierr);
134b967cddfSBarry Smith     ierr = PetscStrlen(contenttype,&contenttypelen);CHKERRQ(ierr);
135b967cddfSBarry Smith   }
136b967cddfSBarry Smith   ierr = PetscStrlen(header,&headlen);CHKERRQ(ierr);
137b967cddfSBarry Smith   ierr = PetscStrlen(body,&bodylen);CHKERRQ(ierr);
138b967cddfSBarry Smith   ierr = PetscSNPrintf(contentlength,40,"Content-Length: %d\r\n\r\n",(int)bodylen);CHKERRQ(ierr);
139b967cddfSBarry Smith   ierr = PetscStrlen(contentlength,&contentlen);CHKERRQ(ierr);
140b967cddfSBarry Smith 
141b967cddfSBarry Smith   /* Now construct our HTTP request */
14293e1d32fSBarry Smith   request_len = typelen + 1 + pathlen + hostlen + 100 + headlen + contenttypelen + contentlen + bodylen + 1;
143fe278a28SBarry Smith   ierr = PetscMalloc1(request_len,&request);CHKERRQ(ierr);
144b967cddfSBarry Smith   ierr = PetscStrcpy(request,type);CHKERRQ(ierr);
145b967cddfSBarry Smith   ierr = PetscStrcat(request," ");CHKERRQ(ierr);
14693e1d32fSBarry Smith   ierr = PetscStrcat(request,path);CHKERRQ(ierr);
14793e1d32fSBarry Smith   ierr = PetscStrcat(request," HTTP/1.1\r\nHost: ");CHKERRQ(ierr);
14893e1d32fSBarry Smith   ierr = PetscStrcat(request,host);CHKERRQ(ierr);
14993e1d32fSBarry Smith   ierr = PetscFree(host);CHKERRQ(ierr);
15093e1d32fSBarry Smith   ierr = PetscStrcat(request,"\r\nUser-Agent:PETScClient\r\n");CHKERRQ(ierr);
151b967cddfSBarry Smith   ierr = PetscStrcat(request,header);CHKERRQ(ierr);
152b967cddfSBarry Smith   if (ctype) {
153b967cddfSBarry Smith     ierr = PetscStrcat(request,contenttype);CHKERRQ(ierr);
154b967cddfSBarry Smith   }
155b967cddfSBarry Smith   ierr = PetscStrcat(request,contentlength);CHKERRQ(ierr);
156b967cddfSBarry Smith   ierr = PetscStrcat(request,body);CHKERRQ(ierr);
157b967cddfSBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
1587d3de750SJacob Faibussowitsch   ierr = PetscInfo(NULL,"HTTPS request follows: \n%s\n",request);CHKERRQ(ierr);
159b967cddfSBarry Smith 
16004102261SBarry Smith   *outrequest = request;
16104102261SBarry Smith   PetscFunctionReturn(0);
16204102261SBarry Smith }
16304102261SBarry Smith 
1644683183fSBarry Smith /*@C
16504102261SBarry Smith      PetscHTTPSRequest - Send a request to an HTTPS server
16604102261SBarry Smith 
16704102261SBarry Smith    Input Parameters:
16804102261SBarry Smith +   type - either "POST" or "GET"
16904102261SBarry Smith .   url -  URL of request host/path
17004102261SBarry Smith .   header - additional header information, may be NULL
17104102261SBarry Smith .   ctype - data type of body, for example application/json
17204102261SBarry Smith .   body - data to send to server
17304102261SBarry Smith .   ssl - obtained with PetscHTTPSConnect()
17404102261SBarry Smith -   buffsize - size of buffer
17504102261SBarry Smith 
17604102261SBarry Smith    Output Parameter:
17704102261SBarry Smith .   buff - everything returned from server
1784683183fSBarry Smith 
1794683183fSBarry Smith     Level: advanced
1804683183fSBarry Smith 
1814683183fSBarry Smith .seealso: PetscHTTPRequest(), PetscHTTPSConnect(), PetscSSLInitializeContext(), PetscSSLDestroyContext(), PetscPullJSONValue()
1824683183fSBarry Smith 
1834683183fSBarry Smith @*/
18404102261SBarry Smith PetscErrorCode PetscHTTPSRequest(const char type[],const char url[],const char header[],const char ctype[],const char body[],SSL *ssl,char buff[],size_t buffsize)
18504102261SBarry Smith {
18604102261SBarry Smith   char           *request;
18704102261SBarry Smith   int            r;
18804102261SBarry Smith   size_t         request_len,len;
18904102261SBarry Smith   PetscErrorCode ierr;
1905dc0f0a4SBarry Smith   PetscBool      foundbody = PETSC_FALSE;
19104102261SBarry Smith 
19204102261SBarry Smith   PetscFunctionBegin;
19304102261SBarry Smith   ierr = PetscHTTPBuildRequest(type,url,header,ctype,body,&request);CHKERRQ(ierr);
19404102261SBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
19504102261SBarry Smith 
196d8dcb26dSBarry Smith   r = SSL_write(ssl,request,(int)request_len);
197b967cddfSBarry Smith   switch (SSL_get_error(ssl,r)) {
198b967cddfSBarry Smith     case SSL_ERROR_NONE:
199*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(request_len != (size_t)r,PETSC_COMM_SELF,PETSC_ERR_LIB,"Incomplete write to SSL socket");
200b967cddfSBarry Smith       break;
201b967cddfSBarry Smith     default:
202b967cddfSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL socket write problem");
203b967cddfSBarry Smith   }
204b967cddfSBarry Smith 
2055dc0f0a4SBarry Smith   /* Now read the server's response, globus sends it in two chunks hence must read a second time if needed */
206580bdb30SBarry Smith   ierr      = PetscArrayzero(buff,buffsize);CHKERRQ(ierr);
2075dc0f0a4SBarry Smith   len       = 0;
2085dc0f0a4SBarry Smith   foundbody = PETSC_FALSE;
2095dc0f0a4SBarry Smith   do {
2105dc0f0a4SBarry Smith     char   *clen;
2115dc0f0a4SBarry Smith     int    cl;
2125dc0f0a4SBarry Smith     size_t nlen;
2135dc0f0a4SBarry Smith 
2145dc0f0a4SBarry Smith     r = SSL_read(ssl,buff+len,(int)buffsize);
2155dc0f0a4SBarry Smith     len += r;
216b967cddfSBarry Smith     switch (SSL_get_error(ssl,r)) {
217b967cddfSBarry Smith     case SSL_ERROR_NONE:
218b967cddfSBarry Smith       break;
219b967cddfSBarry Smith     case SSL_ERROR_ZERO_RETURN:
2205dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
2215dc0f0a4SBarry Smith       SSL_shutdown(ssl);
222b967cddfSBarry Smith       break;
223b967cddfSBarry Smith     case SSL_ERROR_SYSCALL:
2245dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
225b967cddfSBarry Smith       break;
226b967cddfSBarry Smith     default:
227b967cddfSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL read problem");
228b967cddfSBarry Smith     }
2295dc0f0a4SBarry Smith 
2305dc0f0a4SBarry Smith     ierr = PetscStrstr(buff,"Content-Length: ",&clen);CHKERRQ(ierr);
2315dc0f0a4SBarry Smith     if (clen) {
2325dc0f0a4SBarry Smith       clen += 15;
2335dc0f0a4SBarry Smith       sscanf(clen,"%d",&cl);
2345dc0f0a4SBarry Smith       if (!cl) foundbody = PETSC_TRUE;
2355dc0f0a4SBarry Smith       else {
2365dc0f0a4SBarry Smith         ierr = PetscStrstr(buff,"\r\n\r\n",&clen);CHKERRQ(ierr);
2375dc0f0a4SBarry Smith         if (clen) {
2385dc0f0a4SBarry Smith           ierr = PetscStrlen(clen,&nlen);CHKERRQ(ierr);
2395dc0f0a4SBarry Smith           if (nlen-4 == (size_t) cl) foundbody = PETSC_TRUE;
2405dc0f0a4SBarry Smith         }
2415dc0f0a4SBarry Smith       }
2425dc0f0a4SBarry Smith     } else {
2435dc0f0a4SBarry Smith       /* if no content length than must leave because you don't know if you can read again */
2445dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
2455dc0f0a4SBarry Smith     }
2465dc0f0a4SBarry Smith   } while (!foundbody);
2477d3de750SJacob Faibussowitsch   ierr = PetscInfo(NULL,"HTTPS result follows: \n%s\n",buff);CHKERRQ(ierr);
248b967cddfSBarry Smith 
249b967cddfSBarry Smith   SSL_free(ssl);
250b967cddfSBarry Smith   ierr = PetscFree(request);CHKERRQ(ierr);
251b967cddfSBarry Smith   PetscFunctionReturn(0);
252b967cddfSBarry Smith }
253b967cddfSBarry Smith 
2544683183fSBarry Smith /*@C
25504102261SBarry Smith      PetscHTTPRequest - Send a request to an HTTP server
25604102261SBarry Smith 
25704102261SBarry Smith    Input Parameters:
25804102261SBarry Smith +   type - either "POST" or "GET"
25904102261SBarry Smith .   url -  URL of request host/path
26004102261SBarry Smith .   header - additional header information, may be NULL
26104102261SBarry Smith .   ctype - data type of body, for example application/json
26204102261SBarry Smith .   body - data to send to server
26304102261SBarry Smith .   sock - obtained with PetscOpenSocket()
26404102261SBarry Smith -   buffsize - size of buffer
26504102261SBarry Smith 
26604102261SBarry Smith    Output Parameter:
26704102261SBarry Smith .   buff - everything returned from server
2684683183fSBarry Smith 
2694683183fSBarry Smith     Level: advanced
2704683183fSBarry Smith 
2714683183fSBarry Smith .seealso: PetscHTTPSRequest(), PetscOpenSocket(), PetscHTTPSConnect(), PetscPullJSONValue()
2724683183fSBarry Smith @*/
27304102261SBarry Smith PetscErrorCode PetscHTTPRequest(const char type[],const char url[],const char header[],const char ctype[],const char body[],int sock,char buff[],size_t buffsize)
27404102261SBarry Smith {
27504102261SBarry Smith   char           *request;
27604102261SBarry Smith   size_t         request_len;
27704102261SBarry Smith   PetscErrorCode ierr;
27804102261SBarry Smith 
27904102261SBarry Smith   PetscFunctionBegin;
28004102261SBarry Smith   ierr = PetscHTTPBuildRequest(type,url,header,ctype,body,&request);CHKERRQ(ierr);
28104102261SBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
28204102261SBarry Smith 
283f253e43cSLisandro Dalcin   ierr = PetscBinaryWrite(sock,request,request_len,PETSC_CHAR);CHKERRQ(ierr);
28404102261SBarry Smith   ierr = PetscFree(request);CHKERRQ(ierr);
2859860990eSLisandro Dalcin   PetscBinaryRead(sock,buff,buffsize,NULL,PETSC_CHAR);
28604102261SBarry Smith   buff[buffsize-1] = 0;
2877d3de750SJacob Faibussowitsch   ierr = PetscInfo(NULL,"HTTP result follows: \n%s\n",buff);CHKERRQ(ierr);
28804102261SBarry Smith   PetscFunctionReturn(0);
28904102261SBarry Smith }
29004102261SBarry Smith 
2914683183fSBarry Smith /*@C
2924683183fSBarry Smith       PetscHTTPSConnect - connect to a HTTPS server
2934683183fSBarry Smith 
2944683183fSBarry Smith     Input Parameters:
2954683183fSBarry Smith +    host - the name of the machine hosting the HTTPS server
2964683183fSBarry Smith .    port - the port number where the server is hosting, usually 443
2974683183fSBarry Smith -    ctx - value obtained with PetscSSLInitializeContext()
2984683183fSBarry Smith 
2994683183fSBarry Smith     Output Parameters:
3004683183fSBarry Smith +    sock - socket to connect
3014683183fSBarry Smith -    ssl - the argument passed to PetscHTTPSRequest()
3024683183fSBarry Smith 
3034683183fSBarry Smith     Level: advanced
3044683183fSBarry Smith 
3054683183fSBarry Smith .seealso: PetscOpenSocket(), PetscHTTPSRequest(), PetscSSLInitializeContext()
3064683183fSBarry Smith @*/
307b967cddfSBarry Smith PetscErrorCode PetscHTTPSConnect(const char host[],int port,SSL_CTX *ctx,int *sock,SSL **ssl)
308b967cddfSBarry Smith {
309b967cddfSBarry Smith   BIO            *sbio;
310b967cddfSBarry Smith   PetscErrorCode ierr;
311b967cddfSBarry Smith 
312b967cddfSBarry Smith   PetscFunctionBegin;
313b967cddfSBarry Smith   /* Connect the TCP socket*/
314b967cddfSBarry Smith   ierr = PetscOpenSocket(host,port,sock);CHKERRQ(ierr);
315b967cddfSBarry Smith 
316b967cddfSBarry Smith   /* Connect the SSL socket */
317b967cddfSBarry Smith   *ssl = SSL_new(ctx);
318b967cddfSBarry Smith   sbio = BIO_new_socket(*sock,BIO_NOCLOSE);
319b967cddfSBarry Smith   SSL_set_bio(*ssl,sbio,sbio);
320*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(SSL_connect(*ssl) <= 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL connect error");
321b967cddfSBarry Smith   PetscFunctionReturn(0);
322b967cddfSBarry Smith }
323b967cddfSBarry Smith 
3244683183fSBarry Smith /*@C
3254683183fSBarry Smith      PetscPullJSONValue - Given a JSON response containing the substring with "key" : "value"  where there may or not be spaces around the : returns the value.
3264683183fSBarry Smith 
3274683183fSBarry Smith     Input Parameters:
3284683183fSBarry Smith +    buff - the char array containing the possible values
3294683183fSBarry Smith .    key - the key of the requested value
3304683183fSBarry Smith -    valuelen - the length of the array to contain the value associated with the key
3314683183fSBarry Smith 
3324683183fSBarry Smith     Output Parameters:
3334683183fSBarry Smith +    value - the value obtained
3344683183fSBarry Smith -    found - flag indicating if the value was found in the buff
3354683183fSBarry Smith 
3364683183fSBarry Smith     Level: advanced
3374683183fSBarry Smith 
3384683183fSBarry Smith @*/
33968e69593SBarry Smith PetscErrorCode PetscPullJSONValue(const char buff[],const char key[],char value[],size_t valuelen,PetscBool *found)
34068e69593SBarry Smith {
34168e69593SBarry Smith   PetscErrorCode ierr;
34268e69593SBarry Smith   char           *v,*w;
34368e69593SBarry Smith   char           work[256];
34468e69593SBarry Smith   size_t         len;
34568e69593SBarry Smith 
34668e69593SBarry Smith   PetscFunctionBegin;
34768e69593SBarry Smith   ierr = PetscStrcpy(work,"\"");CHKERRQ(ierr);
348a126751eSBarry Smith   ierr = PetscStrlcat(work,key,sizeof(work));CHKERRQ(ierr);
34968e69593SBarry Smith   ierr = PetscStrcat(work,"\":");CHKERRQ(ierr);
35068e69593SBarry Smith   ierr = PetscStrstr(buff,work,&v);CHKERRQ(ierr);
35168e69593SBarry Smith   ierr = PetscStrlen(work,&len);CHKERRQ(ierr);
35268e69593SBarry Smith   if (v) {
35368e69593SBarry Smith     v += len;
35468e69593SBarry Smith   } else {
35568e69593SBarry Smith     work[len++-1] = 0;
35668e69593SBarry Smith     ierr = PetscStrcat(work," :");CHKERRQ(ierr);
35768e69593SBarry Smith     ierr = PetscStrstr(buff,work,&v);CHKERRQ(ierr);
35868e69593SBarry Smith     if (!v) {
35968e69593SBarry Smith       *found = PETSC_FALSE;
36068e69593SBarry Smith       PetscFunctionReturn(0);
36168e69593SBarry Smith     }
36268e69593SBarry Smith     v += len;
36368e69593SBarry Smith   }
36468e69593SBarry Smith   ierr = PetscStrchr(v,'\"',&v);CHKERRQ(ierr);
36568e69593SBarry Smith   if (!v) {
36668e69593SBarry Smith     *found = PETSC_FALSE;
36768e69593SBarry Smith     PetscFunctionReturn(0);
36868e69593SBarry Smith   }
36968e69593SBarry Smith   ierr = PetscStrchr(v+1,'\"',&w);CHKERRQ(ierr);
37068e69593SBarry Smith   if (!w) {
37168e69593SBarry Smith     *found = PETSC_FALSE;
37268e69593SBarry Smith     PetscFunctionReturn(0);
37368e69593SBarry Smith   }
37468e69593SBarry Smith   *found = PETSC_TRUE;
375c1f4622dSBarry Smith   ierr = PetscStrncpy(value,v+1,PetscMin((size_t)(w-v),valuelen));CHKERRQ(ierr);
37668e69593SBarry Smith   PetscFunctionReturn(0);
37768e69593SBarry Smith }
3785dc0f0a4SBarry Smith 
3795dc0f0a4SBarry Smith #include <ctype.h>
3805dc0f0a4SBarry Smith 
3814683183fSBarry Smith /*@C
3824683183fSBarry Smith     PetscPushJSONValue -  Puts a "key" : "value" pair onto a string
3835dc0f0a4SBarry Smith 
3844683183fSBarry Smith     Input Parameters:
3854683183fSBarry Smith +   buffer - the char array where the value will be put
3864683183fSBarry Smith .   key - the key value to be set
3874683183fSBarry Smith .   value - the value associated with the key
3884683183fSBarry Smith -   bufflen - the size of the buffer (currently ignored)
3894683183fSBarry Smith 
3904683183fSBarry Smith     Level: advanced
3914683183fSBarry Smith 
39295452b02SPatrick Sanan     Notes:
39395452b02SPatrick Sanan     Ignores lengths so can cause buffer overflow
3944683183fSBarry Smith @*/
3955dc0f0a4SBarry Smith PetscErrorCode PetscPushJSONValue(char buff[],const char key[],const char value[],size_t bufflen)
3965dc0f0a4SBarry Smith {
3975dc0f0a4SBarry Smith   PetscErrorCode ierr;
3985dc0f0a4SBarry Smith   size_t         len;
3995dc0f0a4SBarry Smith   PetscBool      special;
4005dc0f0a4SBarry Smith 
4015dc0f0a4SBarry Smith   PetscFunctionBegin;
4025dc0f0a4SBarry Smith   ierr = PetscStrcmp(value,"null",&special);CHKERRQ(ierr);
4035dc0f0a4SBarry Smith   if (!special) {
4045dc0f0a4SBarry Smith     ierr = PetscStrcmp(value,"true",&special);CHKERRQ(ierr);
4055dc0f0a4SBarry Smith   }
4065dc0f0a4SBarry Smith   if (!special) {
4075dc0f0a4SBarry Smith     ierr = PetscStrcmp(value,"false",&special);CHKERRQ(ierr);
4085dc0f0a4SBarry Smith   }
4095dc0f0a4SBarry Smith   if (!special) {
4105dc0f0a4SBarry Smith     PetscInt i;
4115dc0f0a4SBarry Smith 
4125dc0f0a4SBarry Smith     ierr    = PetscStrlen(value,&len);CHKERRQ(ierr);
4135dc0f0a4SBarry Smith     special = PETSC_TRUE;
4145dc0f0a4SBarry Smith     for (i=0; i<(int)len; i++) {
4155dc0f0a4SBarry Smith       if (!isdigit(value[i])) {
4165dc0f0a4SBarry Smith         special = PETSC_FALSE;
4175dc0f0a4SBarry Smith         break;
4185dc0f0a4SBarry Smith       }
4195dc0f0a4SBarry Smith     }
4205dc0f0a4SBarry Smith   }
4215dc0f0a4SBarry Smith 
4225dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
4235dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,key);CHKERRQ(ierr);
4245dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,"\":");CHKERRQ(ierr);
4255dc0f0a4SBarry Smith   if (!special) {
4265dc0f0a4SBarry Smith     ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
4275dc0f0a4SBarry Smith   }
4285dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,value);CHKERRQ(ierr);
4295dc0f0a4SBarry Smith   if (!special) {
4305dc0f0a4SBarry Smith     ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
4315dc0f0a4SBarry Smith   }
4325dc0f0a4SBarry Smith   PetscFunctionReturn(0);
4335dc0f0a4SBarry Smith }
434