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