1 2 #include <petscwebclient.h> 3 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 4 #pragma gcc diagnostic ignored "-Wdeprecated-declarations" 5 6 /* 7 These variables identify the code as a PETSc application to Google. 8 9 See - http://stackoverflow.com/questions/4616553/using-oauth-in-free-open-source-software 10 Users can get their own application IDs - https://code.google.com/p/google-apps-manager/wiki/GettingAnOAuthConsoleKey 11 12 */ 13 #define PETSC_GOOGLE_CLIENT_ID "521429262559-i19i57eek8tnt9ftpp4p91rcl0bo9ag5.apps.googleusercontent.com" 14 #define PETSC_GOOGLE_CLIENT_ST "vOds_A71I3_S_aHMq_kZAI0t" 15 #define PETSC_GOOGLE_API_KEY "AIzaSyDRZsOcySpWVzsUvIBL2UG3J2tcg-MXbyk" 16 17 18 #undef __FUNCT__ 19 #define __FUNCT__ "PetscGoogleDriveRefresh" 20 /*@C 21 PetscGoogleDriveRefresh - Get a new authorization token for accessing Google drive from PETSc from a refresh token 22 23 Not collective, only the first process in the MPI_Comm does anything 24 25 Input Parameters: 26 + comm - MPI communicator 27 . refresh token - obtained with PetscGoogleDriveAuthorize(), if NULL PETSc will first look for one in the options data 28 if not found it will call PetscGoogleDriveAuthorize() 29 - tokensize - size of the output string access_token 30 31 Output Parameter: 32 . access_token - token that can be passed to PetscGoogleDriveUpload() 33 34 Options Database: 35 . -google_refresh_token XXX where XXX was obtained from PetscGoogleDriveAuthorize() 36 37 Level: intermediate 38 39 .seealso: PetscURLShorten(), PetscGoogleDriveAuthorize(), PetscGoogleDriveUpload() 40 41 @*/ 42 PetscErrorCode PetscGoogleDriveRefresh(MPI_Comm comm,const char refresh_token[],char access_token[],size_t tokensize) 43 { 44 SSL_CTX *ctx; 45 SSL *ssl; 46 int sock; 47 PetscErrorCode ierr; 48 char buff[8*1024],body[1024]; 49 PetscMPIInt rank; 50 char *refreshtoken = (char*)refresh_token; 51 PetscBool found; 52 53 PetscFunctionBegin; 54 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 55 if (!rank) { 56 if (!refresh_token) { 57 PetscBool set; 58 ierr = PetscMalloc1(512,&refreshtoken);CHKERRQ(ierr); 59 ierr = PetscOptionsGetString(NULL,NULL,"-google_refresh_token",refreshtoken,512,&set);CHKERRQ(ierr); 60 if (!set) { 61 ierr = PetscGoogleDriveAuthorize(comm,access_token,refreshtoken,512*sizeof(char));CHKERRQ(ierr); 62 ierr = PetscFree(refreshtoken);CHKERRQ(ierr); 63 PetscFunctionReturn(0); 64 } 65 } 66 ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 67 ierr = PetscHTTPSConnect("accounts.google.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 68 ierr = PetscStrcpy(body,"client_id=");CHKERRQ(ierr); 69 ierr = PetscStrcat(body,PETSC_GOOGLE_CLIENT_ID);CHKERRQ(ierr); 70 ierr = PetscStrcat(body,"&client_secret=");CHKERRQ(ierr); 71 ierr = PetscStrcat(body,PETSC_GOOGLE_CLIENT_ST);CHKERRQ(ierr); 72 ierr = PetscStrcat(body,"&refresh_token=");CHKERRQ(ierr); 73 ierr = PetscStrcat(body,refreshtoken);CHKERRQ(ierr); 74 if (!refresh_token) {ierr = PetscFree(refreshtoken);CHKERRQ(ierr);} 75 ierr = PetscStrcat(body,"&grant_type=refresh_token");CHKERRQ(ierr); 76 77 ierr = PetscHTTPSRequest("POST","accounts.google.com/o/oauth2/token",NULL,"application/x-www-form-urlencoded",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 78 ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 79 close(sock); 80 81 ierr = PetscPullJSONValue(buff,"access_token",access_token,tokensize,&found);CHKERRQ(ierr); 82 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Google drive did not return access_token"); 83 } 84 PetscFunctionReturn(0); 85 } 86 87 #include <sys/stat.h> 88 89 #undef __FUNCT__ 90 #define __FUNCT__ "PetscGoogleDriveUpload" 91 /*@C 92 PetscGoogleDriveUpload - Loads a file to the Google Drive 93 94 Not collective, only the first process in the MPI_Comm uploads the file 95 96 Input Parameters: 97 + comm - MPI communicator 98 . access_token - obtained with PetscGoogleDriveRefresh(), pass NULL to have PETSc generate one 99 - filename - file to upload; if you upload multiple times it will have different names each time on Google Drive 100 101 Options Database: 102 . -google_refresh_token XXX 103 104 Usage Patterns: 105 With PETSc option -google_refresh_token XXX given 106 PetscGoogleDriveUpload(comm,NULL,filename); will upload file with no user interaction 107 108 Without PETSc option -google_refresh_token XXX given 109 PetscGoogleDriveUpload(comm,NULL,filename); for first use will prompt user to authorize access to Google Drive with their browser 110 111 With PETSc option -google_refresh_token XXX given 112 PetscGoogleDriveRefresh(comm,NULL,access_token,sizeof(access_token)); 113 PetscGoogleDriveUpload(comm,access_token,filename); 114 115 With refresh token entered in some way by the user 116 PetscGoogleDriveRefresh(comm,refresh_token,access_token,sizeof(access_token)); 117 PetscGoogleDriveUpload(comm,access_token,filename); 118 119 PetscGoogleDriveAuthorize(comm,access_token,refresh_token,sizeof(access_token)); 120 PetscGoogleDriveUpload(comm,access_token,filename); 121 122 Level: intermediate 123 124 .seealso: PetscURLShorten(), PetscGoogleDriveAuthorize(), PetscGoogleDriveRefresh() 125 126 @*/ 127 PetscErrorCode PetscGoogleDriveUpload(MPI_Comm comm,const char access_token[],const char filename[]) 128 { 129 SSL_CTX *ctx; 130 SSL *ssl; 131 int sock; 132 PetscErrorCode ierr; 133 char head[1024],buff[8*1024],*body,*title; 134 PetscMPIInt rank; 135 struct stat sb; 136 size_t len,blen,rd; 137 FILE *fd; 138 139 PetscFunctionBegin; 140 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 141 if (!rank) { 142 ierr = PetscStrcpy(head,"Authorization: Bearer ");CHKERRQ(ierr); 143 ierr = PetscStrcat(head,access_token);CHKERRQ(ierr); 144 ierr = PetscStrcat(head,"\r\n");CHKERRQ(ierr); 145 ierr = PetscStrcat(head,"uploadType: multipart\r\n");CHKERRQ(ierr); 146 147 ierr = stat(filename,&sb); 148 if (ierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to stat file: %s",filename); 149 len = 1024 + sb.st_size; 150 ierr = PetscMalloc1(len,&body);CHKERRQ(ierr); 151 ierr = PetscStrcpy(body,"--foo_bar_baz\r\n" 152 "Content-Type: application/json\r\n\r\n" 153 "{");CHKERRQ(ierr); 154 ierr = PetscPushJSONValue(body,"title",filename,len);CHKERRQ(ierr); 155 ierr = PetscStrcat(body,",");CHKERRQ(ierr); 156 ierr = PetscPushJSONValue(body,"mimeType","text.html",len);CHKERRQ(ierr); 157 ierr = PetscStrcat(body,",");CHKERRQ(ierr); 158 ierr = PetscPushJSONValue(body,"description","a file",len);CHKERRQ(ierr); 159 ierr = PetscStrcat(body,"}\r\n\r\n" 160 "--foo_bar_baz\r\n" 161 "Content-Type: text/html\r\n\r\n");CHKERRQ(ierr); 162 ierr = PetscStrlen(body,&blen);CHKERRQ(ierr); 163 fd = fopen (filename, "r"); 164 if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file: %s",filename); 165 rd = fread (body+blen, sizeof (unsigned char), sb.st_size, fd); 166 if (rd != (size_t) 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); 167 fclose(fd); 168 body[blen + rd] = 0; 169 ierr = PetscStrcat(body,"\r\n\r\n" 170 "--foo_bar_baz\r\n");CHKERRQ(ierr); 171 ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 172 ierr = PetscHTTPSConnect("www.googleapis.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 173 ierr = PetscHTTPSRequest("POST","www.googleapis.com/upload/drive/v2/files/",head,"multipart/related; boundary=\"foo_bar_baz\"",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 174 ierr = PetscFree(body);CHKERRQ(ierr); 175 ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 176 close(sock); 177 ierr = PetscStrstr(buff,"\"title\"",&title);CHKERRQ(ierr); 178 if (!title) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Upload of file %s failed",filename); 179 } 180 PetscFunctionReturn(0); 181 } 182 183 #if defined(PETSC_HAVE_UNISTD_H) 184 #include <unistd.h> 185 #endif 186 187 #undef __FUNCT__ 188 #define __FUNCT__ "PetscGoogleDriveAuthorize" 189 /*@C 190 PetscGoogleDriveAuthorize - Get authorization and refresh token for accessing Google drive from PETSc 191 192 Not collective, only the first process in MPI_Comm does anything 193 194 Input Parameters: 195 + comm - the MPI communicator 196 - tokensize - size of the token arrays 197 198 Output Parameters: 199 + access_token - can be used with PetscGoogleDriveUpload() for this one session 200 - refresh_token - can be used for ever to obtain new access_tokens with PetscGoogleDriveRefresh(), guard this like a password 201 it gives access to your Google Drive 202 203 Notes: This call requires stdout and stdin access from process 0 on the MPI communicator 204 205 You can run src/sys/webclient/examples/tutorials/googleobtainrefreshtoken to get a refresh token and then in the future pass it to 206 PETSc programs with -google_refresh_token XXX 207 208 Level: intermediate 209 210 .seealso: PetscGoogleDriveRefresh(), PetscGoogleDriveUpload(), PetscURLShorten() 211 212 @*/ 213 PetscErrorCode PetscGoogleDriveAuthorize(MPI_Comm comm,char access_token[],char refresh_token[],size_t tokensize) 214 { 215 SSL_CTX *ctx; 216 SSL *ssl; 217 int sock; 218 PetscErrorCode ierr; 219 char buff[8*1024],*ptr,body[1024]; 220 PetscMPIInt rank; 221 size_t len; 222 PetscBool found; 223 224 PetscFunctionBegin; 225 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 226 if (!rank) { 227 if (!isatty(fileno(PETSC_STDOUT))) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Requires users input/output"); 228 ierr = PetscPrintf(comm,"Cut and paste the following into your browser:\n\n" 229 "https://accounts.google.com/o/oauth2/auth?" 230 "scope=https%%3A%%2F%%2Fwww.googleapis.com%%2Fauth%%2Fdrive.file&" 231 "redirect_uri=urn:ietf:wg:oauth:2.0:oob&" 232 "response_type=code&" 233 "client_id=" 234 PETSC_GOOGLE_CLIENT_ID 235 "\n\n");CHKERRQ(ierr); 236 ierr = PetscPrintf(comm,"Paste the result here:");CHKERRQ(ierr); 237 ptr = fgets(buff, 1024, stdin); 238 if (!ptr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from stdin: %d", errno); 239 ierr = PetscStrlen(buff,&len);CHKERRQ(ierr); 240 buff[len-1] = 0; /* remove carriage return at end of line */ 241 242 ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 243 ierr = PetscHTTPSConnect("accounts.google.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 244 ierr = PetscStrcpy(body,"code=");CHKERRQ(ierr); 245 ierr = PetscStrcat(body,buff);CHKERRQ(ierr); 246 ierr = PetscStrcat(body,"&client_id=");CHKERRQ(ierr); 247 ierr = PetscStrcat(body,PETSC_GOOGLE_CLIENT_ID);CHKERRQ(ierr); 248 ierr = PetscStrcat(body,"&client_secret=");CHKERRQ(ierr); 249 ierr = PetscStrcat(body,PETSC_GOOGLE_CLIENT_ST);CHKERRQ(ierr); 250 ierr = PetscStrcat(body,"&redirect_uri=urn:ietf:wg:oauth:2.0:oob&");CHKERRQ(ierr); 251 ierr = PetscStrcat(body,"grant_type=authorization_code");CHKERRQ(ierr); 252 253 ierr = PetscHTTPSRequest("POST","accounts.google.com/o/oauth2/token",NULL,"application/x-www-form-urlencoded",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 254 ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 255 close(sock); 256 257 ierr = PetscPullJSONValue(buff,"access_token",access_token,tokensize,&found);CHKERRQ(ierr); 258 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Google drive did not return access_token"); 259 ierr = PetscPullJSONValue(buff,"refresh_token",refresh_token,tokensize,&found);CHKERRQ(ierr); 260 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Google drive did not return refresh_token"); 261 262 ierr = PetscPrintf(comm,"Here is your Google refresh token, save it in a save place, in the future you can run PETSc\n");CHKERRQ(ierr); 263 ierr = PetscPrintf(comm,"programs with the option -google_refresh_token %s\n",refresh_token);CHKERRQ(ierr); 264 ierr = PetscPrintf(comm,"to access Google Drive automatically\n");CHKERRQ(ierr); 265 } 266 PetscFunctionReturn(0); 267 } 268 269 270 #undef __FUNCT__ 271 #define __FUNCT__ "PetscURLShorten" 272 /*@C 273 PetscURLShorten - Uses Google's service to get a short url for a long url 274 275 Input Parameters: 276 + url - long URL you want shortened 277 - lenshorturl - length of buffer to contain short URL 278 279 Output Parameter: 280 . shorturl - the shortened URL 281 282 Level: intermediate 283 284 .seealso: PetscGoogleDriveRefresh(), PetscGoogleDriveUpload(), PetscGoogleDriveAuthorize() 285 @*/ 286 PetscErrorCode PetscURLShorten(const char url[],char shorturl[],size_t lenshorturl) 287 { 288 SSL_CTX *ctx; 289 SSL *ssl; 290 int sock; 291 PetscErrorCode ierr; 292 char buff[1024],body[512],post[1024]; 293 PetscBool found; 294 295 PetscFunctionBegin; 296 ierr = PetscSSLInitializeContext(&ctx);CHKERRQ(ierr); 297 ierr = PetscHTTPSConnect("www.googleapis.com",443,ctx,&sock,&ssl);CHKERRQ(ierr); 298 ierr = PetscStrcpy(body,"{");CHKERRQ(ierr); 299 ierr = PetscPushJSONValue(body,"longUrl",url,sizeof(body)-2);CHKERRQ(ierr); 300 ierr = PetscStrcat(body,"}");CHKERRQ(ierr); 301 ierr = PetscSNPrintf(post,sizeof(post),"www.googleapis.com/urlshortener/v1/url?key=%s",PETSC_GOOGLE_API_KEY);CHKERRQ(ierr); 302 ierr = PetscHTTPSRequest("POST",post,NULL,"application/json",body,ssl,buff,sizeof(buff));CHKERRQ(ierr); 303 ierr = PetscSSLDestroyContext(ctx);CHKERRQ(ierr); 304 close(sock); 305 306 ierr = PetscPullJSONValue(buff,"id",shorturl,lenshorturl,&found);CHKERRQ(ierr); 307 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Google drive did not return short URL"); 308 PetscFunctionReturn(0); 309 } 310 311