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 */ 705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(keyfile,"sslclient.pem")); 715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTestFile(keyfile,'r',&exists)); 72b967cddfSBarry Smith if (!exists) { 735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGetHomeDirectory(keyfile,PETSC_MAX_PATH_LEN)); 745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(keyfile,"/")); 755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(keyfile,"sslclient.pem")); 765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTestFile(keyfile,'r',&exists)); 77*28b400f6SJacob Faibussowitsch PetscCheck(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*/ 812c71b3e2SJacob 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); 842c71b3e2SJacob 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; 1175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrallocpy(url,&host)); 1185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrchr(host,'/',&path)); 119*28b400f6SJacob Faibussowitsch PetscCheck(path,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"url must contain / it is %s",url); 120c245270aSBarry Smith *path = 0; 1215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(host,&hostlen)); 12293e1d32fSBarry Smith 1235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrchr(url,'/',&path)); 1245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(path,&pathlen)); 12593e1d32fSBarry Smith 126b967cddfSBarry Smith if (header) { 1275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrendswith(header,"\r\n",&flg)); 128*28b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"header must end with \\r\"); 129b967cddfSBarry Smith } 130b967cddfSBarry Smith 1315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(type,&typelen)); 132b967cddfSBarry Smith if (ctype) { 1335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(contenttype,80,"Content-Type: %s\r\n",ctype)); 1345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(contenttype,&contenttypelen)); 135b967cddfSBarry Smith } 1365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(header,&headlen)); 1375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(body,&bodylen)); 1385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(contentlength,40,"Content-Length: %d\r\n\r\n",(int)bodylen)); 1395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(contentlength,&contentlen)); 140b967cddfSBarry Smith 141b967cddfSBarry Smith /* Now construct our HTTP request */ 14293e1d32fSBarry Smith request_len = typelen + 1 + pathlen + hostlen + 100 + headlen + contenttypelen + contentlen + bodylen + 1; 1435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(request_len,&request)); 1445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(request,type)); 1455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(request," ")); 1465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(request,path)); 1475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(request," HTTP/1.1\r\nHost: ")); 1485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(request,host)); 1495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(host)); 1505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(request,"\r\nUser-Agent:PETScClient\r\n")); 1515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(request,header)); 152b967cddfSBarry Smith if (ctype) { 1535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(request,contenttype)); 154b967cddfSBarry Smith } 1555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(request,contentlength)); 1565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(request,body)); 1575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(request,&request_len)); 1585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"HTTPS request follows: \n%s\n",request)); 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; 1935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHTTPBuildRequest(type,url,header,ctype,body,&request)); 1945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(request,&request_len)); 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: 1992c71b3e2SJacob 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 */ 2065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(buff,buffsize)); 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 2305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrstr(buff,"Content-Length: ",&clen)); 2315dc0f0a4SBarry Smith if (clen) { 2325dc0f0a4SBarry Smith clen += 15; 2335dc0f0a4SBarry Smith sscanf(clen,"%d",&cl); 2345dc0f0a4SBarry Smith if (!cl) foundbody = PETSC_TRUE; 2355dc0f0a4SBarry Smith else { 2365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrstr(buff,"\r\n\r\n",&clen)); 2375dc0f0a4SBarry Smith if (clen) { 2385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(clen,&nlen)); 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); 2475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"HTTPS result follows: \n%s\n",buff)); 248b967cddfSBarry Smith 249b967cddfSBarry Smith SSL_free(ssl); 2505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(request)); 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; 2805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHTTPBuildRequest(type,url,header,ctype,body,&request)); 2815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(request,&request_len)); 28204102261SBarry Smith 2835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBinaryWrite(sock,request,request_len,PETSC_CHAR)); 2845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(request)); 2859860990eSLisandro Dalcin PetscBinaryRead(sock,buff,buffsize,NULL,PETSC_CHAR); 28604102261SBarry Smith buff[buffsize-1] = 0; 2875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"HTTP result follows: \n%s\n",buff)); 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*/ 3145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOpenSocket(host,port,sock)); 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); 3202c71b3e2SJacob 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; 3475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(work,"\"")); 3485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(work,key,sizeof(work))); 3495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(work,"\":")); 3505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrstr(buff,work,&v)); 3515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(work,&len)); 35268e69593SBarry Smith if (v) { 35368e69593SBarry Smith v += len; 35468e69593SBarry Smith } else { 35568e69593SBarry Smith work[len++-1] = 0; 3565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(work," :")); 3575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrstr(buff,work,&v)); 35868e69593SBarry Smith if (!v) { 35968e69593SBarry Smith *found = PETSC_FALSE; 36068e69593SBarry Smith PetscFunctionReturn(0); 36168e69593SBarry Smith } 36268e69593SBarry Smith v += len; 36368e69593SBarry Smith } 3645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrchr(v,'\"',&v)); 36568e69593SBarry Smith if (!v) { 36668e69593SBarry Smith *found = PETSC_FALSE; 36768e69593SBarry Smith PetscFunctionReturn(0); 36868e69593SBarry Smith } 3695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrchr(v+1,'\"',&w)); 37068e69593SBarry Smith if (!w) { 37168e69593SBarry Smith *found = PETSC_FALSE; 37268e69593SBarry Smith PetscFunctionReturn(0); 37368e69593SBarry Smith } 37468e69593SBarry Smith *found = PETSC_TRUE; 3755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(value,v+1,PetscMin((size_t)(w-v),valuelen))); 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; 4025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(value,"null",&special)); 4035dc0f0a4SBarry Smith if (!special) { 4045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(value,"true",&special)); 4055dc0f0a4SBarry Smith } 4065dc0f0a4SBarry Smith if (!special) { 4075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(value,"false",&special)); 4085dc0f0a4SBarry Smith } 4095dc0f0a4SBarry Smith if (!special) { 4105dc0f0a4SBarry Smith PetscInt i; 4115dc0f0a4SBarry Smith 4125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(value,&len)); 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 4225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(buff,"\"")); 4235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(buff,key)); 4245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(buff,"\":")); 4255dc0f0a4SBarry Smith if (!special) { 4265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(buff,"\"")); 4275dc0f0a4SBarry Smith } 4285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(buff,value)); 4295dc0f0a4SBarry Smith if (!special) { 4305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcat(buff,"\"")); 4315dc0f0a4SBarry Smith } 4325dc0f0a4SBarry Smith PetscFunctionReturn(0); 4335dc0f0a4SBarry Smith } 434