xref: /petsc/src/sys/webclient/client.c (revision ecd1d7b800a8e5d54bd2bb04019759f2bc8b1326)
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 
23b967cddfSBarry Smith #undef __FUNCT__
24b967cddfSBarry Smith #define __FUNCT__ "PetscSSLInitializeContext"
254683183fSBarry Smith /*@C
26b967cddfSBarry Smith     PetscSSLInitializeContext - Set up an SSL context suitable for initiating HTTPS requests.
27b967cddfSBarry Smith 
284683183fSBarry Smith     Output Parameter:
294683183fSBarry Smith .   octx - the SSL_CTX to be passed to PetscHTTPSConnect
30b967cddfSBarry Smith 
314683183fSBarry Smith     Level: advanced
324683183fSBarry Smith 
334683183fSBarry Smith     If PETSc was ./configure -with-ssl-certificate requires the user have created a self-signed certificate with
3468e69593SBarry Smith $    saws/CA.pl  -newcert  (using the passphrase of password)
35b967cddfSBarry Smith $    cat newkey.pem newcert.pem > sslclient.pem
36b967cddfSBarry Smith 
37b967cddfSBarry Smith     and put the resulting file in either the current directory (with the application) or in the home directory. This seems kind of
38b967cddfSBarry Smith     silly but it was all I could figure out.
39b967cddfSBarry Smith 
404683183fSBarry Smith .seealso: PetscSSLDestroyContext(), PetscHTTPSConnect(), PetscHTTPSRequest()
414683183fSBarry Smith 
424683183fSBarry Smith @*/
43b967cddfSBarry Smith PetscErrorCode PetscSSLInitializeContext(SSL_CTX **octx)
44b967cddfSBarry Smith {
45b967cddfSBarry Smith     SSL_CTX        *ctx;
464a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
47b967cddfSBarry Smith     char           keyfile[PETSC_MAX_PATH_LEN];
48b967cddfSBarry Smith     PetscBool      exists;
49b967cddfSBarry Smith     PetscErrorCode ierr;
50b967cddfSBarry Smith #endif
51b967cddfSBarry Smith 
52b967cddfSBarry Smith     PetscFunctionBegin;
53b967cddfSBarry Smith     if (!bio_err){
54b967cddfSBarry Smith       SSL_library_init();
55b967cddfSBarry Smith       SSL_load_error_strings();
56b967cddfSBarry Smith       bio_err = BIO_new_fp(stderr,BIO_NOCLOSE);
57b967cddfSBarry Smith     }
58b967cddfSBarry Smith 
59b967cddfSBarry Smith     /* Set up a SIGPIPE handler */
60b967cddfSBarry Smith     signal(SIGPIPE,sigpipe_handle);
61b967cddfSBarry Smith 
62*ecd1d7b8SBarry Smith /* suggested at https://mta.openssl.org/pipermail/openssl-dev/2015-May/001449.html */
63*ecd1d7b8SBarry Smith #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
64*ecd1d7b8SBarry Smith     ctx  = SSL_CTX_new(TLS_client_method());
65*ecd1d7b8SBarry Smith #else
66*ecd1d7b8SBarry Smith     ctx  = SSL_CTX_new(SSLv23_client_method());
67*ecd1d7b8SBarry Smith #endif
685dc0f0a4SBarry Smith     SSL_CTX_set_mode(ctx,SSL_MODE_AUTO_RETRY);
69b967cddfSBarry Smith 
704a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE)
71b967cddfSBarry Smith     /* Locate keyfile */
72b967cddfSBarry Smith     ierr = PetscStrcpy(keyfile,"sslclient.pem");CHKERRQ(ierr);
73b967cddfSBarry Smith     ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr);
74b967cddfSBarry Smith     if (!exists) {
75b967cddfSBarry Smith       ierr = PetscGetHomeDirectory(keyfile,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
76b967cddfSBarry Smith       ierr = PetscStrcat(keyfile,"/");CHKERRQ(ierr);
77b967cddfSBarry Smith       ierr = PetscStrcat(keyfile,"sslclient.pem");CHKERRQ(ierr);
78b967cddfSBarry Smith       ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr);
79b967cddfSBarry Smith       if (!exists) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate sslclient.pem file in current directory or home directory");
80b967cddfSBarry Smith     }
81b967cddfSBarry Smith 
82b967cddfSBarry Smith     /* Load our keys and certificates*/
83b967cddfSBarry Smith     if (!(SSL_CTX_use_certificate_chain_file(ctx,keyfile))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read certificate file");
84b967cddfSBarry Smith 
85b967cddfSBarry Smith     SSL_CTX_set_default_passwd_cb(ctx,password_cb);
86b967cddfSBarry Smith     if (!(SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read key file");
87b967cddfSBarry Smith #endif
88b967cddfSBarry Smith 
89b967cddfSBarry Smith     *octx = ctx;
90b967cddfSBarry Smith     PetscFunctionReturn(0);
91b967cddfSBarry Smith }
92b967cddfSBarry Smith 
93b967cddfSBarry Smith #undef __FUNCT__
94b967cddfSBarry Smith #define __FUNCT__ "PetscSSLDestroyContext"
954683183fSBarry Smith /*@C
964683183fSBarry Smith      PetscSSLDestroyContext - frees a SSL_CTX obtained with PetscSSLInitializeContext()
974683183fSBarry Smith 
984683183fSBarry Smith      Input Parameter:
994683183fSBarry Smith .     ctx - the SSL_CTX
1004683183fSBarry Smith 
1014683183fSBarry Smith     Level: advanced
1024683183fSBarry Smith 
1034683183fSBarry Smith .seealso: PetscSSLInitializeContext(), PetscHTTPSConnect()
1044683183fSBarry Smith @*/
105b967cddfSBarry Smith PetscErrorCode PetscSSLDestroyContext(SSL_CTX *ctx)
106b967cddfSBarry Smith {
107b967cddfSBarry Smith   PetscFunctionBegin;
108b967cddfSBarry Smith   SSL_CTX_free(ctx);
109b967cddfSBarry Smith   PetscFunctionReturn(0);
110b967cddfSBarry Smith }
111b967cddfSBarry Smith 
112b967cddfSBarry Smith #undef __FUNCT__
11304102261SBarry Smith #define __FUNCT__ "PetscHTTPBuildRequest"
1144683183fSBarry Smith static PetscErrorCode PetscHTTPBuildRequest(const char type[],const char url[],const char header[],const char ctype[],const char body[],char **outrequest)
115b967cddfSBarry Smith {
116b967cddfSBarry Smith   char           *request=0;
11793e1d32fSBarry Smith   char           contentlength[40],contenttype[80],*path,*host;
1187a3410edSBarry Smith   size_t         request_len,headlen,bodylen,contentlen,pathlen,hostlen,typelen,contenttypelen = 0;
119b967cddfSBarry Smith   PetscErrorCode ierr;
120b967cddfSBarry Smith   PetscBool      flg;
121b967cddfSBarry Smith 
122b967cddfSBarry Smith   PetscFunctionBegin;
12393e1d32fSBarry Smith   ierr = PetscStrallocpy(url,&host);CHKERRQ(ierr);
12493e1d32fSBarry Smith   ierr = PetscStrchr(host,'/',&path);CHKERRQ(ierr);
12593e1d32fSBarry Smith   if (!path) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"url must contain / it is %s",url);
126c245270aSBarry Smith   *path = 0;
12793e1d32fSBarry Smith   ierr  = PetscStrlen(host,&hostlen);CHKERRQ(ierr);
12893e1d32fSBarry Smith 
12993e1d32fSBarry Smith   ierr = PetscStrchr(url,'/',&path);CHKERRQ(ierr);
13093e1d32fSBarry Smith   ierr = PetscStrlen(path,&pathlen);CHKERRQ(ierr);
13193e1d32fSBarry Smith 
132b967cddfSBarry Smith   if (header) {
133b967cddfSBarry Smith     ierr = PetscStrendswith(header,"\r\n",&flg);CHKERRQ(ierr);
134b967cddfSBarry Smith     if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"header must end with \\r\\n");
135b967cddfSBarry Smith   }
136b967cddfSBarry Smith 
137b967cddfSBarry Smith   ierr = PetscStrlen(type,&typelen);CHKERRQ(ierr);
138b967cddfSBarry Smith   if (ctype) {
139b967cddfSBarry Smith     ierr = PetscSNPrintf(contenttype,80,"Content-Type: %s\r\n",ctype);CHKERRQ(ierr);
140b967cddfSBarry Smith     ierr = PetscStrlen(contenttype,&contenttypelen);CHKERRQ(ierr);
141b967cddfSBarry Smith   }
142b967cddfSBarry Smith   ierr = PetscStrlen(header,&headlen);CHKERRQ(ierr);
143b967cddfSBarry Smith   ierr = PetscStrlen(body,&bodylen);CHKERRQ(ierr);
144b967cddfSBarry Smith   ierr = PetscSNPrintf(contentlength,40,"Content-Length: %d\r\n\r\n",(int)bodylen);CHKERRQ(ierr);
145b967cddfSBarry Smith   ierr = PetscStrlen(contentlength,&contentlen);CHKERRQ(ierr);
146b967cddfSBarry Smith 
147b967cddfSBarry Smith   /* Now construct our HTTP request */
14893e1d32fSBarry Smith   request_len = typelen + 1 + pathlen + hostlen + 100 + headlen + contenttypelen + contentlen + bodylen + 1;
149fe278a28SBarry Smith   ierr = PetscMalloc1(request_len,&request);CHKERRQ(ierr);
150b967cddfSBarry Smith   ierr = PetscStrcpy(request,type);CHKERRQ(ierr);
151b967cddfSBarry Smith   ierr = PetscStrcat(request," ");CHKERRQ(ierr);
15293e1d32fSBarry Smith   ierr = PetscStrcat(request,path);CHKERRQ(ierr);
15393e1d32fSBarry Smith   ierr = PetscStrcat(request," HTTP/1.1\r\nHost: ");CHKERRQ(ierr);
15493e1d32fSBarry Smith   ierr = PetscStrcat(request,host);CHKERRQ(ierr);
15593e1d32fSBarry Smith   ierr = PetscFree(host);CHKERRQ(ierr);
15693e1d32fSBarry Smith   ierr = PetscStrcat(request,"\r\nUser-Agent:PETScClient\r\n");CHKERRQ(ierr);
157b967cddfSBarry Smith   ierr = PetscStrcat(request,header);CHKERRQ(ierr);
158b967cddfSBarry Smith   if (ctype) {
159b967cddfSBarry Smith     ierr = PetscStrcat(request,contenttype);CHKERRQ(ierr);
160b967cddfSBarry Smith   }
161b967cddfSBarry Smith   ierr = PetscStrcat(request,contentlength);CHKERRQ(ierr);
162b967cddfSBarry Smith   ierr = PetscStrcat(request,body);CHKERRQ(ierr);
163b967cddfSBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
164b967cddfSBarry Smith   ierr = PetscInfo1(NULL,"HTTPS request follows: \n%s\n",request);CHKERRQ(ierr);
165b967cddfSBarry Smith 
16604102261SBarry Smith   *outrequest = request;
16704102261SBarry Smith   PetscFunctionReturn(0);
16804102261SBarry Smith }
16904102261SBarry Smith 
17004102261SBarry Smith 
17104102261SBarry Smith #undef __FUNCT__
17204102261SBarry Smith #define __FUNCT__ "PetscHTTPSRequest"
1734683183fSBarry Smith /*@C
17404102261SBarry Smith      PetscHTTPSRequest - Send a request to an HTTPS server
17504102261SBarry Smith 
17604102261SBarry Smith    Input Parameters:
17704102261SBarry Smith +   type - either "POST" or "GET"
17804102261SBarry Smith .   url -  URL of request host/path
17904102261SBarry Smith .   header - additional header information, may be NULL
18004102261SBarry Smith .   ctype - data type of body, for example application/json
18104102261SBarry Smith .   body - data to send to server
18204102261SBarry Smith .   ssl - obtained with PetscHTTPSConnect()
18304102261SBarry Smith -   buffsize - size of buffer
18404102261SBarry Smith 
18504102261SBarry Smith    Output Parameter:
18604102261SBarry Smith .   buff - everything returned from server
1874683183fSBarry Smith 
1884683183fSBarry Smith     Level: advanced
1894683183fSBarry Smith 
1904683183fSBarry Smith .seealso: PetscHTTPRequest(), PetscHTTPSConnect(), PetscSSLInitializeContext(), PetscSSLDestroyContext(), PetscPullJSONValue()
1914683183fSBarry Smith 
1924683183fSBarry Smith @*/
19304102261SBarry 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)
19404102261SBarry Smith {
19504102261SBarry Smith   char           *request;
19604102261SBarry Smith   int            r;
19704102261SBarry Smith   size_t         request_len,len;
19804102261SBarry Smith   PetscErrorCode ierr;
1995dc0f0a4SBarry Smith   PetscBool      foundbody = PETSC_FALSE;
20004102261SBarry Smith 
20104102261SBarry Smith   PetscFunctionBegin;
20204102261SBarry Smith   ierr = PetscHTTPBuildRequest(type,url,header,ctype,body,&request);CHKERRQ(ierr);
20304102261SBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
20404102261SBarry Smith 
205d8dcb26dSBarry Smith   r = SSL_write(ssl,request,(int)request_len);
206b967cddfSBarry Smith   switch (SSL_get_error(ssl,r)){
207b967cddfSBarry Smith     case SSL_ERROR_NONE:
208d8dcb26dSBarry Smith       if (request_len != (size_t)r) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Incomplete write to SSL socket");
209b967cddfSBarry Smith       break;
210b967cddfSBarry Smith     default:
211b967cddfSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL socket write problem");
212b967cddfSBarry Smith   }
213b967cddfSBarry Smith 
2145dc0f0a4SBarry Smith   /* Now read the server's response, globus sends it in two chunks hence must read a second time if needed */
2155dc0f0a4SBarry Smith   ierr      = PetscMemzero(buff,buffsize);CHKERRQ(ierr);
2165dc0f0a4SBarry Smith   len       = 0;
2175dc0f0a4SBarry Smith   foundbody = PETSC_FALSE;
2185dc0f0a4SBarry Smith   do {
2195dc0f0a4SBarry Smith     char   *clen;
2205dc0f0a4SBarry Smith     int    cl;
2215dc0f0a4SBarry Smith     size_t nlen;
2225dc0f0a4SBarry Smith 
2235dc0f0a4SBarry Smith     r = SSL_read(ssl,buff+len,(int)buffsize);
2245dc0f0a4SBarry Smith     len += r;
225b967cddfSBarry Smith     switch (SSL_get_error(ssl,r)){
226b967cddfSBarry Smith     case SSL_ERROR_NONE:
227b967cddfSBarry Smith       break;
228b967cddfSBarry Smith     case SSL_ERROR_ZERO_RETURN:
2295dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
2305dc0f0a4SBarry Smith       SSL_shutdown(ssl);
231b967cddfSBarry Smith       break;
232b967cddfSBarry Smith     case SSL_ERROR_SYSCALL:
2335dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
234b967cddfSBarry Smith       break;
235b967cddfSBarry Smith     default:
236b967cddfSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL read problem");
237b967cddfSBarry Smith     }
2385dc0f0a4SBarry Smith 
2395dc0f0a4SBarry Smith     ierr = PetscStrstr(buff,"Content-Length: ",&clen);CHKERRQ(ierr);
2405dc0f0a4SBarry Smith     if (clen) {
2415dc0f0a4SBarry Smith       clen += 15;
2425dc0f0a4SBarry Smith       sscanf(clen,"%d",&cl);
2435dc0f0a4SBarry Smith       if (!cl) foundbody = PETSC_TRUE;
2445dc0f0a4SBarry Smith       else {
2455dc0f0a4SBarry Smith         ierr = PetscStrstr(buff,"\r\n\r\n",&clen);CHKERRQ(ierr);
2465dc0f0a4SBarry Smith         if (clen) {
2475dc0f0a4SBarry Smith           ierr = PetscStrlen(clen,&nlen);CHKERRQ(ierr);
2485dc0f0a4SBarry Smith           if (nlen-4 == (size_t) cl) foundbody = PETSC_TRUE;
2495dc0f0a4SBarry Smith         }
2505dc0f0a4SBarry Smith       }
2515dc0f0a4SBarry Smith     } else {
2525dc0f0a4SBarry Smith       /* if no content length than must leave because you don't know if you can read again */
2535dc0f0a4SBarry Smith       foundbody = PETSC_TRUE;
2545dc0f0a4SBarry Smith     }
2555dc0f0a4SBarry Smith   } while (!foundbody);
256b967cddfSBarry Smith   ierr = PetscInfo1(NULL,"HTTPS result follows: \n%s\n",buff);CHKERRQ(ierr);
257b967cddfSBarry Smith 
258b967cddfSBarry Smith   SSL_free(ssl);
259b967cddfSBarry Smith   ierr = PetscFree(request);CHKERRQ(ierr);
260b967cddfSBarry Smith   PetscFunctionReturn(0);
261b967cddfSBarry Smith }
262b967cddfSBarry Smith 
263b967cddfSBarry Smith #undef __FUNCT__
26404102261SBarry Smith #define __FUNCT__ "PetscHTTPRequest"
2654683183fSBarry Smith /*@C
26604102261SBarry Smith      PetscHTTPRequest - Send a request to an HTTP server
26704102261SBarry Smith 
26804102261SBarry Smith    Input Parameters:
26904102261SBarry Smith +   type - either "POST" or "GET"
27004102261SBarry Smith .   url -  URL of request host/path
27104102261SBarry Smith .   header - additional header information, may be NULL
27204102261SBarry Smith .   ctype - data type of body, for example application/json
27304102261SBarry Smith .   body - data to send to server
27404102261SBarry Smith .   sock - obtained with PetscOpenSocket()
27504102261SBarry Smith -   buffsize - size of buffer
27604102261SBarry Smith 
27704102261SBarry Smith    Output Parameter:
27804102261SBarry Smith .   buff - everything returned from server
2794683183fSBarry Smith 
2804683183fSBarry Smith     Level: advanced
2814683183fSBarry Smith 
2824683183fSBarry Smith .seealso: PetscHTTPSRequest(), PetscOpenSocket(), PetscHTTPSConnect(), PetscPullJSONValue()
2834683183fSBarry Smith @*/
28404102261SBarry 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)
28504102261SBarry Smith {
28604102261SBarry Smith   char           *request;
28704102261SBarry Smith   size_t         request_len;
28804102261SBarry Smith   PetscErrorCode ierr;
28904102261SBarry Smith 
29004102261SBarry Smith   PetscFunctionBegin;
29104102261SBarry Smith   ierr = PetscHTTPBuildRequest(type,url,header,ctype,body,&request);CHKERRQ(ierr);
29204102261SBarry Smith   ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr);
29304102261SBarry Smith 
29404102261SBarry Smith   ierr = PetscBinaryWrite(sock,request,request_len,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
29504102261SBarry Smith   ierr = PetscFree(request);CHKERRQ(ierr);
29604102261SBarry Smith   PetscBinaryRead(sock,buff,buffsize,PETSC_CHAR);
29704102261SBarry Smith   buff[buffsize-1] = 0;
29804102261SBarry Smith   ierr = PetscInfo1(NULL,"HTTP result follows: \n%s\n",buff);CHKERRQ(ierr);
29904102261SBarry Smith   PetscFunctionReturn(0);
30004102261SBarry Smith }
30104102261SBarry Smith 
30204102261SBarry Smith #undef __FUNCT__
303b967cddfSBarry Smith #define __FUNCT__ "PetscHTTPSConnect"
3044683183fSBarry Smith /*@C
3054683183fSBarry Smith       PetscHTTPSConnect - connect to a HTTPS server
3064683183fSBarry Smith 
3074683183fSBarry Smith     Input Parameters:
3084683183fSBarry Smith +    host - the name of the machine hosting the HTTPS server
3094683183fSBarry Smith .    port - the port number where the server is hosting, usually 443
3104683183fSBarry Smith -    ctx - value obtained with PetscSSLInitializeContext()
3114683183fSBarry Smith 
3124683183fSBarry Smith     Output Parameters:
3134683183fSBarry Smith +    sock - socket to connect
3144683183fSBarry Smith -    ssl - the argument passed to PetscHTTPSRequest()
3154683183fSBarry Smith 
3164683183fSBarry Smith     Level: advanced
3174683183fSBarry Smith 
3184683183fSBarry Smith .seealso: PetscOpenSocket(), PetscHTTPSRequest(), PetscSSLInitializeContext()
3194683183fSBarry Smith @*/
320b967cddfSBarry Smith PetscErrorCode PetscHTTPSConnect(const char host[],int port,SSL_CTX *ctx,int *sock,SSL **ssl)
321b967cddfSBarry Smith {
322b967cddfSBarry Smith   BIO            *sbio;
323b967cddfSBarry Smith   PetscErrorCode ierr;
324b967cddfSBarry Smith 
325b967cddfSBarry Smith   PetscFunctionBegin;
326b967cddfSBarry Smith   /* Connect the TCP socket*/
327b967cddfSBarry Smith   ierr = PetscOpenSocket(host,port,sock);CHKERRQ(ierr);
328b967cddfSBarry Smith 
329b967cddfSBarry Smith   /* Connect the SSL socket */
330b967cddfSBarry Smith   *ssl = SSL_new(ctx);
331b967cddfSBarry Smith   sbio = BIO_new_socket(*sock,BIO_NOCLOSE);
332b967cddfSBarry Smith   SSL_set_bio(*ssl,sbio,sbio);
333b967cddfSBarry Smith   if (SSL_connect(*ssl) <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL connect error");
334b967cddfSBarry Smith   PetscFunctionReturn(0);
335b967cddfSBarry Smith }
336b967cddfSBarry Smith 
33768e69593SBarry Smith #undef __FUNCT__
33868e69593SBarry Smith #define __FUNCT__ "PetscPullJSONValue"
3394683183fSBarry Smith /*@C
3404683183fSBarry Smith      PetscPullJSONValue - Given a JSON response containing the substring with "key" : "value"  where there may or not be spaces around the : returns the value.
3414683183fSBarry Smith 
3424683183fSBarry Smith     Input Parameters:
3434683183fSBarry Smith +    buff - the char array containing the possible values
3444683183fSBarry Smith .    key - the key of the requested value
3454683183fSBarry Smith -    valuelen - the length of the array to contain the value associated with the key
3464683183fSBarry Smith 
3474683183fSBarry Smith     Output Parameters:
3484683183fSBarry Smith +    value - the value obtained
3494683183fSBarry Smith -    found - flag indicating if the value was found in the buff
3504683183fSBarry Smith 
3514683183fSBarry Smith     Level: advanced
3524683183fSBarry Smith 
3534683183fSBarry Smith @*/
35468e69593SBarry Smith PetscErrorCode PetscPullJSONValue(const char buff[],const char key[],char value[],size_t valuelen,PetscBool *found)
35568e69593SBarry Smith {
35668e69593SBarry Smith   PetscErrorCode ierr;
35768e69593SBarry Smith   char           *v,*w;
35868e69593SBarry Smith   char           work[256];
35968e69593SBarry Smith   size_t         len;
36068e69593SBarry Smith 
36168e69593SBarry Smith   PetscFunctionBegin;
36268e69593SBarry Smith   ierr = PetscStrcpy(work,"\"");CHKERRQ(ierr);
36368e69593SBarry Smith   ierr = PetscStrncat(work,key,250);CHKERRQ(ierr);
36468e69593SBarry Smith   ierr = PetscStrcat(work,"\":");CHKERRQ(ierr);
36568e69593SBarry Smith   ierr = PetscStrstr(buff,work,&v);CHKERRQ(ierr);
36668e69593SBarry Smith   ierr = PetscStrlen(work,&len);CHKERRQ(ierr);
36768e69593SBarry Smith   if (v) {
36868e69593SBarry Smith     v += len;
36968e69593SBarry Smith   } else {
37068e69593SBarry Smith     work[len++-1] = 0;
37168e69593SBarry Smith     ierr = PetscStrcat(work," :");CHKERRQ(ierr);
37268e69593SBarry Smith     ierr = PetscStrstr(buff,work,&v);CHKERRQ(ierr);
37368e69593SBarry Smith     if (!v) {
37468e69593SBarry Smith       *found = PETSC_FALSE;
37568e69593SBarry Smith       PetscFunctionReturn(0);
37668e69593SBarry Smith     }
37768e69593SBarry Smith     v += len;
37868e69593SBarry Smith   }
37968e69593SBarry Smith   ierr = PetscStrchr(v,'\"',&v);CHKERRQ(ierr);
38068e69593SBarry Smith   if (!v) {
38168e69593SBarry Smith     *found = PETSC_FALSE;
38268e69593SBarry Smith     PetscFunctionReturn(0);
38368e69593SBarry Smith   }
38468e69593SBarry Smith   ierr = PetscStrchr(v+1,'\"',&w);CHKERRQ(ierr);
38568e69593SBarry Smith   if (!w) {
38668e69593SBarry Smith     *found = PETSC_FALSE;
38768e69593SBarry Smith     PetscFunctionReturn(0);
38868e69593SBarry Smith   }
38968e69593SBarry Smith   *found = PETSC_TRUE;
390c1f4622dSBarry Smith   ierr = PetscStrncpy(value,v+1,PetscMin((size_t)(w-v),valuelen));CHKERRQ(ierr);
39168e69593SBarry Smith   PetscFunctionReturn(0);
39268e69593SBarry Smith }
3935dc0f0a4SBarry Smith 
3945dc0f0a4SBarry Smith #include <ctype.h>
3955dc0f0a4SBarry Smith 
3965dc0f0a4SBarry Smith #undef __FUNCT__
3975dc0f0a4SBarry Smith #define __FUNCT__ "PetscPushJSONValue"
3984683183fSBarry Smith /*@C
3994683183fSBarry Smith     PetscPushJSONValue -  Puts a "key" : "value" pair onto a string
4005dc0f0a4SBarry Smith 
4014683183fSBarry Smith     Input Parameters:
4024683183fSBarry Smith +   buffer - the char array where the value will be put
4034683183fSBarry Smith .   key - the key value to be set
4044683183fSBarry Smith .   value - the value associated with the key
4054683183fSBarry Smith -   bufflen - the size of the buffer (currently ignored)
4064683183fSBarry Smith 
4074683183fSBarry Smith     Level: advanced
4084683183fSBarry Smith 
4094683183fSBarry Smith     Notes: Ignores lengths so can cause buffer overflow
4104683183fSBarry Smith @*/
4115dc0f0a4SBarry Smith PetscErrorCode PetscPushJSONValue(char buff[],const char key[],const char value[],size_t bufflen)
4125dc0f0a4SBarry Smith {
4135dc0f0a4SBarry Smith   PetscErrorCode ierr;
4145dc0f0a4SBarry Smith   size_t         len;
4155dc0f0a4SBarry Smith   PetscBool      special;
4165dc0f0a4SBarry Smith 
4175dc0f0a4SBarry Smith   PetscFunctionBegin;
4185dc0f0a4SBarry Smith   ierr = PetscStrcmp(value,"null",&special);CHKERRQ(ierr);
4195dc0f0a4SBarry Smith   if (!special) {
4205dc0f0a4SBarry Smith     ierr = PetscStrcmp(value,"true",&special);CHKERRQ(ierr);
4215dc0f0a4SBarry Smith   }
4225dc0f0a4SBarry Smith   if (!special) {
4235dc0f0a4SBarry Smith     ierr = PetscStrcmp(value,"false",&special);CHKERRQ(ierr);
4245dc0f0a4SBarry Smith   }
4255dc0f0a4SBarry Smith   if (!special) {
4265dc0f0a4SBarry Smith     PetscInt i;
4275dc0f0a4SBarry Smith 
4285dc0f0a4SBarry Smith     ierr    = PetscStrlen(value,&len);CHKERRQ(ierr);
4295dc0f0a4SBarry Smith     special = PETSC_TRUE;
4305dc0f0a4SBarry Smith     for (i=0; i<(int)len; i++) {
4315dc0f0a4SBarry Smith       if (!isdigit(value[i])) {
4325dc0f0a4SBarry Smith         special = PETSC_FALSE;
4335dc0f0a4SBarry Smith         break;
4345dc0f0a4SBarry Smith       }
4355dc0f0a4SBarry Smith     }
4365dc0f0a4SBarry Smith   }
4375dc0f0a4SBarry Smith 
4385dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
4395dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,key);CHKERRQ(ierr);
4405dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,"\":");CHKERRQ(ierr);
4415dc0f0a4SBarry Smith   if (!special) {
4425dc0f0a4SBarry Smith     ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
4435dc0f0a4SBarry Smith   }
4445dc0f0a4SBarry Smith   ierr = PetscStrcat(buff,value);CHKERRQ(ierr);
4455dc0f0a4SBarry Smith   if (!special) {
4465dc0f0a4SBarry Smith     ierr = PetscStrcat(buff,"\"");CHKERRQ(ierr);
4475dc0f0a4SBarry Smith   }
4485dc0f0a4SBarry Smith   PetscFunctionReturn(0);
4495dc0f0a4SBarry Smith }
450