diff --git a/extensions/gdata/module/MOD-INF/controller.js b/extensions/gdata/module/MOD-INF/controller.js index 06ae8d700..25f069143 100644 --- a/extensions/gdata/module/MOD-INF/controller.js +++ b/extensions/gdata/module/MOD-INF/controller.js @@ -44,8 +44,6 @@ function init() { //Packages.java.lang.System.err.println(module.getMountPoint()); var RS = Packages.com.google.refine.RefineServlet; - RS.registerCommand(module, "authorize", Packages.com.google.refine.extension.gdata.AuthorizeCommand()); - RS.registerCommand(module, "authorize2", Packages.com.google.refine.extension.gdata.AuthorizeCommand2()); RS.registerCommand(module, "deauthorize", Packages.com.google.refine.extension.gdata.DeAuthorizeCommand()); RS.registerCommand(module, "upload", Packages.com.google.refine.extension.gdata.UploadCommand()); @@ -69,6 +67,7 @@ function init() { "index/scripts", module, [ + "scripts/gdata-extension.js", "scripts/index/importing-controller.js", "scripts/index/gdata-source-ui.js" ] @@ -87,6 +86,7 @@ function init() { "project/scripts", module, [ + "scripts/gdata-extension.js", "scripts/project/exporters.js" ] ); @@ -97,24 +97,32 @@ function init() { */ function process(path, request, response) { // Analyze path and handle this request yourself. - if (path == "authorized") { + if (path == "authorize") { var context = {}; - var params = new Packages.java.util.Properties(); - context.params = params; + context.authorizationUrl = Packages.com.google.refine.extension.gdata.GDataExtension.getAuthorizationUrl(module, request); - var queryString = request.getQueryString(); - if (queryString != null) { - var AuthSubUtil = Packages.com.google.gdata.client.http.AuthSubUtil; + send(request, response, "authorize.vt", context); + } else if (path == "authorized") { + var context = {}; + context.winname = request.getParameter("winname"); + context.callback = request.getParameter("callback"); + + (function() { + var queryString = request.getQueryString(); + if (queryString != null) { + var AuthSubUtil = Packages.com.google.gdata.client.http.AuthSubUtil; - // FIXME(SM): can we safely assume UTF-8 encoding here? - var onetimeUseToken = AuthSubUtil.getTokenFromReply( - Packages.java.net.URLDecoder.decode(queryString,"UTF-8")); - - var sessionToken = AuthSubUtil.exchangeForSessionToken(onetimeUseToken, null); - Packages.com.google.refine.extension.gdata.TokenCookie.setToken(request, response, sessionToken); - } else { + // FIXME(SM): can we safely assume UTF-8 encoding here? + var onetimeUseToken = AuthSubUtil.getTokenFromReply( + Packages.java.net.URLDecoder.decode(queryString, "UTF-8")); + if (onetimeUseToken) { + var sessionToken = AuthSubUtil.exchangeForSessionToken(onetimeUseToken, null); + Packages.com.google.refine.extension.gdata.TokenCookie.setToken(request, response, sessionToken); + return; + } + } Packages.com.google.refine.extension.gdata.TokenCookie.deleteToken(request, response); - } + })(); send(request, response, "authorized.vt", context); } diff --git a/extensions/gdata/module/scripts/project-injection.js b/extensions/gdata/module/authorize.vt similarity index 72% rename from extensions/gdata/module/scripts/project-injection.js rename to extensions/gdata/module/authorize.vt index c80382d76..2cf73f8be 100644 --- a/extensions/gdata/module/scripts/project-injection.js +++ b/extensions/gdata/module/authorize.vt @@ -1,6 +1,7 @@ -/* + + + + + + Google Refine - Authorization + + + + + diff --git a/extensions/gdata/module/authorized.vt b/extensions/gdata/module/authorized.vt index ca7e38267..8972e9594 100644 --- a/extensions/gdata/module/authorized.vt +++ b/extensions/gdata/module/authorized.vt @@ -34,28 +34,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Google Refine + Google Refine - Authorized - Closing... + Authorization process completed. Close this window and return to Google Refine. + diff --git a/extensions/gdata/module/scripts/gdata-extension.js b/extensions/gdata/module/scripts/gdata-extension.js new file mode 100644 index 000000000..d3fb83167 --- /dev/null +++ b/extensions/gdata/module/scripts/gdata-extension.js @@ -0,0 +1,62 @@ +/* + +Copyright 2010, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +var GdataExtension = {}; + +GdataExtension.isAuthorized = function() { + return $.cookie('authsub_token') !== null; +}; + +GdataExtension.showAuthorizationDialog = function(onAuthorized, onNotAuthorized) { + if (window.name) { + var windowName = window.name; + } else { + var windowName = "googlerefine" + new Date().getTime(); + window.name = windowName; + } + + var callbackName = "cb" + new Date().getTime(); + var callback = function(evt) { + delete window[callbackName]; + if (GdataExtension.isAuthorized()) { + onAuthorized(); + } else if (onNotAuthorized) { + onNotAuthorized(); + } + window.setTimeout(function() { win.close(); }, 100); + }; + window[callbackName] = callback; + + var url = ModuleWirings['gdata'] + "authorize?winname=" + escape(windowName) + "&callback=" + escape(callbackName); + var win = window.open(url, "googlerefinegdataauth", "resizable=1,width=800,height=600"); +}; diff --git a/extensions/gdata/module/scripts/index/gdata-source-ui.js b/extensions/gdata/module/scripts/index/gdata-source-ui.js index 1db6900aa..acd55b37c 100644 --- a/extensions/gdata/module/scripts/index/gdata-source-ui.js +++ b/extensions/gdata/module/scripts/index/gdata-source-ui.js @@ -33,19 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Refine.GDataSourceUI = function(controller) { this._controller = controller; - - var self = this; - window.addEventListener( - "message", - function(evt) { - if ($.cookie('authsub_token')) { - self._listDocuments(); - } else { - self._body.find('.gdata-page').hide(); - self._elmts.signinPage.show(); - } - }, - false); }; Refine.GDataSourceUI.prototype.attachUI = function(body) { @@ -54,18 +41,23 @@ Refine.GDataSourceUI.prototype.attachUI = function(body) { this._body.html(DOM.loadHTML("gdata", "scripts/index/import-from-gdata-form.html")); this._elmts = DOM.bind(this._body); + var self = this; this._body.find('.gdata-signin.button').click(function() { - window.open( - "/command/gdata/authorize", - "google-refine-gdata-signin", - "resizable=1,width=600,height=450" + GdataExtension.showAuthorizationDialog( + function() { + self._listDocuments(); + }, + function() { + self._body.find('.gdata-page').hide(); + self._elmts.signinPage.show(); + } ); }); this._body.find('.gdata-page').hide(); this._elmts.signinPage.show(); - if ($.cookie('authsub_token')) { + if (GdataExtension.isAuthorized()) { this._listDocuments(); } }; diff --git a/extensions/gdata/module/scripts/project/exporters.js b/extensions/gdata/module/scripts/project/exporters.js index a60a1d5eb..b1f776167 100644 --- a/extensions/gdata/module/scripts/project/exporters.js +++ b/extensions/gdata/module/scripts/project/exporters.js @@ -61,23 +61,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } }; - var messageListener = function(evt) { - window.removeEventListener("message", messageListener, false); - if ($.cookie('authsub_token')) { - doUpload(); - } - }; - - var authenticate = function() { - window.addEventListener("message", messageListener, false); - window.open( - "/command/gdata/authorize", - "google-refine-gdata-signin", - "resizable=1,width=600,height=450" - ); - }; - - authenticate(); + if (GdataExtension.isAuthorized()) { + doUpload(); + } else { + GdataExtension.showAuthorizationDialog(doUpload); + } }; CustomTabularExporterDialog.uploadTargets.push({ diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/AuthorizeCommand.java b/extensions/gdata/src/com/google/refine/extension/gdata/AuthorizeCommand.java deleted file mode 100644 index 05d47655d..000000000 --- a/extensions/gdata/src/com/google/refine/extension/gdata/AuthorizeCommand.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2011, Thomas F. Morris - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of Google nor the names of its contributors may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */package com.google.refine.extension.gdata; - -import java.io.IOException; -import java.net.URL; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.google.gdata.client.http.AuthSubUtil; - -import com.google.refine.commands.Command; - -/** - * Command to allow user to authenticate themselves. - * - */ -public class AuthorizeCommand extends Command { - - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - char[] mountPointChars = this.servlet.getModule("gdata") - .getMountPoint().getMountPoint().toCharArray(); - - StringBuffer sb = new StringBuffer(); - sb.append(mountPointChars, 0, mountPointChars.length); - sb.append("authorized"); - - URL thisUrl = new URL(request.getRequestURL().toString()); - URL authorizedUrl = new URL(thisUrl, sb.toString()); - - String requestUrl = AuthSubUtil.getRequestUrl( - authorizedUrl.toExternalForm(), // execution continues at authorized on redirect - "https://docs.google.com/feeds https://spreadsheets.google.com/feeds https://www.google.com/fusiontables/api/query", - false, - true); - response.sendRedirect(requestUrl); - } - -} diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/AuthorizeCommand2.java b/extensions/gdata/src/com/google/refine/extension/gdata/AuthorizeCommand2.java deleted file mode 100644 index be1693bb7..000000000 --- a/extensions/gdata/src/com/google/refine/extension/gdata/AuthorizeCommand2.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2011, Thomas F. Morris - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of Google nor the names of its contributors may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.refine.extension.gdata; - -import java.io.IOException; -import java.net.URLDecoder; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.google.gdata.client.http.AuthSubUtil; - -import com.google.refine.commands.Command; - -/** - * Second half of authentication sequence after Google has redirected back to us - * - */ -public class AuthorizeCommand2 extends Command { - - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - try { - String queryString = request.getQueryString(); - if (queryString == null) { - respond(response, "401 Unauthorized", "Authentication failed."); - return; - } - - String onetimeUseToken = AuthSubUtil.getTokenFromReply(URLDecoder.decode(queryString,"UTF-8")); - // FIXME(SM): can we safely assume UTF-8 encoding here? - - String sessionToken = AuthSubUtil.exchangeForSessionToken(onetimeUseToken, null); - TokenCookie.setToken(request, response, sessionToken); - -// FeedURLFactory factory = FeedURLFactory.getDefault(); -// SpreadsheetService service = new SpreadsheetService( -// "Google-Refine-GData-Extension-0.2"); -// service.setAuthSubToken(sessionToken); -// -// SpreadsheetFeed feed = service.getFeed( -// factory.getSpreadsheetsFeedUrl(), SpreadsheetFeed.class); -// List spreadsheets = feed.getEntries(); -// for (int i = 0; i < spreadsheets.size(); i++) { -// SpreadsheetEntry entry = spreadsheets.get(i); -// System.out.println("\t" + entry.getTitle().getPlainText()); -// } - - respond(response, "200 OK", ""); - // } catch (AuthenticationException e) { - // } catch (GeneralSecurityException e) { - } catch (Exception e) { // AuthenticationException - // GeneralSecurityException - e.printStackTrace(); - TokenCookie.deleteToken(request, response); - respondException(response, e); - } - } - -} diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/GDataExtension.java b/extensions/gdata/src/com/google/refine/extension/gdata/GDataExtension.java index ad8c3af8b..b8cb8ae4c 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/GDataExtension.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/GDataExtension.java @@ -30,6 +30,7 @@ package com.google.refine.extension.gdata; import java.io.IOException; import java.io.OutputStreamWriter; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; @@ -38,15 +39,22 @@ import java.util.Scanner; import java.util.regex.MatchResult; import java.util.regex.Pattern; +import javax.servlet.http.HttpServletRequest; + import com.google.gdata.client.GoogleService; import com.google.gdata.client.Service.GDataRequest; import com.google.gdata.client.Service.GDataRequest.RequestType; import com.google.gdata.client.docs.DocsService; +import com.google.gdata.client.http.AuthSubUtil; import com.google.gdata.client.spreadsheet.FeedURLFactory; import com.google.gdata.client.spreadsheet.SpreadsheetService; import com.google.gdata.util.ContentType; import com.google.gdata.util.ServiceException; +import com.google.refine.util.ParsingUtilities; + +import edu.mit.simile.butterfly.ButterflyModule; + /** * @author Tom Morris * @copyright 2010 Thomas F. Morris @@ -55,6 +63,27 @@ import com.google.gdata.util.ServiceException; abstract public class GDataExtension { static final String SERVICE_APP_NAME = "Google-Refine-GData-Extension"; + static public String getAuthorizationUrl(ButterflyModule module, HttpServletRequest request) + throws MalformedURLException { + char[] mountPointChars = module.getMountPoint().getMountPoint().toCharArray(); + + StringBuffer sb = new StringBuffer(); + sb.append(mountPointChars, 0, mountPointChars.length); + sb.append("authorized?winname="); + sb.append(ParsingUtilities.encode(request.getParameter("winname"))); + sb.append("&callback="); + sb.append(ParsingUtilities.encode(request.getParameter("callback"))); + + URL thisUrl = new URL(request.getRequestURL().toString()); + URL authorizedUrl = new URL(thisUrl, sb.toString()); + + return AuthSubUtil.getRequestUrl( + authorizedUrl.toExternalForm(), // execution continues at authorized on redirect + "https://docs.google.com/feeds https://spreadsheets.google.com/feeds https://www.google.com/fusiontables/api/query", + false, + true); + } + static private FeedURLFactory factory; static public FeedURLFactory getFeedUrlFactory() { if (factory == null) { diff --git a/main/webapp/modules/core/about.html b/main/webapp/modules/core/about.html index 9750f0f4b..a39976c4f 100644 --- a/main/webapp/modules/core/about.html +++ b/main/webapp/modules/core/about.html @@ -33,6 +33,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> + + About - Google Refine diff --git a/main/webapp/modules/core/error.vt b/main/webapp/modules/core/error.vt index 6715e9a3f..1f9cdefb7 100644 --- a/main/webapp/modules/core/error.vt +++ b/main/webapp/modules/core/error.vt @@ -35,6 +35,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + Error - Google Refine diff --git a/main/webapp/modules/core/index.vt b/main/webapp/modules/core/index.vt index 6427766b9..a5c886ed6 100644 --- a/main/webapp/modules/core/index.vt +++ b/main/webapp/modules/core/index.vt @@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + Google Refine diff --git a/main/webapp/modules/core/preferences.vt b/main/webapp/modules/core/preferences.vt index 2268302db..a102a5756 100644 --- a/main/webapp/modules/core/preferences.vt +++ b/main/webapp/modules/core/preferences.vt @@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + Preferences - Google Refine diff --git a/main/webapp/modules/core/project.vt b/main/webapp/modules/core/project.vt index 20bc1e451..113bd0c7e 100644 --- a/main/webapp/modules/core/project.vt +++ b/main/webapp/modules/core/project.vt @@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + Google Refine