xref: /petsc/src/sys/webclient/client.c (revision bb04b57d8fc8b99a9ce04c03188cf4f575836949)
1b967cddfSBarry Smith 
20efc6a03SBarry Smith #include <petscwebclient.h>
3*bb04b57dSBarry Smith #pragma clang diagnostic ignored "-Wdeprecated-declarations"
4b967cddfSBarry Smith 
5b967cddfSBarry Smith static BIO *bio_err = NULL;
6b967cddfSBarry Smith 
7b967cddfSBarry Smith #define PASSWORD "password"
8b967cddfSBarry Smith 
94a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
10b967cddfSBarry Smith static int password_cb(char *buf,int num, int rwflag,void *userdata)
11b967cddfSBarry Smith {
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 
18b967cddfSBarry Smith static void sigpipe_handle(int x)
19b967cddfSBarry Smith {
20b967cddfSBarry Smith }
21b967cddfSBarry Smith 
22b967cddfSBarry Smith #undef __FUNCT__
23b967cddfSBarry Smith #define __FUNCT__ "PetscSSLInitializeContext"
24b967cddfSBarry Smith /*
25b967cddfSBarry Smith     PetscSSLInitializeContext - Set up an SSL context suitable for initiating HTTPS requests.
26b967cddfSBarry Smith 
274a285bdaSBarry Smith     If built with PETSC_USE_SSL_CERTIFICATE requires the user have created a self-signed certificate with
28b967cddfSBarry Smith 
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 
35b967cddfSBarry Smith */
36b967cddfSBarry Smith PetscErrorCode PetscSSLInitializeContext(SSL_CTX **octx)
37b967cddfSBarry Smith {
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     PetscErrorCode ierr;
43b967cddfSBarry Smith #endif
44b967cddfSBarry Smith 
45b967cddfSBarry Smith     PetscFunctionBegin;
46b967cddfSBarry Smith     if (!bio_err){
47b967cddfSBarry Smith       SSL_library_init();
48b967cddfSBarry Smith       SSL_load_error_strings();
49b967cddfSBarry Smith       bio_err = BIO_new_fp(stderr,BIO_NOCLOSE);
50b967cddfSBarry Smith     }
51b967cddfSBarry Smith 
52b967cddfSBarry Smith     /* Set up a SIGPIPE handler */
53b967cddfSBarry Smith     signal(SIGPIPE,sigpipe_handle);
54b967cddfSBarry Smith 
55d8dcb26dSBarry Smith     ctx  = SSL_CTX_new(SSLv23_method());
565dc0f0a4SBarry Smith     SSL_CTX_set_mode(ctx,SSL_MODE_AUTO_RETRY);
57b967cddfSBarry Smith 
584a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
59b967cddfSBarry Smith     /* Locate keyfile */
60b967cddfSBarry Smith     ierr = PetscStrcpy(keyfile,"sslclient.pem");CHKERRQ(ierr);
61b967cddfSBarry Smith     ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr);
62b967cddfSBarry Smith     if (!exists) {
63b967cddfSBarry Smith       ierr = PetscGetHomeDirectory(keyfile,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
64b967cddfSBarry Smith       ierr = PetscStrcat(keyfile,"/");CHKERRQ(ierr);
65b967cddfSBarry Smith       ierr = PetscStrcat(keyfile,"sslclient.pem");CHKERRQ(ierr);
66b967cddfSBarry Smith       ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr);
67b967cddfSBarry Smith       if (!exists) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate sslclient.pem file in current directory or home directory");
68b967cddfSBarry Smith     }
69b967cddfSBarry Smith 
70b967cddfSBarry Smith     /* Load our keys and certificates*/
71b967cddfSBarry Smith     if (!(SSL_CTX_use_certificate_chain_file(ctx,keyfile))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read certificate file");
72b967cddfSBarry Smith 
73b967cddfSBarry Smith     SSL_CTX_set_default_passwd_cb(ctx,password_cb);
74b967cddfSBarry Smith     if (!(SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read key file");
75b967cddfSBarry Smith #endif
76b967cddfSBarry Smith 
77b967cddfSBarry Smith     *octx = ctx;
78b967cddfSBarry Smith     PetscFunctionReturn(0);
79b967cddfSBarry Smith }
80b967cddfSBarry Smith 
81b967cddfSBarry Smith #undef __FUNCT__
82b967cddfSBarry Smith #define __FUNCT__ "PetscSSLDestroyContext"
83b967cddfSBarry Smith PetscErrorCode PetscSSLDestroyContext(SSL_CTX *ctx)
84b967cddfSBarry Smith {
85b967cddfSBarry Smith   PetscFunctionBegin;
86b967cddfSBarry Smith   SSL_CTX_free(ctx);
87b967cddfSBarry Smith   PetscFunctionReturn(0);
88b967cddfSBarry Smith }
89b967cddfSBarry Smith 
90b967cddfSBarry Smith #undef __FUNCT__
9104102261SBarry Smith #define __FUNCT__ "PetscHTTPBuildRequest"
9204102261SBarry Smith PetscErrorCode PetscHTTPBuildRequest(const char type[],const char url[],const char header[],const char ctype[],const char body[],char **outrequest)
93b967cddfSBarry Smith {
94b967cddfSBarry Smith   char           *request=0;
9593e1d32fSBarry Smith   char           contentlength[40],contenttype[80],*path,*host;
967a3410edSBarry Smith   size_t         request_len,headlen,bodylen,contentlen,pathlen,hostlen,typelen,contenttypelen = 0;
97b967cddfSBarry Smith   PetscErrorCode ierr;
98b967cddfSBarry Smith   PetscBool      flg;
99b967cddfSBarry Smith 
100b967cddfSBarry Smith   PetscFunctionBegin;
10193e1d32fSBarry Smith   ierr = PetscStrallocpy(url,&host);CHKERRQ(ierr);
10293e1d32fSBarry Smith   ierr = PetscStrchr(host,'/',&path);CHKERRQ(ierr);
10393e1d32fSBarry Smith   if (!path) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"url must contain / it is %s",url);
104c245270aSBarry Smith   *path = 0;
10593e1d32fSBarry Smith   ierr  = PetscStrlen(host,&hostlen);CHKERRQ(ierr);
10693e1d32fSBarry Smith 
10793e1d32fSBarry Smith   ierr = PetscStrchr(url,'/',&path);CHKERRQ(ierr);
10893e1d32fSBarry Smith   ierr = PetscStrlen(path,&pathlen);CHKERRQ(ierr);
10993e1d32fSBarry Smith 
110b967cddfSBarry Smith   if (header) {
111b967cddfSBarry Smith     ierr = PetscStrendswith(header,"\r\n",&flg);CHKERRQ(ierr);
112b967cddfSBarry Smith     if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"header must end with \\r\\n");
113b967cddfSBarry Smith   }
114b967cddfSBarry Smith 
115b967cddfSBarry Smith   ierr = PetscStrlen(type,&typelen);CHKERRQ(ierr);
116b967cddfSBarry Smith   if (ctype) {
117b967cddfSBarry Smith     ierr = PetscSNPrintf(contenttype,80,"Content-Type: %s\r\n",ctype);CHKERRQ(ierr);
118b967cddfSBarry Smith     ierr = PetscStrlen(contenttype,&contenttypelen);CHKERRQ(ierr);
119b967cddfSBarry Smith   }
120b967cddfSBarry Smith   ierr = PetscStrlen(header,&headlen);CHKERRQ(ierr);
121b967cddfSBarry Smith   ierr = PetscStrlen(body,&bodylen);CHKERRQ(ierr);
122b967cddfSBarry Smith   ierr = PetscSNPrintf(contentlength,40,"Content-Length: %d\r\n\r\n",(int)bodylen);CHKERRQ(ierr);
123b967cddfSBarry Smith   ierr = PetscStrlen(contentlength,&contentlen);CHKERRQ(ierr);
124b967cddfSBarry Smith 
125b967cddfSBarry Smith   /* Now construct our HTTP request */
12693e1d32fSBarry Smith   request_len = typelen + 1 + pathlen + hostlen + 100 + headlen + contenttypelen + contentlen + bodylen + 1;
127fe278a28SBarry Smith   ierr = PetscMalloc1(request_len,&request);CHKERRQ(ierr);
128b967cddfSBarry Smith   ierr = PetscStrcpy(request,type);CHKERRQ(ierr);
129b967cddfSBarry Smith   ierr = PetscStrcat(request," ");CHKERRQ(ierr);
13093e1d32fSBarry Smith   ierr = PetscStrcat(request,path);CHKERRQ(ierr);
13193e1d32fSBarry Smith   ierr = PetscStrcat(request," HTTP/1.1\r\nHost: ");CHKERRQ(ierr);
13293e1d32fSBarry Smith   ierr = PetscStrcat(request,host);CHKERRQ(ierr);
13393e1d32fSBarry Smith   ierr = PetscFree(host);CHKERRQ(ierr);
13493e1d32fSBarry Smith   ierr = PetscStrcat(request,"\r\nUser-Agent:PETScClient\r\n");CHKERRQ(ierr);
135b967cddfSBarry Smith   ierr = PetscStrcat(request,header);CHKERRQ(ierr);
136b967cddfSBarry Smith   if (ctype) {
137b967cddfSBarry Smith     ierr = PetscStrcat(request,contenttype);CHKERRQ(ierr);
138b967cddfSBarry Smith   }
139b967cddfSBarry Smith   ierr = PetscStrcat(request,contentlength);CHKERRQ(ierr);
140b967cddfSBarry Smith   ierr = PetscStrcat(request,body);CHKERRQ(ierr);
141b967cddfSBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
142b967cddfSBarry Smith   ierr = PetscInfo1(NULL,"HTTPS request follows: \n%s\n",request);CHKERRQ(ierr);
143b967cddfSBarry Smith 
14404102261SBarry Smith   *outrequest = request;
14504102261SBarry Smith   PetscFunctionReturn(0);
14604102261SBarry Smith }
14704102261SBarry Smith 
14804102261SBarry Smith 
14904102261SBarry Smith #undef __FUNCT__
15004102261SBarry Smith #define __FUNCT__ "PetscHTTPSRequest"
15104102261SBarry Smith /*
15204102261SBarry Smith      PetscHTTPSRequest - Send a request to an HTTPS server
15304102261SBarry Smith 
15404102261SBarry Smith    Input Parameters:
15504102261SBarry Smith +   type - either "POST" or "GET"
15604102261SBarry Smith .   url -  URL of request host/path
15704102261SBarry Smith .   header - additional header information, may be NULL
15804102261SBarry Smith .   ctype - data type of body, for example application/json
15904102261SBarry Smith .   body - data to send to server
16004102261SBarry Smith .   ssl - obtained with PetscHTTPSConnect()
16104102261SBarry Smith -   buffsize - size of buffer
16204102261SBarry Smith 
16304102261SBarry Smith    Output Parameter:
16404102261SBarry Smith .   buff - everything returned from server
16504102261SBarry Smith  */
16604102261SBarry 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)
16704102261SBarry Smith {
16804102261SBarry Smith   char           *request;
16904102261SBarry Smith   int            r;
17004102261SBarry Smith   size_t         request_len,len;
17104102261SBarry Smith   PetscErrorCode ierr;
1725dc0f0a4SBarry Smith   PetscBool      foundbody = PETSC_FALSE;
17304102261SBarry Smith 
17404102261SBarry Smith   PetscFunctionBegin;
17504102261SBarry Smith   ierr = PetscHTTPBuildRequest(type,url,header,ctype,body,&request);CHKERRQ(ierr);
17604102261SBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
17704102261SBarry Smith 
178d8dcb26dSBarry Smith   r = SSL_write(ssl,request,(int)request_len);
179b967cddfSBarry Smith   switch (SSL_get_error(ssl,r)){
180b967cddfSBarry Smith     case SSL_ERROR_NONE:
181d8dcb26dSBarry Smith       if (request_len != (size_t)r) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Incomplete write to SSL socket");
182b967cddfSBarry Smith       break;
183b967cddfSBarry Smith     default:
184b967cddfSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL socket write problem");
185b967cddfSBarry Smith   }
186b967cddfSBarry Smith 
1875dc0f0a4SBarry Smith   /* Now read the server's response, globus sends it in two chunks hence must read a second time if needed */
1885dc0f0a4SBarry Smith   ierr      = PetscMemzero(buff,buffsize);CHKERRQ(ierr);
1895dc0f0a4SBarry Smith   len       = 0;
1905dc0f0a4SBarry Smith   foundbody = PETSC_FALSE;
1915dc0f0a4SBarry Smith   do {
1925dc0f0a4SBarry Smith     char   *clen;
1935dc0f0a4SBarry Smith     int    cl;
1945dc0f0a4SBarry Smith     size_t nlen;
1955dc0f0a4SBarry Smith 
1965dc0f0a4SBarry Smith     r = SSL_read(ssl,buff+len,(int)buffsize);
1975dc0f0a4SBarry Smith     len += r;
198b967cddfSBarry Smith     switch (SSL_get_error(ssl,r)){
199b967cddfSBarry Smith     case SSL_ERROR_NONE:
200b967cddfSBarry Smith       break;
201b967cddfSBarry Smith     case SSL_ERROR_ZERO_RETURN:
2025dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
2035dc0f0a4SBarry Smith       SSL_shutdown(ssl);
204b967cddfSBarry Smith       break;
205b967cddfSBarry Smith     case SSL_ERROR_SYSCALL:
2065dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
207b967cddfSBarry Smith       break;
208b967cddfSBarry Smith     default:
209b967cddfSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL read problem");
210b967cddfSBarry Smith     }
2115dc0f0a4SBarry Smith 
2125dc0f0a4SBarry Smith     ierr = PetscStrstr(buff,"Content-Length: ",&clen);CHKERRQ(ierr);
2135dc0f0a4SBarry Smith     if (clen) {
2145dc0f0a4SBarry Smith       clen += 15;
2155dc0f0a4SBarry Smith       sscanf(clen,"%d",&cl);
2165dc0f0a4SBarry Smith       if (!cl) foundbody = PETSC_TRUE;
2175dc0f0a4SBarry Smith       else {
2185dc0f0a4SBarry Smith         ierr = PetscStrstr(buff,"\r\n\r\n",&clen);CHKERRQ(ierr);
2195dc0f0a4SBarry Smith         if (clen) {
2205dc0f0a4SBarry Smith           ierr = PetscStrlen(clen,&nlen);CHKERRQ(ierr);
2215dc0f0a4SBarry Smith           if (nlen-4 == (size_t) cl) foundbody = PETSC_TRUE;
2225dc0f0a4SBarry Smith         }
2235dc0f0a4SBarry Smith       }
2245dc0f0a4SBarry Smith     } else {
2255dc0f0a4SBarry Smith       /* if no content length than must leave because you don't know if you can read again */
2265dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
2275dc0f0a4SBarry Smith     }
2285dc0f0a4SBarry Smith   } while (!foundbody);
229b967cddfSBarry Smith   ierr = PetscInfo1(NULL,"HTTPS result follows: \n%s\n",buff);CHKERRQ(ierr);
230b967cddfSBarry Smith 
231b967cddfSBarry Smith   SSL_free(ssl);
232b967cddfSBarry Smith   ierr = PetscFree(request);CHKERRQ(ierr);
233b967cddfSBarry Smith   PetscFunctionReturn(0);
234b967cddfSBarry Smith }
235b967cddfSBarry Smith 
236b967cddfSBarry Smith #undef __FUNCT__
23704102261SBarry Smith #define __FUNCT__ "PetscHTTPRequest"
23804102261SBarry Smith /*
23904102261SBarry Smith      PetscHTTPRequest - Send a request to an HTTP server
24004102261SBarry Smith 
24104102261SBarry Smith    Input Parameters:
24204102261SBarry Smith +   type - either "POST" or "GET"
24304102261SBarry Smith .   url -  URL of request host/path
24404102261SBarry Smith .   header - additional header information, may be NULL
24504102261SBarry Smith .   ctype - data type of body, for example application/json
24604102261SBarry Smith .   body - data to send to server
24704102261SBarry Smith .   sock - obtained with PetscOpenSocket()
24804102261SBarry Smith -   buffsize - size of buffer
24904102261SBarry Smith 
25004102261SBarry Smith    Output Parameter:
25104102261SBarry Smith .   buff - everything returned from server
25204102261SBarry Smith  */
25304102261SBarry 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)
25404102261SBarry Smith {
25504102261SBarry Smith   char           *request;
25604102261SBarry Smith   size_t         request_len;
25704102261SBarry Smith   PetscErrorCode ierr;
25804102261SBarry Smith 
25904102261SBarry Smith   PetscFunctionBegin;
26004102261SBarry Smith   ierr = PetscHTTPBuildRequest(type,url,header,ctype,body,&request);CHKERRQ(ierr);
26104102261SBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
26204102261SBarry Smith 
26304102261SBarry Smith   ierr = PetscBinaryWrite(sock,request,request_len,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
26404102261SBarry Smith   ierr = PetscFree(request);CHKERRQ(ierr);
26504102261SBarry Smith   PetscBinaryRead(sock,buff,buffsize,PETSC_CHAR);
26604102261SBarry Smith   buff[buffsize-1] = 0;
26704102261SBarry Smith   ierr = PetscInfo1(NULL,"HTTP result follows: \n%s\n",buff);CHKERRQ(ierr);
26804102261SBarry Smith   PetscFunctionReturn(0);
26904102261SBarry Smith }
27004102261SBarry Smith 
27104102261SBarry Smith #undef __FUNCT__
272b967cddfSBarry Smith #define __FUNCT__ "PetscHTTPSConnect"
273b967cddfSBarry Smith PetscErrorCode PetscHTTPSConnect(const char host[],int port,SSL_CTX *ctx,int *sock,SSL **ssl)
274b967cddfSBarry Smith {
275b967cddfSBarry Smith   BIO            *sbio;
276b967cddfSBarry Smith   PetscErrorCode ierr;
277b967cddfSBarry Smith 
278b967cddfSBarry Smith   PetscFunctionBegin;
279b967cddfSBarry Smith   /* Connect the TCP socket*/
280b967cddfSBarry Smith   ierr = PetscOpenSocket(host,port,sock);CHKERRQ(ierr);
281b967cddfSBarry Smith 
282b967cddfSBarry Smith   /* Connect the SSL socket */
283b967cddfSBarry Smith   *ssl = SSL_new(ctx);
284b967cddfSBarry Smith   sbio = BIO_new_socket(*sock,BIO_NOCLOSE);
285b967cddfSBarry Smith   SSL_set_bio(*ssl,sbio,sbio);
286b967cddfSBarry Smith   if (SSL_connect(*ssl) <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL connect error");
287b967cddfSBarry Smith   PetscFunctionReturn(0);
288b967cddfSBarry Smith }
289b967cddfSBarry Smith 
29068e69593SBarry Smith #undef __FUNCT__
29168e69593SBarry Smith #define __FUNCT__ "PetscPullJSONValue"
29268e69593SBarry Smith /*
29368e69593SBarry Smith      Given a JSON response containing the substring with "key" : "value"  where there may or not be spaces around the : returns the value.
29468e69593SBarry Smith */
29568e69593SBarry Smith PetscErrorCode PetscPullJSONValue(const char buff[],const char key[],char value[],size_t valuelen,PetscBool *found)
29668e69593SBarry Smith {
29768e69593SBarry Smith   PetscErrorCode ierr;
29868e69593SBarry Smith   char           *v,*w;
29968e69593SBarry Smith   char           work[256];
30068e69593SBarry Smith   size_t         len;
30168e69593SBarry Smith 
30268e69593SBarry Smith   PetscFunctionBegin;
30368e69593SBarry Smith   ierr = PetscStrcpy(work,"\"");CHKERRQ(ierr);
30468e69593SBarry Smith   ierr = PetscStrncat(work,key,250);CHKERRQ(ierr);
30568e69593SBarry Smith   ierr = PetscStrcat(work,"\":");CHKERRQ(ierr);
30668e69593SBarry Smith   ierr = PetscStrstr(buff,work,&v);CHKERRQ(ierr);
30768e69593SBarry Smith   ierr = PetscStrlen(work,&len);CHKERRQ(ierr);
30868e69593SBarry Smith   if (v) {
30968e69593SBarry Smith     v += len;
31068e69593SBarry Smith   } else {
31168e69593SBarry Smith     work[len++-1] = 0;
31268e69593SBarry Smith     ierr = PetscStrcat(work," :");CHKERRQ(ierr);
31368e69593SBarry Smith     ierr = PetscStrstr(buff,work,&v);CHKERRQ(ierr);
31468e69593SBarry Smith     if (!v) {
31568e69593SBarry Smith       *found = PETSC_FALSE;
31668e69593SBarry Smith       PetscFunctionReturn(0);
31768e69593SBarry Smith     }
31868e69593SBarry Smith     v += len;
31968e69593SBarry Smith   }
32068e69593SBarry Smith   ierr = PetscStrchr(v,'\"',&v);CHKERRQ(ierr);
32168e69593SBarry Smith   if (!v) {
32268e69593SBarry Smith     *found = PETSC_FALSE;
32368e69593SBarry Smith     PetscFunctionReturn(0);
32468e69593SBarry Smith   }
32568e69593SBarry Smith   ierr = PetscStrchr(v+1,'\"',&w);CHKERRQ(ierr);
32668e69593SBarry Smith   if (!w) {
32768e69593SBarry Smith     *found = PETSC_FALSE;
32868e69593SBarry Smith     PetscFunctionReturn(0);
32968e69593SBarry Smith   }
33068e69593SBarry Smith   *found = PETSC_TRUE;
331c1f4622dSBarry Smith   ierr = PetscStrncpy(value,v+1,PetscMin((size_t)(w-v),valuelen));CHKERRQ(ierr);
33268e69593SBarry Smith   PetscFunctionReturn(0);
33368e69593SBarry Smith }
3345dc0f0a4SBarry Smith 
3355dc0f0a4SBarry Smith #include <ctype.h>
3365dc0f0a4SBarry Smith 
3375dc0f0a4SBarry Smith #undef __FUNCT__
3385dc0f0a4SBarry Smith #define __FUNCT__ "PetscPushJSONValue"
3395dc0f0a4SBarry Smith /*
3405dc0f0a4SBarry Smith      Pushs a "key" : "value" pair onto a string
3415dc0f0a4SBarry Smith 
3425dc0f0a4SBarry Smith      Ignores lengths so can cause buffer overflow
3435dc0f0a4SBarry Smith */
3445dc0f0a4SBarry Smith PetscErrorCode PetscPushJSONValue(char buff[],const char key[],const char value[],size_t bufflen)
3455dc0f0a4SBarry Smith {
3465dc0f0a4SBarry Smith   PetscErrorCode ierr;
3475dc0f0a4SBarry Smith   size_t         len;
3485dc0f0a4SBarry Smith   PetscBool      special;
3495dc0f0a4SBarry Smith 
3505dc0f0a4SBarry Smith   PetscFunctionBegin;
3515dc0f0a4SBarry Smith   ierr = PetscStrcmp(value,"null",&special);CHKERRQ(ierr);
3525dc0f0a4SBarry Smith   if (!special) {
3535dc0f0a4SBarry Smith     ierr = PetscStrcmp(value,"true",&special);CHKERRQ(ierr);
3545dc0f0a4SBarry Smith   }
3555dc0f0a4SBarry Smith   if (!special) {
3565dc0f0a4SBarry Smith     ierr = PetscStrcmp(value,"false",&special);CHKERRQ(ierr);
3575dc0f0a4SBarry Smith   }
3585dc0f0a4SBarry Smith   if (!special) {
3595dc0f0a4SBarry Smith     PetscInt i;
3605dc0f0a4SBarry Smith 
3615dc0f0a4SBarry Smith     ierr    = PetscStrlen(value,&len);CHKERRQ(ierr);
3625dc0f0a4SBarry Smith     special = PETSC_TRUE;
3635dc0f0a4SBarry Smith     for (i=0; i<(int)len; i++) {
3645dc0f0a4SBarry Smith       if (!isdigit(value[i])) {
3655dc0f0a4SBarry Smith         special = PETSC_FALSE;
3665dc0f0a4SBarry Smith         break;
3675dc0f0a4SBarry Smith       }
3685dc0f0a4SBarry Smith     }
3695dc0f0a4SBarry Smith   }
3705dc0f0a4SBarry Smith 
3715dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
3725dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,key);CHKERRQ(ierr);
3735dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,"\":");CHKERRQ(ierr);
3745dc0f0a4SBarry Smith   if (!special) {
3755dc0f0a4SBarry Smith     ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
3765dc0f0a4SBarry Smith   }
3775dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,value);CHKERRQ(ierr);
3785dc0f0a4SBarry Smith   if (!special) {
3795dc0f0a4SBarry Smith     ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
3805dc0f0a4SBarry Smith   }
3815dc0f0a4SBarry Smith   PetscFunctionReturn(0);
3825dc0f0a4SBarry Smith }
383