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