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 38db781477SPatrick Sanan .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 #endif 48b967cddfSBarry Smith 49b967cddfSBarry Smith PetscFunctionBegin; 50b967cddfSBarry Smith if (!bio_err) { 51b967cddfSBarry Smith SSL_library_init(); 52b967cddfSBarry Smith SSL_load_error_strings(); 53b967cddfSBarry Smith bio_err = BIO_new_fp(stderr,BIO_NOCLOSE); 54b967cddfSBarry Smith } 55b967cddfSBarry Smith 56b967cddfSBarry Smith /* Set up a SIGPIPE handler */ 57b967cddfSBarry Smith signal(SIGPIPE,sigpipe_handle); 58b967cddfSBarry Smith 59ecd1d7b8SBarry Smith /* suggested at https://mta.openssl.org/pipermail/openssl-dev/2015-May/001449.html */ 60ecd1d7b8SBarry Smith #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) 61ecd1d7b8SBarry Smith ctx = SSL_CTX_new(TLS_client_method()); 62ecd1d7b8SBarry Smith #else 63ecd1d7b8SBarry Smith ctx = SSL_CTX_new(SSLv23_client_method()); 64ecd1d7b8SBarry Smith #endif 655dc0f0a4SBarry Smith SSL_CTX_set_mode(ctx,SSL_MODE_AUTO_RETRY); 66b967cddfSBarry Smith 674a285bdaSBarry Smith #if defined(PETSC_USE_SSL_CERTIFICATE) 68b967cddfSBarry Smith /* Locate keyfile */ 699566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(keyfile,"sslclient.pem")); 709566063dSJacob Faibussowitsch PetscCall(PetscTestFile(keyfile,'r',&exists)); 71b967cddfSBarry Smith if (!exists) { 729566063dSJacob Faibussowitsch PetscCall(PetscGetHomeDirectory(keyfile,PETSC_MAX_PATH_LEN)); 739566063dSJacob Faibussowitsch PetscCall(PetscStrcat(keyfile,"/")); 749566063dSJacob Faibussowitsch PetscCall(PetscStrcat(keyfile,"sslclient.pem")); 759566063dSJacob Faibussowitsch PetscCall(PetscTestFile(keyfile,'r',&exists)); 7628b400f6SJacob Faibussowitsch PetscCheck(exists,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate sslclient.pem file in current directory or home directory"); 77b967cddfSBarry Smith } 78b967cddfSBarry Smith 79b967cddfSBarry Smith /* Load our keys and certificates*/ 80cc73adaaSBarry Smith PetscCheck(SSL_CTX_use_certificate_chain_file(ctx,keyfile),PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read certificate file"); 81b967cddfSBarry Smith 82b967cddfSBarry Smith SSL_CTX_set_default_passwd_cb(ctx,password_cb); 83cc73adaaSBarry Smith PetscCheck(SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM),PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read key file"); 84b967cddfSBarry Smith #endif 85b967cddfSBarry Smith 86b967cddfSBarry Smith *octx = ctx; 87b967cddfSBarry Smith PetscFunctionReturn(0); 88b967cddfSBarry Smith } 89b967cddfSBarry Smith 904683183fSBarry Smith /*@C 914683183fSBarry Smith PetscSSLDestroyContext - frees a SSL_CTX obtained with PetscSSLInitializeContext() 924683183fSBarry Smith 934683183fSBarry Smith Input Parameter: 944683183fSBarry Smith . ctx - the SSL_CTX 954683183fSBarry Smith 964683183fSBarry Smith Level: advanced 974683183fSBarry Smith 98db781477SPatrick Sanan .seealso: `PetscSSLInitializeContext()`, `PetscHTTPSConnect()` 994683183fSBarry Smith @*/ 100b967cddfSBarry Smith PetscErrorCode PetscSSLDestroyContext(SSL_CTX *ctx) 101b967cddfSBarry Smith { 102b967cddfSBarry Smith PetscFunctionBegin; 103b967cddfSBarry Smith SSL_CTX_free(ctx); 104b967cddfSBarry Smith PetscFunctionReturn(0); 105b967cddfSBarry Smith } 106b967cddfSBarry Smith 1074683183fSBarry Smith static PetscErrorCode PetscHTTPBuildRequest(const char type[],const char url[],const char header[],const char ctype[],const char body[],char **outrequest) 108b967cddfSBarry Smith { 109b967cddfSBarry Smith char *request=0; 11093e1d32fSBarry Smith char contentlength[40],contenttype[80],*path,*host; 1117a3410edSBarry Smith size_t request_len,headlen,bodylen,contentlen,pathlen,hostlen,typelen,contenttypelen = 0; 112b967cddfSBarry Smith PetscBool flg; 113b967cddfSBarry Smith 114b967cddfSBarry Smith PetscFunctionBegin; 1159566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(url,&host)); 1169566063dSJacob Faibussowitsch PetscCall(PetscStrchr(host,'/',&path)); 11728b400f6SJacob Faibussowitsch PetscCheck(path,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"url must contain / it is %s",url); 118c245270aSBarry Smith *path = 0; 1199566063dSJacob Faibussowitsch PetscCall(PetscStrlen(host,&hostlen)); 12093e1d32fSBarry Smith 1219566063dSJacob Faibussowitsch PetscCall(PetscStrchr(url,'/',&path)); 1229566063dSJacob Faibussowitsch PetscCall(PetscStrlen(path,&pathlen)); 12393e1d32fSBarry Smith 124b967cddfSBarry Smith if (header) { 1259566063dSJacob Faibussowitsch PetscCall(PetscStrendswith(header,"\r\n",&flg)); 126d8174014SToby Isaac PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"header must end with \\r\\n"); 127b967cddfSBarry Smith } 128b967cddfSBarry Smith 1299566063dSJacob Faibussowitsch PetscCall(PetscStrlen(type,&typelen)); 130b967cddfSBarry Smith if (ctype) { 1319566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(contenttype,80,"Content-Type: %s\r\n",ctype)); 1329566063dSJacob Faibussowitsch PetscCall(PetscStrlen(contenttype,&contenttypelen)); 133b967cddfSBarry Smith } 1349566063dSJacob Faibussowitsch PetscCall(PetscStrlen(header,&headlen)); 1359566063dSJacob Faibussowitsch PetscCall(PetscStrlen(body,&bodylen)); 1369566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(contentlength,40,"Content-Length: %d\r\n\r\n",(int)bodylen)); 1379566063dSJacob Faibussowitsch PetscCall(PetscStrlen(contentlength,&contentlen)); 138b967cddfSBarry Smith 139b967cddfSBarry Smith /* Now construct our HTTP request */ 14093e1d32fSBarry Smith request_len = typelen + 1 + pathlen + hostlen + 100 + headlen + contenttypelen + contentlen + bodylen + 1; 1419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(request_len,&request)); 1429566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(request,type)); 1439566063dSJacob Faibussowitsch PetscCall(PetscStrcat(request," ")); 1449566063dSJacob Faibussowitsch PetscCall(PetscStrcat(request,path)); 1459566063dSJacob Faibussowitsch PetscCall(PetscStrcat(request," HTTP/1.1\r\nHost: ")); 1469566063dSJacob Faibussowitsch PetscCall(PetscStrcat(request,host)); 1479566063dSJacob Faibussowitsch PetscCall(PetscFree(host)); 1489566063dSJacob Faibussowitsch PetscCall(PetscStrcat(request,"\r\nUser-Agent:PETScClient\r\n")); 1499566063dSJacob Faibussowitsch PetscCall(PetscStrcat(request,header)); 150*1baa6e33SBarry Smith if (ctype) PetscCall(PetscStrcat(request,contenttype)); 1519566063dSJacob Faibussowitsch PetscCall(PetscStrcat(request,contentlength)); 1529566063dSJacob Faibussowitsch PetscCall(PetscStrcat(request,body)); 1539566063dSJacob Faibussowitsch PetscCall(PetscStrlen(request,&request_len)); 1549566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL,"HTTPS request follows: \n%s\n",request)); 155b967cddfSBarry Smith 15604102261SBarry Smith *outrequest = request; 15704102261SBarry Smith PetscFunctionReturn(0); 15804102261SBarry Smith } 15904102261SBarry Smith 1604683183fSBarry Smith /*@C 16104102261SBarry Smith PetscHTTPSRequest - Send a request to an HTTPS server 16204102261SBarry Smith 16304102261SBarry Smith Input Parameters: 16404102261SBarry Smith + type - either "POST" or "GET" 16504102261SBarry Smith . url - URL of request host/path 16604102261SBarry Smith . header - additional header information, may be NULL 16704102261SBarry Smith . ctype - data type of body, for example application/json 16804102261SBarry Smith . body - data to send to server 16904102261SBarry Smith . ssl - obtained with PetscHTTPSConnect() 17004102261SBarry Smith - buffsize - size of buffer 17104102261SBarry Smith 17204102261SBarry Smith Output Parameter: 17304102261SBarry Smith . buff - everything returned from server 1744683183fSBarry Smith 1754683183fSBarry Smith Level: advanced 1764683183fSBarry Smith 177db781477SPatrick Sanan .seealso: `PetscHTTPRequest()`, `PetscHTTPSConnect()`, `PetscSSLInitializeContext()`, `PetscSSLDestroyContext()`, `PetscPullJSONValue()` 1784683183fSBarry Smith 1794683183fSBarry Smith @*/ 18004102261SBarry 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) 18104102261SBarry Smith { 18204102261SBarry Smith char *request; 18304102261SBarry Smith int r; 18404102261SBarry Smith size_t request_len,len; 1855dc0f0a4SBarry Smith PetscBool foundbody = PETSC_FALSE; 18604102261SBarry Smith 18704102261SBarry Smith PetscFunctionBegin; 1889566063dSJacob Faibussowitsch PetscCall(PetscHTTPBuildRequest(type,url,header,ctype,body,&request)); 1899566063dSJacob Faibussowitsch PetscCall(PetscStrlen(request,&request_len)); 19004102261SBarry Smith 191d8dcb26dSBarry Smith r = SSL_write(ssl,request,(int)request_len); 192b967cddfSBarry Smith switch (SSL_get_error(ssl,r)) { 193b967cddfSBarry Smith case SSL_ERROR_NONE: 194cc73adaaSBarry Smith PetscCheck(request_len == (size_t)r,PETSC_COMM_SELF,PETSC_ERR_LIB,"Incomplete write to SSL socket"); 195b967cddfSBarry Smith break; 196b967cddfSBarry Smith default: 197b967cddfSBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL socket write problem"); 198b967cddfSBarry Smith } 199b967cddfSBarry Smith 2005dc0f0a4SBarry Smith /* Now read the server's response, globus sends it in two chunks hence must read a second time if needed */ 2019566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(buff,buffsize)); 2025dc0f0a4SBarry Smith len = 0; 2035dc0f0a4SBarry Smith foundbody = PETSC_FALSE; 2045dc0f0a4SBarry Smith do { 2055dc0f0a4SBarry Smith char *clen; 2065dc0f0a4SBarry Smith int cl; 2075dc0f0a4SBarry Smith size_t nlen; 2085dc0f0a4SBarry Smith 2095dc0f0a4SBarry Smith r = SSL_read(ssl,buff+len,(int)buffsize); 2105dc0f0a4SBarry Smith len += r; 211b967cddfSBarry Smith switch (SSL_get_error(ssl,r)) { 212b967cddfSBarry Smith case SSL_ERROR_NONE: 213b967cddfSBarry Smith break; 214b967cddfSBarry Smith case SSL_ERROR_ZERO_RETURN: 2155dc0f0a4SBarry Smith foundbody = PETSC_TRUE; 2165dc0f0a4SBarry Smith SSL_shutdown(ssl); 217b967cddfSBarry Smith break; 218b967cddfSBarry Smith case SSL_ERROR_SYSCALL: 2195dc0f0a4SBarry Smith foundbody = PETSC_TRUE; 220b967cddfSBarry Smith break; 221b967cddfSBarry Smith default: 222b967cddfSBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL read problem"); 223b967cddfSBarry Smith } 2245dc0f0a4SBarry Smith 2259566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buff,"Content-Length: ",&clen)); 2265dc0f0a4SBarry Smith if (clen) { 2275dc0f0a4SBarry Smith clen += 15; 2285dc0f0a4SBarry Smith sscanf(clen,"%d",&cl); 2295dc0f0a4SBarry Smith if (!cl) foundbody = PETSC_TRUE; 2305dc0f0a4SBarry Smith else { 2319566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buff,"\r\n\r\n",&clen)); 2325dc0f0a4SBarry Smith if (clen) { 2339566063dSJacob Faibussowitsch PetscCall(PetscStrlen(clen,&nlen)); 2345dc0f0a4SBarry Smith if (nlen-4 == (size_t) cl) foundbody = PETSC_TRUE; 2355dc0f0a4SBarry Smith } 2365dc0f0a4SBarry Smith } 2375dc0f0a4SBarry Smith } else { 2385dc0f0a4SBarry Smith /* if no content length than must leave because you don't know if you can read again */ 2395dc0f0a4SBarry Smith foundbody = PETSC_TRUE; 2405dc0f0a4SBarry Smith } 2415dc0f0a4SBarry Smith } while (!foundbody); 2429566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL,"HTTPS result follows: \n%s\n",buff)); 243b967cddfSBarry Smith 244b967cddfSBarry Smith SSL_free(ssl); 2459566063dSJacob Faibussowitsch PetscCall(PetscFree(request)); 246b967cddfSBarry Smith PetscFunctionReturn(0); 247b967cddfSBarry Smith } 248b967cddfSBarry Smith 2494683183fSBarry Smith /*@C 25004102261SBarry Smith PetscHTTPRequest - Send a request to an HTTP server 25104102261SBarry Smith 25204102261SBarry Smith Input Parameters: 25304102261SBarry Smith + type - either "POST" or "GET" 25404102261SBarry Smith . url - URL of request host/path 25504102261SBarry Smith . header - additional header information, may be NULL 25604102261SBarry Smith . ctype - data type of body, for example application/json 25704102261SBarry Smith . body - data to send to server 25804102261SBarry Smith . sock - obtained with PetscOpenSocket() 25904102261SBarry Smith - buffsize - size of buffer 26004102261SBarry Smith 26104102261SBarry Smith Output Parameter: 26204102261SBarry Smith . buff - everything returned from server 2634683183fSBarry Smith 2644683183fSBarry Smith Level: advanced 2654683183fSBarry Smith 266db781477SPatrick Sanan .seealso: `PetscHTTPSRequest()`, `PetscOpenSocket()`, `PetscHTTPSConnect()`, `PetscPullJSONValue()` 2674683183fSBarry Smith @*/ 26804102261SBarry 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) 26904102261SBarry Smith { 27004102261SBarry Smith char *request; 27104102261SBarry Smith size_t request_len; 27204102261SBarry Smith 27304102261SBarry Smith PetscFunctionBegin; 2749566063dSJacob Faibussowitsch PetscCall(PetscHTTPBuildRequest(type,url,header,ctype,body,&request)); 2759566063dSJacob Faibussowitsch PetscCall(PetscStrlen(request,&request_len)); 27604102261SBarry Smith 2779566063dSJacob Faibussowitsch PetscCall(PetscBinaryWrite(sock,request,request_len,PETSC_CHAR)); 2789566063dSJacob Faibussowitsch PetscCall(PetscFree(request)); 2799860990eSLisandro Dalcin PetscBinaryRead(sock,buff,buffsize,NULL,PETSC_CHAR); 28004102261SBarry Smith buff[buffsize-1] = 0; 2819566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL,"HTTP result follows: \n%s\n",buff)); 28204102261SBarry Smith PetscFunctionReturn(0); 28304102261SBarry Smith } 28404102261SBarry Smith 2854683183fSBarry Smith /*@C 2864683183fSBarry Smith PetscHTTPSConnect - connect to a HTTPS server 2874683183fSBarry Smith 2884683183fSBarry Smith Input Parameters: 2894683183fSBarry Smith + host - the name of the machine hosting the HTTPS server 2904683183fSBarry Smith . port - the port number where the server is hosting, usually 443 2914683183fSBarry Smith - ctx - value obtained with PetscSSLInitializeContext() 2924683183fSBarry Smith 2934683183fSBarry Smith Output Parameters: 2944683183fSBarry Smith + sock - socket to connect 2954683183fSBarry Smith - ssl - the argument passed to PetscHTTPSRequest() 2964683183fSBarry Smith 2974683183fSBarry Smith Level: advanced 2984683183fSBarry Smith 299db781477SPatrick Sanan .seealso: `PetscOpenSocket()`, `PetscHTTPSRequest()`, `PetscSSLInitializeContext()` 3004683183fSBarry Smith @*/ 301b967cddfSBarry Smith PetscErrorCode PetscHTTPSConnect(const char host[],int port,SSL_CTX *ctx,int *sock,SSL **ssl) 302b967cddfSBarry Smith { 303b967cddfSBarry Smith BIO *sbio; 304b967cddfSBarry Smith 305b967cddfSBarry Smith PetscFunctionBegin; 306b967cddfSBarry Smith /* Connect the TCP socket*/ 3079566063dSJacob Faibussowitsch PetscCall(PetscOpenSocket(host,port,sock)); 308b967cddfSBarry Smith 309b967cddfSBarry Smith /* Connect the SSL socket */ 310b967cddfSBarry Smith *ssl = SSL_new(ctx); 311b967cddfSBarry Smith sbio = BIO_new_socket(*sock,BIO_NOCLOSE); 312b967cddfSBarry Smith SSL_set_bio(*ssl,sbio,sbio); 31308401ef6SPierre Jolivet PetscCheck(SSL_connect(*ssl) > 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL connect error"); 314b967cddfSBarry Smith PetscFunctionReturn(0); 315b967cddfSBarry Smith } 316b967cddfSBarry Smith 3174683183fSBarry Smith /*@C 3184683183fSBarry Smith PetscPullJSONValue - Given a JSON response containing the substring with "key" : "value" where there may or not be spaces around the : returns the value. 3194683183fSBarry Smith 3204683183fSBarry Smith Input Parameters: 3214683183fSBarry Smith + buff - the char array containing the possible values 3224683183fSBarry Smith . key - the key of the requested value 3234683183fSBarry Smith - valuelen - the length of the array to contain the value associated with the key 3244683183fSBarry Smith 3254683183fSBarry Smith Output Parameters: 3264683183fSBarry Smith + value - the value obtained 3274683183fSBarry Smith - found - flag indicating if the value was found in the buff 3284683183fSBarry Smith 3294683183fSBarry Smith Level: advanced 3304683183fSBarry Smith 3314683183fSBarry Smith @*/ 33268e69593SBarry Smith PetscErrorCode PetscPullJSONValue(const char buff[],const char key[],char value[],size_t valuelen,PetscBool *found) 33368e69593SBarry Smith { 33468e69593SBarry Smith char *v,*w; 33568e69593SBarry Smith char work[256]; 33668e69593SBarry Smith size_t len; 33768e69593SBarry Smith 33868e69593SBarry Smith PetscFunctionBegin; 3399566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(work,"\"")); 3409566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(work,key,sizeof(work))); 3419566063dSJacob Faibussowitsch PetscCall(PetscStrcat(work,"\":")); 3429566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buff,work,&v)); 3439566063dSJacob Faibussowitsch PetscCall(PetscStrlen(work,&len)); 34468e69593SBarry Smith if (v) { 34568e69593SBarry Smith v += len; 34668e69593SBarry Smith } else { 34768e69593SBarry Smith work[len++-1] = 0; 3489566063dSJacob Faibussowitsch PetscCall(PetscStrcat(work," :")); 3499566063dSJacob Faibussowitsch PetscCall(PetscStrstr(buff,work,&v)); 35068e69593SBarry Smith if (!v) { 35168e69593SBarry Smith *found = PETSC_FALSE; 35268e69593SBarry Smith PetscFunctionReturn(0); 35368e69593SBarry Smith } 35468e69593SBarry Smith v += len; 35568e69593SBarry Smith } 3569566063dSJacob Faibussowitsch PetscCall(PetscStrchr(v,'\"',&v)); 35768e69593SBarry Smith if (!v) { 35868e69593SBarry Smith *found = PETSC_FALSE; 35968e69593SBarry Smith PetscFunctionReturn(0); 36068e69593SBarry Smith } 3619566063dSJacob Faibussowitsch PetscCall(PetscStrchr(v+1,'\"',&w)); 36268e69593SBarry Smith if (!w) { 36368e69593SBarry Smith *found = PETSC_FALSE; 36468e69593SBarry Smith PetscFunctionReturn(0); 36568e69593SBarry Smith } 36668e69593SBarry Smith *found = PETSC_TRUE; 3679566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(value,v+1,PetscMin((size_t)(w-v),valuelen))); 36868e69593SBarry Smith PetscFunctionReturn(0); 36968e69593SBarry Smith } 3705dc0f0a4SBarry Smith 3715dc0f0a4SBarry Smith #include <ctype.h> 3725dc0f0a4SBarry Smith 3734683183fSBarry Smith /*@C 3744683183fSBarry Smith PetscPushJSONValue - Puts a "key" : "value" pair onto a string 3755dc0f0a4SBarry Smith 3764683183fSBarry Smith Input Parameters: 3774683183fSBarry Smith + buffer - the char array where the value will be put 3784683183fSBarry Smith . key - the key value to be set 3794683183fSBarry Smith . value - the value associated with the key 3804683183fSBarry Smith - bufflen - the size of the buffer (currently ignored) 3814683183fSBarry Smith 3824683183fSBarry Smith Level: advanced 3834683183fSBarry Smith 38495452b02SPatrick Sanan Notes: 38595452b02SPatrick Sanan Ignores lengths so can cause buffer overflow 3864683183fSBarry Smith @*/ 3875dc0f0a4SBarry Smith PetscErrorCode PetscPushJSONValue(char buff[],const char key[],const char value[],size_t bufflen) 3885dc0f0a4SBarry Smith { 3895dc0f0a4SBarry Smith size_t len; 3905dc0f0a4SBarry Smith PetscBool special; 3915dc0f0a4SBarry Smith 3925dc0f0a4SBarry Smith PetscFunctionBegin; 3939566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(value,"null",&special)); 3945dc0f0a4SBarry Smith if (!special) { 3959566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(value,"true",&special)); 3965dc0f0a4SBarry Smith } 3975dc0f0a4SBarry Smith if (!special) { 3989566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(value,"false",&special)); 3995dc0f0a4SBarry Smith } 4005dc0f0a4SBarry Smith if (!special) { 4015dc0f0a4SBarry Smith PetscInt i; 4025dc0f0a4SBarry Smith 4039566063dSJacob Faibussowitsch PetscCall(PetscStrlen(value,&len)); 4045dc0f0a4SBarry Smith special = PETSC_TRUE; 4055dc0f0a4SBarry Smith for (i=0; i<(int)len; i++) { 4065dc0f0a4SBarry Smith if (!isdigit(value[i])) { 4075dc0f0a4SBarry Smith special = PETSC_FALSE; 4085dc0f0a4SBarry Smith break; 4095dc0f0a4SBarry Smith } 4105dc0f0a4SBarry Smith } 4115dc0f0a4SBarry Smith } 4125dc0f0a4SBarry Smith 4139566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buff,"\"")); 4149566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buff,key)); 4159566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buff,"\":")); 4165dc0f0a4SBarry Smith if (!special) { 4179566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buff,"\"")); 4185dc0f0a4SBarry Smith } 4199566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buff,value)); 4205dc0f0a4SBarry Smith if (!special) { 4219566063dSJacob Faibussowitsch PetscCall(PetscStrcat(buff,"\"")); 4225dc0f0a4SBarry Smith } 4235dc0f0a4SBarry Smith PetscFunctionReturn(0); 4245dc0f0a4SBarry Smith } 425