xref: /petsc/src/sys/webclient/client.c (revision 5dc0f0a4f1e5fadabb4a56402c5d08263bae98d2)
1b967cddfSBarry Smith 
20efc6a03SBarry Smith #include <petscwebclient.h>
3b967cddfSBarry Smith 
4b967cddfSBarry Smith static BIO *bio_err = NULL;
5b967cddfSBarry Smith 
6b967cddfSBarry Smith #define PASSWORD "password"
7b967cddfSBarry Smith 
84a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
9b967cddfSBarry Smith static int password_cb(char *buf,int num, int rwflag,void *userdata)
10b967cddfSBarry Smith {
11b967cddfSBarry Smith   if (num < strlen(PASSWORD)+1) return(0);
12b967cddfSBarry Smith   strcpy(buf,PASSWORD);
13b967cddfSBarry Smith   return(strlen(PASSWORD));
14b967cddfSBarry Smith }
15b967cddfSBarry Smith #endif
16b967cddfSBarry Smith 
17b967cddfSBarry Smith static void sigpipe_handle(int x)
18b967cddfSBarry Smith {
19b967cddfSBarry Smith }
20b967cddfSBarry Smith 
21b967cddfSBarry Smith #undef __FUNCT__
22b967cddfSBarry Smith #define __FUNCT__ "PetscSSLInitializeContext"
23b967cddfSBarry Smith /*
24b967cddfSBarry Smith     PetscSSLInitializeContext - Set up an SSL context suitable for initiating HTTPS requests.
25b967cddfSBarry Smith 
264a285bdaSBarry Smith     If built with PETSC_USE_SSL_CERTIFICATE requires the user have created a self-signed certificate with
27b967cddfSBarry Smith 
2868e69593SBarry Smith $    saws/CA.pl  -newcert  (using the passphrase of password)
29b967cddfSBarry Smith $    cat newkey.pem newcert.pem > sslclient.pem
30b967cddfSBarry Smith 
31b967cddfSBarry Smith     and put the resulting file in either the current directory (with the application) or in the home directory. This seems kind of
32b967cddfSBarry Smith     silly but it was all I could figure out.
33b967cddfSBarry Smith 
34b967cddfSBarry Smith */
35b967cddfSBarry Smith PetscErrorCode PetscSSLInitializeContext(SSL_CTX **octx)
36b967cddfSBarry Smith {
37b967cddfSBarry Smith     SSL_CTX        *ctx;
384a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
39b967cddfSBarry Smith     char           keyfile[PETSC_MAX_PATH_LEN];
40b967cddfSBarry Smith     PetscBool      exists;
41b967cddfSBarry Smith     PetscErrorCode ierr;
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 
54d8dcb26dSBarry Smith     ctx  = SSL_CTX_new(SSLv23_method());
55*5dc0f0a4SBarry Smith     SSL_CTX_set_mode(ctx,SSL_MODE_AUTO_RETRY);
56b967cddfSBarry Smith 
574a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
58b967cddfSBarry Smith     /* Locate keyfile */
59b967cddfSBarry Smith     ierr = PetscStrcpy(keyfile,"sslclient.pem");CHKERRQ(ierr);
60b967cddfSBarry Smith     ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr);
61b967cddfSBarry Smith     if (!exists) {
62b967cddfSBarry Smith       ierr = PetscGetHomeDirectory(keyfile,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
63b967cddfSBarry Smith       ierr = PetscStrcat(keyfile,"/");CHKERRQ(ierr);
64b967cddfSBarry Smith       ierr = PetscStrcat(keyfile,"sslclient.pem");CHKERRQ(ierr);
65b967cddfSBarry Smith       ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr);
66b967cddfSBarry Smith       if (!exists) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate sslclient.pem file in current directory or home directory");
67b967cddfSBarry Smith     }
68b967cddfSBarry Smith 
69b967cddfSBarry Smith     /* Load our keys and certificates*/
70b967cddfSBarry Smith     if (!(SSL_CTX_use_certificate_chain_file(ctx,keyfile))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read certificate file");
71b967cddfSBarry Smith 
72b967cddfSBarry Smith     SSL_CTX_set_default_passwd_cb(ctx,password_cb);
73b967cddfSBarry Smith     if (!(SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read key file");
74b967cddfSBarry Smith #endif
75b967cddfSBarry Smith 
76b967cddfSBarry Smith     *octx = ctx;
77b967cddfSBarry Smith     PetscFunctionReturn(0);
78b967cddfSBarry Smith }
79b967cddfSBarry Smith 
80b967cddfSBarry Smith #undef __FUNCT__
81b967cddfSBarry Smith #define __FUNCT__ "PetscSSLDestroyContext"
82b967cddfSBarry Smith PetscErrorCode PetscSSLDestroyContext(SSL_CTX *ctx)
83b967cddfSBarry Smith {
84b967cddfSBarry Smith   PetscFunctionBegin;
85b967cddfSBarry Smith   SSL_CTX_free(ctx);
86b967cddfSBarry Smith   PetscFunctionReturn(0);
87b967cddfSBarry Smith }
88b967cddfSBarry Smith 
89b967cddfSBarry Smith #undef __FUNCT__
9004102261SBarry Smith #define __FUNCT__ "PetscHTTPBuildRequest"
9104102261SBarry Smith PetscErrorCode PetscHTTPBuildRequest(const char type[],const char url[],const char header[],const char ctype[],const char body[],char **outrequest)
92b967cddfSBarry Smith {
93b967cddfSBarry Smith   char           *request=0;
9493e1d32fSBarry Smith   char           contentlength[40],contenttype[80],*path,*host;
957a3410edSBarry Smith   size_t         request_len,headlen,bodylen,contentlen,pathlen,hostlen,typelen,contenttypelen = 0;
96b967cddfSBarry Smith   PetscErrorCode ierr;
97b967cddfSBarry Smith   PetscBool      flg;
98b967cddfSBarry Smith 
99b967cddfSBarry Smith   PetscFunctionBegin;
10093e1d32fSBarry Smith   ierr = PetscStrallocpy(url,&host);CHKERRQ(ierr);
10193e1d32fSBarry Smith   ierr = PetscStrchr(host,'/',&path);CHKERRQ(ierr);
10293e1d32fSBarry Smith   if (!path) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"url must contain / it is %s",url);
103c245270aSBarry Smith   *path = 0;
10493e1d32fSBarry Smith   ierr  = PetscStrlen(host,&hostlen);CHKERRQ(ierr);
10593e1d32fSBarry Smith 
10693e1d32fSBarry Smith   ierr = PetscStrchr(url,'/',&path);CHKERRQ(ierr);
10793e1d32fSBarry Smith   ierr = PetscStrlen(path,&pathlen);CHKERRQ(ierr);
10893e1d32fSBarry Smith 
109b967cddfSBarry Smith   if (header) {
110b967cddfSBarry Smith     ierr = PetscStrendswith(header,"\r\n",&flg);CHKERRQ(ierr);
111b967cddfSBarry Smith     if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"header must end with \\r\\n");
112b967cddfSBarry Smith   }
113b967cddfSBarry Smith 
114b967cddfSBarry Smith   ierr = PetscStrlen(type,&typelen);CHKERRQ(ierr);
115b967cddfSBarry Smith   if (ctype) {
116b967cddfSBarry Smith     ierr = PetscSNPrintf(contenttype,80,"Content-Type: %s\r\n",ctype);CHKERRQ(ierr);
117b967cddfSBarry Smith     ierr = PetscStrlen(contenttype,&contenttypelen);CHKERRQ(ierr);
118b967cddfSBarry Smith   }
119b967cddfSBarry Smith   ierr = PetscStrlen(header,&headlen);CHKERRQ(ierr);
120b967cddfSBarry Smith   ierr = PetscStrlen(body,&bodylen);CHKERRQ(ierr);
121b967cddfSBarry Smith   ierr = PetscSNPrintf(contentlength,40,"Content-Length: %d\r\n\r\n",(int)bodylen);CHKERRQ(ierr);
122b967cddfSBarry Smith   ierr = PetscStrlen(contentlength,&contentlen);CHKERRQ(ierr);
123b967cddfSBarry Smith 
124b967cddfSBarry Smith   /* Now construct our HTTP request */
12593e1d32fSBarry Smith   request_len = typelen + 1 + pathlen + hostlen + 100 + headlen + contenttypelen + contentlen + bodylen + 1;
126fe278a28SBarry Smith   ierr = PetscMalloc1(request_len,&request);CHKERRQ(ierr);
127b967cddfSBarry Smith   ierr = PetscStrcpy(request,type);CHKERRQ(ierr);
128b967cddfSBarry Smith   ierr = PetscStrcat(request," ");CHKERRQ(ierr);
12993e1d32fSBarry Smith   ierr = PetscStrcat(request,path);CHKERRQ(ierr);
13093e1d32fSBarry Smith   ierr = PetscStrcat(request," HTTP/1.1\r\nHost: ");CHKERRQ(ierr);
13193e1d32fSBarry Smith   ierr = PetscStrcat(request,host);CHKERRQ(ierr);
13293e1d32fSBarry Smith   ierr = PetscFree(host);CHKERRQ(ierr);
13393e1d32fSBarry Smith   ierr = PetscStrcat(request,"\r\nUser-Agent:PETScClient\r\n");CHKERRQ(ierr);
134b967cddfSBarry Smith   ierr = PetscStrcat(request,header);CHKERRQ(ierr);
135b967cddfSBarry Smith   if (ctype) {
136b967cddfSBarry Smith     ierr = PetscStrcat(request,contenttype);CHKERRQ(ierr);
137b967cddfSBarry Smith   }
138b967cddfSBarry Smith   ierr = PetscStrcat(request,contentlength);CHKERRQ(ierr);
139b967cddfSBarry Smith   ierr = PetscStrcat(request,body);CHKERRQ(ierr);
140b967cddfSBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
141b967cddfSBarry Smith   ierr = PetscInfo1(NULL,"HTTPS request follows: \n%s\n",request);CHKERRQ(ierr);
142b967cddfSBarry Smith 
14304102261SBarry Smith   *outrequest = request;
14404102261SBarry Smith   PetscFunctionReturn(0);
14504102261SBarry Smith }
14604102261SBarry Smith 
14704102261SBarry Smith 
14804102261SBarry Smith #undef __FUNCT__
14904102261SBarry Smith #define __FUNCT__ "PetscHTTPSRequest"
15004102261SBarry Smith /*
15104102261SBarry Smith      PetscHTTPSRequest - Send a request to an HTTPS server
15204102261SBarry Smith 
15304102261SBarry Smith    Input Parameters:
15404102261SBarry Smith +   type - either "POST" or "GET"
15504102261SBarry Smith .   url -  URL of request host/path
15604102261SBarry Smith .   header - additional header information, may be NULL
15704102261SBarry Smith .   ctype - data type of body, for example application/json
15804102261SBarry Smith .   body - data to send to server
15904102261SBarry Smith .   ssl - obtained with PetscHTTPSConnect()
16004102261SBarry Smith -   buffsize - size of buffer
16104102261SBarry Smith 
16204102261SBarry Smith    Output Parameter:
16304102261SBarry Smith .   buff - everything returned from server
16404102261SBarry Smith  */
16504102261SBarry 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)
16604102261SBarry Smith {
16704102261SBarry Smith   char           *request;
16804102261SBarry Smith   int            r;
16904102261SBarry Smith   size_t         request_len,len;
17004102261SBarry Smith   PetscErrorCode ierr;
171*5dc0f0a4SBarry Smith   PetscBool      foundbody = PETSC_FALSE;
17204102261SBarry Smith 
17304102261SBarry Smith   PetscFunctionBegin;
17404102261SBarry Smith   ierr = PetscHTTPBuildRequest(type,url,header,ctype,body,&request);CHKERRQ(ierr);
17504102261SBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
17604102261SBarry Smith 
177d8dcb26dSBarry Smith   r = SSL_write(ssl,request,(int)request_len);
178b967cddfSBarry Smith   switch (SSL_get_error(ssl,r)){
179b967cddfSBarry Smith     case SSL_ERROR_NONE:
180d8dcb26dSBarry Smith       if (request_len != (size_t)r) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Incomplete write to SSL socket");
181b967cddfSBarry Smith       break;
182b967cddfSBarry Smith     default:
183b967cddfSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL socket write problem");
184b967cddfSBarry Smith   }
185b967cddfSBarry Smith 
186*5dc0f0a4SBarry Smith   /* Now read the server's response, globus sends it in two chunks hence must read a second time if needed */
187*5dc0f0a4SBarry Smith   ierr      = PetscMemzero(buff,buffsize);CHKERRQ(ierr);
188*5dc0f0a4SBarry Smith   len       = 0;
189*5dc0f0a4SBarry Smith   foundbody = PETSC_FALSE;
190*5dc0f0a4SBarry Smith   do {
191*5dc0f0a4SBarry Smith     char   *clen;
192*5dc0f0a4SBarry Smith     int    cl;
193*5dc0f0a4SBarry Smith     size_t nlen;
194*5dc0f0a4SBarry Smith 
195*5dc0f0a4SBarry Smith     r = SSL_read(ssl,buff+len,(int)buffsize);
196*5dc0f0a4SBarry Smith     len += r;
197b967cddfSBarry Smith     switch (SSL_get_error(ssl,r)){
198b967cddfSBarry Smith     case SSL_ERROR_NONE:
199b967cddfSBarry Smith       break;
200b967cddfSBarry Smith     case SSL_ERROR_ZERO_RETURN:
201*5dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
202*5dc0f0a4SBarry Smith       SSL_shutdown(ssl);
203b967cddfSBarry Smith       break;
204b967cddfSBarry Smith     case SSL_ERROR_SYSCALL:
205*5dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
206b967cddfSBarry Smith       break;
207b967cddfSBarry Smith     default:
208b967cddfSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL read problem");
209b967cddfSBarry Smith     }
210*5dc0f0a4SBarry Smith 
211*5dc0f0a4SBarry Smith     ierr = PetscStrstr(buff,"Content-Length: ",&clen);CHKERRQ(ierr);
212*5dc0f0a4SBarry Smith     if (clen) {
213*5dc0f0a4SBarry Smith       clen += 15;
214*5dc0f0a4SBarry Smith       sscanf(clen,"%d",&cl);
215*5dc0f0a4SBarry Smith       if (!cl) foundbody = PETSC_TRUE;
216*5dc0f0a4SBarry Smith       else {
217*5dc0f0a4SBarry Smith         ierr = PetscStrstr(buff,"\r\n\r\n",&clen);CHKERRQ(ierr);
218*5dc0f0a4SBarry Smith         if (clen) {
219*5dc0f0a4SBarry Smith           ierr = PetscStrlen(clen,&nlen);CHKERRQ(ierr);
220*5dc0f0a4SBarry Smith           if (nlen-4 == (size_t) cl) foundbody = PETSC_TRUE;
221*5dc0f0a4SBarry Smith         }
222*5dc0f0a4SBarry Smith       }
223*5dc0f0a4SBarry Smith     } else {
224*5dc0f0a4SBarry Smith       /* if no content length than must leave because you don't know if you can read again */
225*5dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
226*5dc0f0a4SBarry Smith     }
227*5dc0f0a4SBarry Smith   } while (!foundbody);
228b967cddfSBarry Smith   ierr = PetscInfo1(NULL,"HTTPS result follows: \n%s\n",buff);CHKERRQ(ierr);
229b967cddfSBarry Smith 
230b967cddfSBarry Smith   SSL_free(ssl);
231b967cddfSBarry Smith   ierr = PetscFree(request);CHKERRQ(ierr);
232b967cddfSBarry Smith   PetscFunctionReturn(0);
233b967cddfSBarry Smith }
234b967cddfSBarry Smith 
235b967cddfSBarry Smith #undef __FUNCT__
23604102261SBarry Smith #define __FUNCT__ "PetscHTTPRequest"
23704102261SBarry Smith /*
23804102261SBarry Smith      PetscHTTPRequest - Send a request to an HTTP server
23904102261SBarry Smith 
24004102261SBarry Smith    Input Parameters:
24104102261SBarry Smith +   type - either "POST" or "GET"
24204102261SBarry Smith .   url -  URL of request host/path
24304102261SBarry Smith .   header - additional header information, may be NULL
24404102261SBarry Smith .   ctype - data type of body, for example application/json
24504102261SBarry Smith .   body - data to send to server
24604102261SBarry Smith .   sock - obtained with PetscOpenSocket()
24704102261SBarry Smith -   buffsize - size of buffer
24804102261SBarry Smith 
24904102261SBarry Smith    Output Parameter:
25004102261SBarry Smith .   buff - everything returned from server
25104102261SBarry Smith  */
25204102261SBarry 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)
25304102261SBarry Smith {
25404102261SBarry Smith   char           *request;
25504102261SBarry Smith   size_t         request_len;
25604102261SBarry Smith   PetscErrorCode ierr;
25704102261SBarry Smith 
25804102261SBarry Smith   PetscFunctionBegin;
25904102261SBarry Smith   ierr = PetscHTTPBuildRequest(type,url,header,ctype,body,&request);CHKERRQ(ierr);
26004102261SBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
26104102261SBarry Smith 
26204102261SBarry Smith   ierr = PetscBinaryWrite(sock,request,request_len,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
26304102261SBarry Smith   ierr = PetscFree(request);CHKERRQ(ierr);
26404102261SBarry Smith   PetscBinaryRead(sock,buff,buffsize,PETSC_CHAR);
26504102261SBarry Smith   buff[buffsize-1] = 0;
26604102261SBarry Smith   ierr = PetscInfo1(NULL,"HTTP result follows: \n%s\n",buff);CHKERRQ(ierr);
26704102261SBarry Smith   PetscFunctionReturn(0);
26804102261SBarry Smith }
26904102261SBarry Smith 
27004102261SBarry Smith #undef __FUNCT__
271b967cddfSBarry Smith #define __FUNCT__ "PetscHTTPSConnect"
272b967cddfSBarry Smith PetscErrorCode PetscHTTPSConnect(const char host[],int port,SSL_CTX *ctx,int *sock,SSL **ssl)
273b967cddfSBarry Smith {
274b967cddfSBarry Smith   BIO            *sbio;
275b967cddfSBarry Smith   PetscErrorCode ierr;
276b967cddfSBarry Smith 
277b967cddfSBarry Smith   PetscFunctionBegin;
278b967cddfSBarry Smith   /* Connect the TCP socket*/
279b967cddfSBarry Smith   ierr = PetscOpenSocket(host,port,sock);CHKERRQ(ierr);
280b967cddfSBarry Smith 
281b967cddfSBarry Smith   /* Connect the SSL socket */
282b967cddfSBarry Smith   *ssl = SSL_new(ctx);
283b967cddfSBarry Smith   sbio = BIO_new_socket(*sock,BIO_NOCLOSE);
284b967cddfSBarry Smith   SSL_set_bio(*ssl,sbio,sbio);
285b967cddfSBarry Smith   if (SSL_connect(*ssl) <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL connect error");
286b967cddfSBarry Smith   PetscFunctionReturn(0);
287b967cddfSBarry Smith }
288b967cddfSBarry Smith 
28968e69593SBarry Smith #undef __FUNCT__
29068e69593SBarry Smith #define __FUNCT__ "PetscPullJSONValue"
29168e69593SBarry Smith /*
29268e69593SBarry Smith      Given a JSON response containing the substring with "key" : "value"  where there may or not be spaces around the : returns the value.
29368e69593SBarry Smith */
29468e69593SBarry Smith PetscErrorCode PetscPullJSONValue(const char buff[],const char key[],char value[],size_t valuelen,PetscBool *found)
29568e69593SBarry Smith {
29668e69593SBarry Smith   PetscErrorCode ierr;
29768e69593SBarry Smith   char           *v,*w;
29868e69593SBarry Smith   char           work[256];
29968e69593SBarry Smith   size_t         len;
30068e69593SBarry Smith 
30168e69593SBarry Smith   PetscFunctionBegin;
30268e69593SBarry Smith   ierr = PetscStrcpy(work,"\"");CHKERRQ(ierr);
30368e69593SBarry Smith   ierr = PetscStrncat(work,key,250);CHKERRQ(ierr);
30468e69593SBarry Smith   ierr = PetscStrcat(work,"\":");CHKERRQ(ierr);
30568e69593SBarry Smith   ierr = PetscStrstr(buff,work,&v);CHKERRQ(ierr);
30668e69593SBarry Smith   ierr = PetscStrlen(work,&len);CHKERRQ(ierr);
30768e69593SBarry Smith   if (v) {
30868e69593SBarry Smith     v += len;
30968e69593SBarry Smith   } else {
31068e69593SBarry Smith     work[len++-1] = 0;
31168e69593SBarry Smith     ierr = PetscStrcat(work," :");CHKERRQ(ierr);
31268e69593SBarry Smith     ierr = PetscStrstr(buff,work,&v);CHKERRQ(ierr);
31368e69593SBarry Smith     if (!v) {
31468e69593SBarry Smith       *found = PETSC_FALSE;
31568e69593SBarry Smith       PetscFunctionReturn(0);
31668e69593SBarry Smith     }
31768e69593SBarry Smith     v += len;
31868e69593SBarry Smith   }
31968e69593SBarry Smith   ierr = PetscStrchr(v,'\"',&v);CHKERRQ(ierr);
32068e69593SBarry Smith   if (!v) {
32168e69593SBarry Smith     *found = PETSC_FALSE;
32268e69593SBarry Smith     PetscFunctionReturn(0);
32368e69593SBarry Smith   }
32468e69593SBarry Smith   ierr = PetscStrchr(v+1,'\"',&w);CHKERRQ(ierr);
32568e69593SBarry Smith   if (!w) {
32668e69593SBarry Smith     *found = PETSC_FALSE;
32768e69593SBarry Smith     PetscFunctionReturn(0);
32868e69593SBarry Smith   }
32968e69593SBarry Smith   *found = PETSC_TRUE;
33068e69593SBarry Smith   ierr = PetscStrncpy(value,v+1,PetscMin(w-v,valuelen));CHKERRQ(ierr);
33168e69593SBarry Smith   PetscFunctionReturn(0);
33268e69593SBarry Smith }
333*5dc0f0a4SBarry Smith 
334*5dc0f0a4SBarry Smith #include <ctype.h>
335*5dc0f0a4SBarry Smith 
336*5dc0f0a4SBarry Smith #undef __FUNCT__
337*5dc0f0a4SBarry Smith #define __FUNCT__ "PetscPushJSONValue"
338*5dc0f0a4SBarry Smith /*
339*5dc0f0a4SBarry Smith      Pushs a "key" : "value" pair onto a string
340*5dc0f0a4SBarry Smith 
341*5dc0f0a4SBarry Smith      Ignores lengths so can cause buffer overflow
342*5dc0f0a4SBarry Smith */
343*5dc0f0a4SBarry Smith PetscErrorCode PetscPushJSONValue(char buff[],const char key[],const char value[],size_t bufflen)
344*5dc0f0a4SBarry Smith {
345*5dc0f0a4SBarry Smith   PetscErrorCode ierr;
346*5dc0f0a4SBarry Smith   size_t         len;
347*5dc0f0a4SBarry Smith   PetscBool      special;
348*5dc0f0a4SBarry Smith 
349*5dc0f0a4SBarry Smith   PetscFunctionBegin;
350*5dc0f0a4SBarry Smith   ierr = PetscStrcmp(value,"null",&special);CHKERRQ(ierr);
351*5dc0f0a4SBarry Smith   if (!special) {
352*5dc0f0a4SBarry Smith     ierr = PetscStrcmp(value,"true",&special);CHKERRQ(ierr);
353*5dc0f0a4SBarry Smith   }
354*5dc0f0a4SBarry Smith   if (!special) {
355*5dc0f0a4SBarry Smith     ierr = PetscStrcmp(value,"false",&special);CHKERRQ(ierr);
356*5dc0f0a4SBarry Smith   }
357*5dc0f0a4SBarry Smith   if (!special) {
358*5dc0f0a4SBarry Smith     PetscInt i;
359*5dc0f0a4SBarry Smith 
360*5dc0f0a4SBarry Smith     ierr    = PetscStrlen(value,&len);CHKERRQ(ierr);
361*5dc0f0a4SBarry Smith     special = PETSC_TRUE;
362*5dc0f0a4SBarry Smith     for (i=0; i<(int)len; i++) {
363*5dc0f0a4SBarry Smith       if (!isdigit(value[i])) {
364*5dc0f0a4SBarry Smith         special = PETSC_FALSE;
365*5dc0f0a4SBarry Smith         break;
366*5dc0f0a4SBarry Smith       }
367*5dc0f0a4SBarry Smith     }
368*5dc0f0a4SBarry Smith   }
369*5dc0f0a4SBarry Smith 
370*5dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
371*5dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,key);CHKERRQ(ierr);
372*5dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,"\":");CHKERRQ(ierr);
373*5dc0f0a4SBarry Smith   if (!special) {
374*5dc0f0a4SBarry Smith     ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
375*5dc0f0a4SBarry Smith   }
376*5dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,value);CHKERRQ(ierr);
377*5dc0f0a4SBarry Smith   if (!special) {
378*5dc0f0a4SBarry Smith     ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
379*5dc0f0a4SBarry Smith   }
380*5dc0f0a4SBarry Smith   PetscFunctionReturn(0);
381*5dc0f0a4SBarry Smith }
382