1*b967cddfSBarry Smith 2*b967cddfSBarry Smith #include <petscsys.h> 3*b967cddfSBarry Smith #include <errno.h> 4*b967cddfSBarry Smith #include <sys/types.h> 5*b967cddfSBarry Smith #include <sys/socket.h> 6*b967cddfSBarry Smith #include <netinet/in.h> 7*b967cddfSBarry Smith #include <netinet/tcp.h> 8*b967cddfSBarry Smith #include <netdb.h> 9*b967cddfSBarry Smith #include <fcntl.h> 10*b967cddfSBarry Smith #include <signal.h> 11*b967cddfSBarry Smith #include <unistd.h> 12*b967cddfSBarry Smith #include <string.h> 13*b967cddfSBarry Smith 14*b967cddfSBarry Smith #include <openssl/ssl.h> 15*b967cddfSBarry Smith #include <openssl/err.h> 16*b967cddfSBarry Smith 17*b967cddfSBarry Smith static BIO *bio_err = NULL; 18*b967cddfSBarry Smith 19*b967cddfSBarry Smith #define PASSWORD "password" 20*b967cddfSBarry Smith 21*b967cddfSBarry Smith #if defined(PETSC_USE_CERTIFICATE) 22*b967cddfSBarry Smith static int password_cb(char *buf,int num, int rwflag,void *userdata) 23*b967cddfSBarry Smith { 24*b967cddfSBarry Smith if (num < strlen(PASSWORD)+1) return(0); 25*b967cddfSBarry Smith strcpy(buf,PASSWORD); 26*b967cddfSBarry Smith return(strlen(PASSWORD)); 27*b967cddfSBarry Smith } 28*b967cddfSBarry Smith #endif 29*b967cddfSBarry Smith 30*b967cddfSBarry Smith static void sigpipe_handle(int x) 31*b967cddfSBarry Smith { 32*b967cddfSBarry Smith } 33*b967cddfSBarry Smith 34*b967cddfSBarry Smith #undef __FUNCT__ 35*b967cddfSBarry Smith #define __FUNCT__ "PetscSSLInitializeContext" 36*b967cddfSBarry Smith /* 37*b967cddfSBarry Smith PetscSSLInitializeContext - Set up an SSL context suitable for initiating HTTPS requests. 38*b967cddfSBarry Smith 39*b967cddfSBarry Smith If built with PETSC_USE_CERTIFICATE requires the user have created a self-signed certificate with 40*b967cddfSBarry Smith 41*b967cddfSBarry Smith $ ./CA.pl -newcert (using the passphrase of password) 42*b967cddfSBarry Smith $ cat newkey.pem newcert.pem > sslclient.pem 43*b967cddfSBarry Smith 44*b967cddfSBarry Smith and put the resulting file in either the current directory (with the application) or in the home directory. This seems kind of 45*b967cddfSBarry Smith silly but it was all I could figure out. 46*b967cddfSBarry Smith 47*b967cddfSBarry Smith */ 48*b967cddfSBarry Smith PetscErrorCode PetscSSLInitializeContext(SSL_CTX **octx) 49*b967cddfSBarry Smith { 50*b967cddfSBarry Smith SSL_METHOD *meth; 51*b967cddfSBarry Smith SSL_CTX *ctx; 52*b967cddfSBarry Smith #if defined(PETSC_USE_CERTIFICATE) 53*b967cddfSBarry Smith char keyfile[PETSC_MAX_PATH_LEN]; 54*b967cddfSBarry Smith PetscBool exists; 55*b967cddfSBarry Smith PetscErrorCode ierr; 56*b967cddfSBarry Smith #endif 57*b967cddfSBarry Smith 58*b967cddfSBarry Smith PetscFunctionBegin; 59*b967cddfSBarry Smith if (!bio_err){ 60*b967cddfSBarry Smith SSL_library_init(); 61*b967cddfSBarry Smith SSL_load_error_strings(); 62*b967cddfSBarry Smith bio_err = BIO_new_fp(stderr,BIO_NOCLOSE); 63*b967cddfSBarry Smith } 64*b967cddfSBarry Smith 65*b967cddfSBarry Smith /* Set up a SIGPIPE handler */ 66*b967cddfSBarry Smith signal(SIGPIPE,sigpipe_handle); 67*b967cddfSBarry Smith 68*b967cddfSBarry Smith meth = SSLv23_method(); 69*b967cddfSBarry Smith ctx = SSL_CTX_new(meth); 70*b967cddfSBarry Smith 71*b967cddfSBarry Smith #if defined(PETSC_USE_CERTIFICATE) 72*b967cddfSBarry Smith /* Locate keyfile */ 73*b967cddfSBarry Smith ierr = PetscStrcpy(keyfile,"sslclient.pem");CHKERRQ(ierr); 74*b967cddfSBarry Smith ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr); 75*b967cddfSBarry Smith if (!exists) { 76*b967cddfSBarry Smith ierr = PetscGetHomeDirectory(keyfile,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 77*b967cddfSBarry Smith ierr = PetscStrcat(keyfile,"/");CHKERRQ(ierr); 78*b967cddfSBarry Smith ierr = PetscStrcat(keyfile,"sslclient.pem");CHKERRQ(ierr); 79*b967cddfSBarry Smith ierr = PetscTestFile(keyfile,'r',&exists);CHKERRQ(ierr); 80*b967cddfSBarry Smith if (!exists) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate sslclient.pem file in current directory or home directory"); 81*b967cddfSBarry Smith } 82*b967cddfSBarry Smith 83*b967cddfSBarry Smith /* Load our keys and certificates*/ 84*b967cddfSBarry Smith if (!(SSL_CTX_use_certificate_chain_file(ctx,keyfile))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read certificate file"); 85*b967cddfSBarry Smith 86*b967cddfSBarry Smith SSL_CTX_set_default_passwd_cb(ctx,password_cb); 87*b967cddfSBarry Smith if (!(SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot read key file"); 88*b967cddfSBarry Smith #endif 89*b967cddfSBarry Smith 90*b967cddfSBarry Smith *octx = ctx; 91*b967cddfSBarry Smith PetscFunctionReturn(0); 92*b967cddfSBarry Smith } 93*b967cddfSBarry Smith 94*b967cddfSBarry Smith #undef __FUNCT__ 95*b967cddfSBarry Smith #define __FUNCT__ "PetscSSLDestroyContext" 96*b967cddfSBarry Smith PetscErrorCode PetscSSLDestroyContext(SSL_CTX *ctx) 97*b967cddfSBarry Smith { 98*b967cddfSBarry Smith PetscFunctionBegin; 99*b967cddfSBarry Smith SSL_CTX_free(ctx); 100*b967cddfSBarry Smith PetscFunctionReturn(0); 101*b967cddfSBarry Smith } 102*b967cddfSBarry Smith 103*b967cddfSBarry Smith #undef __FUNCT__ 104*b967cddfSBarry Smith #define __FUNCT__ "PetscHTTPSRequest" 105*b967cddfSBarry Smith /* 106*b967cddfSBarry Smith PetscHTTPSRequest - Send a request to an HTTPS server 107*b967cddfSBarry Smith 108*b967cddfSBarry Smith Input Parameters: 109*b967cddfSBarry Smith + type - either "POST" or "GET" 110*b967cddfSBarry Smith . url - complete URL of request including https:// 111*b967cddfSBarry Smith . header - additional header information, may be NULL 112*b967cddfSBarry Smith . ctype - data type of body, for example application/json 113*b967cddfSBarry Smith . body - data to send to server 114*b967cddfSBarry Smith . ssl - obtained with PetscHTTPSConnect() 115*b967cddfSBarry Smith - buffsize - size of buffer 116*b967cddfSBarry Smith 117*b967cddfSBarry Smith Output Parameter: 118*b967cddfSBarry Smith . buff - everything returned from server 119*b967cddfSBarry Smith */ 120*b967cddfSBarry Smith static PetscErrorCode PetscHTTPSRequest(const char type[],const char url[],const char header[],const char ctype[],const char body[],SSL *ssl,char buff[],size_t buffsize) 121*b967cddfSBarry Smith { 122*b967cddfSBarry Smith char *request=0; 123*b967cddfSBarry Smith char contentlength[40],contenttype[80]; 124*b967cddfSBarry Smith int r; 125*b967cddfSBarry Smith size_t request_len,len,headlen,bodylen,contentlen,urllen,typelen,contenttypelen = 0; 126*b967cddfSBarry Smith PetscErrorCode ierr; 127*b967cddfSBarry Smith PetscBool flg; 128*b967cddfSBarry Smith 129*b967cddfSBarry Smith PetscFunctionBegin; 130*b967cddfSBarry Smith ierr = PetscStrbeginswith(url,"https://",&flg);CHKERRQ(ierr); 131*b967cddfSBarry Smith if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"URL must begin with https://"); 132*b967cddfSBarry Smith if (header) { 133*b967cddfSBarry Smith ierr = PetscStrendswith(header,"\r\n",&flg);CHKERRQ(ierr); 134*b967cddfSBarry Smith if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"header must end with \\r\\n"); 135*b967cddfSBarry Smith } 136*b967cddfSBarry Smith 137*b967cddfSBarry Smith ierr = PetscStrlen(type,&typelen);CHKERRQ(ierr); 138*b967cddfSBarry Smith ierr = PetscStrlen(url,&urllen);CHKERRQ(ierr); 139*b967cddfSBarry Smith if (ctype) { 140*b967cddfSBarry Smith ierr = PetscSNPrintf(contenttype,80,"Content-Type: %s\r\n",ctype);CHKERRQ(ierr); 141*b967cddfSBarry Smith ierr = PetscStrlen(contenttype,&contenttypelen);CHKERRQ(ierr); 142*b967cddfSBarry Smith } 143*b967cddfSBarry Smith ierr = PetscStrlen(header,&headlen);CHKERRQ(ierr); 144*b967cddfSBarry Smith ierr = PetscStrlen(body,&bodylen);CHKERRQ(ierr); 145*b967cddfSBarry Smith ierr = PetscSNPrintf(contentlength,40,"Content-Length: %d\r\n\r\n",(int)bodylen);CHKERRQ(ierr); 146*b967cddfSBarry Smith ierr = PetscStrlen(contentlength,&contentlen);CHKERRQ(ierr); 147*b967cddfSBarry Smith 148*b967cddfSBarry Smith /* Now construct our HTTP request */ 149*b967cddfSBarry Smith request_len = typelen + 1 + urllen + 35 + headlen + contenttypelen + contentlen + bodylen + 1; 150*b967cddfSBarry Smith ierr = PetscMalloc(request_len*sizeof(char),&request);CHKERRQ(ierr); 151*b967cddfSBarry Smith ierr = PetscStrcpy(request,type);CHKERRQ(ierr); 152*b967cddfSBarry Smith ierr = PetscStrcat(request," ");CHKERRQ(ierr); 153*b967cddfSBarry Smith ierr = PetscStrcat(request,url);CHKERRQ(ierr); 154*b967cddfSBarry Smith ierr = PetscStrcat(request," HTTP/1.1\r\nUser-Agent:PETScClient\r\n");CHKERRQ(ierr); 155*b967cddfSBarry Smith ierr = PetscStrcat(request,header);CHKERRQ(ierr); 156*b967cddfSBarry Smith if (ctype) { 157*b967cddfSBarry Smith ierr = PetscStrcat(request,contenttype);CHKERRQ(ierr); 158*b967cddfSBarry Smith } 159*b967cddfSBarry Smith ierr = PetscStrcat(request,contentlength);CHKERRQ(ierr); 160*b967cddfSBarry Smith ierr = PetscStrcat(request,body);CHKERRQ(ierr); 161*b967cddfSBarry Smith ierr = PetscStrlen(request,&request_len);CHKERRQ(ierr); 162*b967cddfSBarry Smith ierr = PetscInfo1(NULL,"HTTPS request follows: \n%s\n",request);CHKERRQ(ierr); 163*b967cddfSBarry Smith 164*b967cddfSBarry Smith r = SSL_write(ssl,request,request_len); 165*b967cddfSBarry Smith switch (SSL_get_error(ssl,r)){ 166*b967cddfSBarry Smith case SSL_ERROR_NONE: 167*b967cddfSBarry Smith if (request_len != r) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Incomplete write to SSL socket"); 168*b967cddfSBarry Smith break; 169*b967cddfSBarry Smith default: 170*b967cddfSBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL socket write problem"); 171*b967cddfSBarry Smith } 172*b967cddfSBarry Smith 173*b967cddfSBarry Smith /* Now read the server's response, assuming that it's terminated by a close */ 174*b967cddfSBarry Smith r = SSL_read(ssl,buff,(int)buffsize); 175*b967cddfSBarry Smith len = r; 176*b967cddfSBarry Smith switch (SSL_get_error(ssl,r)){ 177*b967cddfSBarry Smith case SSL_ERROR_NONE: 178*b967cddfSBarry Smith break; 179*b967cddfSBarry Smith case SSL_ERROR_ZERO_RETURN: 180*b967cddfSBarry Smith SSL_shutdown(ssl); /* ignore shutdown error message */ 181*b967cddfSBarry Smith break; 182*b967cddfSBarry Smith case SSL_ERROR_SYSCALL: 183*b967cddfSBarry Smith break; 184*b967cddfSBarry Smith default: 185*b967cddfSBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL read problem"); 186*b967cddfSBarry Smith } 187*b967cddfSBarry Smith buff[len] = 0; /* null terminate string */ 188*b967cddfSBarry Smith ierr = PetscInfo1(NULL,"HTTPS result follows: \n%s\n",buff);CHKERRQ(ierr); 189*b967cddfSBarry Smith 190*b967cddfSBarry Smith SSL_free(ssl); 191*b967cddfSBarry Smith ierr = PetscFree(request);CHKERRQ(ierr); 192*b967cddfSBarry Smith PetscFunctionReturn(0); 193*b967cddfSBarry Smith } 194*b967cddfSBarry Smith 195*b967cddfSBarry Smith #undef __FUNCT__ 196*b967cddfSBarry Smith #define __FUNCT__ "PetscHTTPSConnect" 197*b967cddfSBarry Smith PetscErrorCode PetscHTTPSConnect(const char host[],int port,SSL_CTX *ctx,int *sock,SSL **ssl) 198*b967cddfSBarry Smith { 199*b967cddfSBarry Smith BIO *sbio; 200*b967cddfSBarry Smith PetscErrorCode ierr; 201*b967cddfSBarry Smith 202*b967cddfSBarry Smith PetscFunctionBegin; 203*b967cddfSBarry Smith /* Connect the TCP socket*/ 204*b967cddfSBarry Smith ierr = PetscOpenSocket(host,port,sock);CHKERRQ(ierr); 205*b967cddfSBarry Smith 206*b967cddfSBarry Smith /* Connect the SSL socket */ 207*b967cddfSBarry Smith *ssl = SSL_new(ctx); 208*b967cddfSBarry Smith sbio = BIO_new_socket(*sock,BIO_NOCLOSE); 209*b967cddfSBarry Smith SSL_set_bio(*ssl,sbio,sbio); 210*b967cddfSBarry Smith if (SSL_connect(*ssl) <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SSL connect error"); 211*b967cddfSBarry Smith PetscFunctionReturn(0); 212*b967cddfSBarry Smith } 213*b967cddfSBarry Smith 214*b967cddfSBarry Smith /* 215*b967cddfSBarry Smith This file is not included in the respository since it contains authorization secrets 216*b967cddfSBarry Smith */ 217*b967cddfSBarry Smith #include <../src/sys/webclient/authorization.h> 218*b967cddfSBarry Smith 219*b967cddfSBarry Smith #undef __FUNCT__ 220*b967cddfSBarry Smith #define __FUNCT__ "PetscGoogleDriveRefresh" 221*b967cddfSBarry Smith /*C 222*b967cddfSBarry Smith PetscGoogleDriveRefresh - Get a new authorization token for accessing Google drive from PETSc from a refresh token 223*b967cddfSBarry Smith 224*b967cddfSBarry Smith 225*b967cddfSBarry Smith */ 226*b967cddfSBarry Smith PetscErrorCode PetscGoogleDriveRefresh(MPI_Comm comm,const char refresh_token[],char access_token[],size_t tokensize) 227*b967cddfSBarry Smith { 228*b967cddfSBarry Smith SSL_CTX *ctx; 229*b967cddfSBarry Smith SSL *ssl; 230*b967cddfSBarry Smith int sock; 231*b967cddfSBarry Smith PetscErrorCode ierr; 232*b967cddfSBarry Smith char buff[8*1024],body[1024],*access,*ctmp; 233*b967cddfSBarry Smith PetscMPIInt rank; 234*b967cddfSBarry Smith 235*b967cddfSBarry Smith PetscFunctionBegin; 236*b967cddfSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 237*b967cddfSBarry Smith if (!rank) { 238*b967cddfSBarry Smith ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 239*b967cddfSBarry Smith ierr = PetscHTTPSConnect("accounts.google.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 240*b967cddfSBarry Smith ierr = PetscStrcpy(body,"&client_id=");CHKERRQ(ierr); 241*b967cddfSBarry Smith ierr = PetscStrcat(body,PETSC_CLIENT_ID);CHKERRQ(ierr); 242*b967cddfSBarry Smith ierr = PetscStrcat(body,"&client_secret=");CHKERRQ(ierr); 243*b967cddfSBarry Smith ierr = PetscStrcat(body,PETSC_CLIENT_SECRET);CHKERRQ(ierr); 244*b967cddfSBarry Smith ierr = PetscStrcat(body,"&refresh_token=");CHKERRQ(ierr); 245*b967cddfSBarry Smith ierr = PetscStrcat(body,refresh_token);CHKERRQ(ierr); 246*b967cddfSBarry Smith ierr = PetscStrcat(body,"&grant_type=refresh_token");CHKERRQ(ierr); 247*b967cddfSBarry Smith 248*b967cddfSBarry Smith ierr = PetscHTTPSRequest("POST","https://accounts.google.com/o/oauth2/token",NULL,"application/x-www-form-urlencoded",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 249*b967cddfSBarry Smith ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 250*b967cddfSBarry Smith close(sock); 251*b967cddfSBarry Smith 252*b967cddfSBarry Smith ierr = PetscStrstr(buff,"\"access_token\" : \"",&access);CHKERRQ(ierr); 253*b967cddfSBarry Smith if (!access) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Did not receive access token from Google"); 254*b967cddfSBarry Smith access += 18; 255*b967cddfSBarry Smith ierr = PetscStrchr(access,'\"',&ctmp);CHKERRQ(ierr); 256*b967cddfSBarry Smith if (!ctmp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Access token from Google is misformed"); 257*b967cddfSBarry Smith *ctmp = 0; 258*b967cddfSBarry Smith ierr = PetscStrncpy(access_token,access,tokensize);CHKERRQ(ierr); 259*b967cddfSBarry Smith *ctmp = '\"'; 260*b967cddfSBarry Smith } 261*b967cddfSBarry Smith PetscFunctionReturn(0); 262*b967cddfSBarry Smith } 263*b967cddfSBarry Smith 264*b967cddfSBarry Smith #include <sys/stat.h> 265*b967cddfSBarry Smith 266*b967cddfSBarry Smith #undef __FUNCT__ 267*b967cddfSBarry Smith #define __FUNCT__ "PetscGoogleDriveUpload" 268*b967cddfSBarry Smith /*@C 269*b967cddfSBarry Smith PetscGoogleDriveUpload - Loads a file to the google drive 270*b967cddfSBarry Smith 271*b967cddfSBarry Smith Not collective, only the first process in the MPI_Comm uploads the file 272*b967cddfSBarry Smith 273*b967cddfSBarry Smith Input Parameters: 274*b967cddfSBarry Smith + comm - MPI communicator 275*b967cddfSBarry Smith . access_token - obtained with PetscGoogleDriveRefresh() 276*b967cddfSBarry Smith - filename - file to upload; if you upload multiple times it will have different names each time on Google Drive 277*b967cddfSBarry Smith 278*b967cddfSBarry Smith @*/ 279*b967cddfSBarry Smith PetscErrorCode PetscGoogleDriveUpload(MPI_Comm comm,const char access_token[],const char filename[]) 280*b967cddfSBarry Smith { 281*b967cddfSBarry Smith SSL_CTX *ctx; 282*b967cddfSBarry Smith SSL *ssl; 283*b967cddfSBarry Smith int sock; 284*b967cddfSBarry Smith PetscErrorCode ierr; 285*b967cddfSBarry Smith char head[1024],buff[8*1024],*body,*title; 286*b967cddfSBarry Smith PetscMPIInt rank; 287*b967cddfSBarry Smith struct stat sb; 288*b967cddfSBarry Smith size_t len,blen,rd; 289*b967cddfSBarry Smith FILE *fd; 290*b967cddfSBarry Smith 291*b967cddfSBarry Smith PetscFunctionBegin; 292*b967cddfSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 293*b967cddfSBarry Smith if (!rank) { 294*b967cddfSBarry Smith ierr = PetscStrcpy(head,"Authorization: Bearer ");CHKERRQ(ierr); 295*b967cddfSBarry Smith ierr = PetscStrcat(head,access_token);CHKERRQ(ierr); 296*b967cddfSBarry Smith ierr = PetscStrcat(head,"\r\n");CHKERRQ(ierr); 297*b967cddfSBarry Smith ierr = PetscStrcat(head,"uploadType: multipart\r\n");CHKERRQ(ierr); 298*b967cddfSBarry Smith 299*b967cddfSBarry Smith ierr = stat(filename,&sb); 300*b967cddfSBarry Smith if (ierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to stat file: %s",filename); 301*b967cddfSBarry Smith len = 1024 + sb.st_size; 302*b967cddfSBarry Smith ierr = PetscMalloc(len*sizeof(char),&body);CHKERRQ(ierr); 303*b967cddfSBarry Smith ierr = PetscStrcpy(body,"--foo_bar_baz\r\n" 304*b967cddfSBarry Smith "Content-Type: application/json\r\n\r\n" 305*b967cddfSBarry Smith "{" 306*b967cddfSBarry Smith "\"title\": \""); 307*b967cddfSBarry Smith ierr = PetscStrcat(body,filename); 308*b967cddfSBarry Smith ierr = PetscStrcat(body,"\"," 309*b967cddfSBarry Smith "\"mimeType\": \"text.html\"," 310*b967cddfSBarry Smith "\"description\": \" a file\"" 311*b967cddfSBarry Smith "}\r\n\r\n" 312*b967cddfSBarry Smith "--foo_bar_baz\r\n" 313*b967cddfSBarry Smith "Content-Type: text/html\r\n\r\n"); 314*b967cddfSBarry Smith ierr = PetscStrlen(body,&blen);CHKERRQ(ierr); 315*b967cddfSBarry Smith fd = fopen (filename, "r"); 316*b967cddfSBarry Smith if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file: %s",filename); 317*b967cddfSBarry Smith rd = fread (body+blen, sizeof (unsigned char), sb.st_size, fd); 318*b967cddfSBarry Smith if (rd != sb.st_size) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to read entire file: %s %d %d",filename,(int)rd,sb.st_size); 319*b967cddfSBarry Smith fclose(fd); 320*b967cddfSBarry Smith body[blen + rd] = 0; 321*b967cddfSBarry Smith ierr = PetscStrcat(body,"\r\n\r\n" 322*b967cddfSBarry Smith "--foo_bar_baz\r\n"); 323*b967cddfSBarry Smith ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 324*b967cddfSBarry Smith ierr = PetscHTTPSConnect("www.googleapis.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 325*b967cddfSBarry Smith ierr = PetscHTTPSRequest("POST","https://www.googleapis.com/upload/drive/v2/files/",head,"multipart/related; boundary=\"foo_bar_baz\"",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 326*b967cddfSBarry Smith ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 327*b967cddfSBarry Smith close(sock); 328*b967cddfSBarry Smith ierr = PetscStrstr(buff,"\"title\"",&title);CHKERRQ(ierr); 329*b967cddfSBarry Smith if (!title) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Upload of file %s failed",filename); 330*b967cddfSBarry Smith } 331*b967cddfSBarry Smith PetscFunctionReturn(0); 332*b967cddfSBarry Smith } 333*b967cddfSBarry Smith 334*b967cddfSBarry Smith 335*b967cddfSBarry Smith #undef __FUNCT__ 336*b967cddfSBarry Smith #define __FUNCT__ "PetscGoogleDriveAuthorize" 337*b967cddfSBarry Smith /*C 338*b967cddfSBarry Smith PetscGoogleDriveAuthorize - Get authorization and refresh token for accessing Google drive from PETSc 339*b967cddfSBarry Smith 340*b967cddfSBarry Smith 341*b967cddfSBarry Smith */ 342*b967cddfSBarry Smith PetscErrorCode PetscGoogleDriveAuthorize(MPI_Comm comm,char access_token[],char refresh_token[],size_t tokensize) 343*b967cddfSBarry Smith { 344*b967cddfSBarry Smith SSL_CTX *ctx; 345*b967cddfSBarry Smith SSL *ssl; 346*b967cddfSBarry Smith int sock; 347*b967cddfSBarry Smith PetscErrorCode ierr; 348*b967cddfSBarry Smith char buff[8*1024],*ptr,body[1024],*access,*refresh,*ctmp; 349*b967cddfSBarry Smith PetscMPIInt rank; 350*b967cddfSBarry Smith size_t len; 351*b967cddfSBarry Smith 352*b967cddfSBarry Smith PetscFunctionBegin; 353*b967cddfSBarry Smith ierr = PetscPrintf(comm,"Cut and paste the following into your browser:\n" 354*b967cddfSBarry Smith "https://accounts.google.com/o/oauth2/auth?" 355*b967cddfSBarry Smith "scope=https%%3A%%2F%%2Fwww.googleapis.com%%2Fauth%%2Fdrive.file&" 356*b967cddfSBarry Smith "redirect_uri=urn:ietf:wg:oauth:2.0:oob&" 357*b967cddfSBarry Smith "response_type=code&" 358*b967cddfSBarry Smith "client_id=" 359*b967cddfSBarry Smith PETSC_CLIENT_ID 360*b967cddfSBarry Smith "\n\n");CHKERRQ(ierr); 361*b967cddfSBarry Smith ierr = PetscPrintf(comm,"Paste the result here:");CHKERRQ(ierr); 362*b967cddfSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 363*b967cddfSBarry Smith if (!rank) { 364*b967cddfSBarry Smith ptr = fgets(buff, 1024, stdin); 365*b967cddfSBarry Smith if (!ptr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno); 366*b967cddfSBarry Smith ierr = PetscStrlen(buff,&len);CHKERRQ(ierr); 367*b967cddfSBarry Smith buff[len-1] = 0; /* remove carriage return at end of line */ 368*b967cddfSBarry Smith 369*b967cddfSBarry Smith ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 370*b967cddfSBarry Smith ierr = PetscHTTPSConnect("accounts.google.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 371*b967cddfSBarry Smith ierr = PetscStrcpy(body,"code=");CHKERRQ(ierr); 372*b967cddfSBarry Smith ierr = PetscStrcat(body,buff);CHKERRQ(ierr); 373*b967cddfSBarry Smith ierr = PetscStrcat(body,"&client_id=");CHKERRQ(ierr); 374*b967cddfSBarry Smith ierr = PetscStrcat(body,PETSC_CLIENT_ID);CHKERRQ(ierr); 375*b967cddfSBarry Smith ierr = PetscStrcat(body,"&client_secret=");CHKERRQ(ierr); 376*b967cddfSBarry Smith ierr = PetscStrcat(body,PETSC_CLIENT_SECRET);CHKERRQ(ierr); 377*b967cddfSBarry Smith ierr = PetscStrcat(body,"&redirect_uri=urn:ietf:wg:oauth:2.0:oob&");CHKERRQ(ierr); 378*b967cddfSBarry Smith ierr = PetscStrcat(body,"grant_type=authorization_code");CHKERRQ(ierr); 379*b967cddfSBarry Smith 380*b967cddfSBarry Smith ierr = PetscHTTPSRequest("POST","https://accounts.google.com/o/oauth2/token",NULL,"application/x-www-form-urlencoded",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 381*b967cddfSBarry Smith ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 382*b967cddfSBarry Smith close(sock); 383*b967cddfSBarry Smith 384*b967cddfSBarry Smith ierr = PetscStrstr(buff,"\"access_token\" : \"",&access);CHKERRQ(ierr); 385*b967cddfSBarry Smith if (!access) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Did not receive access token from Google"); 386*b967cddfSBarry Smith access += 18; 387*b967cddfSBarry Smith ierr = PetscStrchr(access,'\"',&ctmp);CHKERRQ(ierr); 388*b967cddfSBarry Smith if (!ctmp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Access token from Google is misformed"); 389*b967cddfSBarry Smith *ctmp = 0; 390*b967cddfSBarry Smith ierr = PetscStrncpy(access_token,access,tokensize);CHKERRQ(ierr); 391*b967cddfSBarry Smith *ctmp = '\"'; 392*b967cddfSBarry Smith 393*b967cddfSBarry Smith ierr = PetscStrstr(buff,"\"refresh_token\" : \"",&refresh);CHKERRQ(ierr); 394*b967cddfSBarry Smith if (!refresh) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Did not receive refresh token from Google"); 395*b967cddfSBarry Smith refresh += 19; 396*b967cddfSBarry Smith ierr = PetscStrchr(refresh,'\"',&ctmp);CHKERRQ(ierr); 397*b967cddfSBarry Smith if (!ctmp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Refresh token from Google is misformed"); 398*b967cddfSBarry Smith *ctmp = 0; 399*b967cddfSBarry Smith ierr = PetscStrncpy(refresh_token,refresh,tokensize);CHKERRQ(ierr); 400*b967cddfSBarry Smith } 401*b967cddfSBarry Smith PetscFunctionReturn(0); 402*b967cddfSBarry Smith } 403*b967cddfSBarry Smith 404*b967cddfSBarry Smith 405*b967cddfSBarry Smith #undef __FUNCT__ 406*b967cddfSBarry Smith #define __FUNCT__ "PetscURLShorten" 407*b967cddfSBarry Smith /*@C 408*b967cddfSBarry Smith PetscURLShorten - Uses Google's service to get a short url for a long url 409*b967cddfSBarry Smith 410*b967cddfSBarry Smith Input Parameters: 411*b967cddfSBarry Smith + url - long URL you want shortened 412*b967cddfSBarry Smith - lenshorturl - length of buffer to contain short URL 413*b967cddfSBarry Smith 414*b967cddfSBarry Smith Output Parameter: 415*b967cddfSBarry Smith . shorturl - the shortened URL 416*b967cddfSBarry Smith 417*b967cddfSBarry Smith @*/ 418*b967cddfSBarry Smith PetscErrorCode PetscURLShorten(const char url[],char shorturl[],size_t lenshorturl) 419*b967cddfSBarry Smith { 420*b967cddfSBarry Smith SSL_CTX *ctx; 421*b967cddfSBarry Smith SSL *ssl; 422*b967cddfSBarry Smith int sock; 423*b967cddfSBarry Smith PetscErrorCode ierr; 424*b967cddfSBarry Smith char buff[1024],body[512],*sub1,*sub2; 425*b967cddfSBarry Smith 426*b967cddfSBarry Smith PetscFunctionBegin; 427*b967cddfSBarry Smith ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 428*b967cddfSBarry Smith ierr = PetscHTTPSConnect("www.googleapis.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 429*b967cddfSBarry Smith ierr = PetscSNPrintf(body,512,"{\"longUrl\": \"%s\"}",url);CHKERRQ(ierr); 430*b967cddfSBarry Smith ierr = PetscHTTPSRequest("POST","https://www.googleapis.com/urlshortener/v1/url",NULL,"application/json",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 431*b967cddfSBarry Smith ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 432*b967cddfSBarry Smith close(sock); 433*b967cddfSBarry Smith ierr = PetscStrstr(buff,"\"id\": \"",&sub1);CHKERRQ(ierr); 434*b967cddfSBarry Smith if (sub1) { 435*b967cddfSBarry Smith sub1 += 7; 436*b967cddfSBarry Smith ierr = PetscStrstr(sub1,"\"",&sub2);CHKERRQ(ierr); 437*b967cddfSBarry Smith if (!sub2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Google did not shorten URL"); 438*b967cddfSBarry Smith sub2[0] = 0; 439*b967cddfSBarry Smith ierr = PetscStrncpy(shorturl,sub1,lenshorturl);CHKERRQ(ierr); 440*b967cddfSBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Google did not shorten URL"); 441*b967cddfSBarry Smith PetscFunctionReturn(0); 442*b967cddfSBarry Smith } 443*b967cddfSBarry Smith 444