Re: Off For a Few Days (and TODO list)
- From: Thomas Van Machelen <thomas vanmachelen gmail com>
- To: John Stowers <john stowers gmail com>
- Cc: conduit-list gnome org
- Subject: Re: Off For a Few Days (and TODO list)
- Date: Fri, 27 Jul 2007 08:15:32 +0200
On Fri, 2007-07-27 at 08:14 +0200, Thomas Van Machelen wrote:
> On Tue, 2007-07-24 at 14:05 +0200, Thomas Van Machelen wrote:
> > Hi,
> >
> > 2007/7/18, John Stowers <john stowers gmail com>:
> > > 3) Web dataprovider login issues.
> > > Currently an article on conduit is being written for Linux Magazine. The
> > > author has found none of the online web services work when using firefox to
> > > authenticate. In addition Ken has mentioned that gnome-www-open is a
> > > debianism and is not really portable. Also the GUI freezes when we
> > > authenticate. The long answer is boring, the short answer is use of
> > > gnome-www-open should die. We should use gnome-open instead.
> > >
> >
> > If no work has been on this yet, I'm willing to devote some time on
> > this one when my internet connection is back up at home; because i'm
> > partly responsible for the gnome-www-open stuff that's in trunk atm.
> > ;-)
> >
>
> In attachment you can a first version of the patch to get rid of
> gnome-www-open, using the approach John described. It needs some more
> cleanup, and the addition of the 'authenticating' signal; but the
> important thing is, you can now use your default browser to perform web
> authentication.
Off course i forget the patch, here it is. Let me know what you
think...
>
> Regards,
> Thomas.
Index: conduit/Utils.py
===================================================================
--- conduit/Utils.py (revision 720)
+++ conduit/Utils.py (working copy)
@@ -224,3 +224,26 @@
#the urllib implementation seems more reliable than gnomevfs.unescape
return urllib.unquote(s)
+class LoginTester:
+ def __init__ (self, testFunc, timeout=30):
+ self.testFunc = testFunc
+ self.timeout = timeout
+
+ def wait_for_login(self):
+ start_time = time.time()
+
+ while not self._is_timed_out(start_time):
+ try:
+ if self.testFunc():
+ return
+ except Exception, e:
+ # logw ("testFunc threw an error: %s" % e.message)
+ pass
+
+ time.sleep(2)
+
+ raise Exception("Login timed out")
+
+ def _is_timed_out(self, start):
+ return int(time.time() - start) > self.timeout
+
Index: conduit/MainWindow.py
===================================================================
--- conduit/MainWindow.py (revision 720)
+++ conduit/MainWindow.py (working copy)
@@ -686,7 +686,6 @@
self.conduitApplication.gui.minimize_to_tray()
else:
self.conduitApplication.gui.present()
-
class Application(dbus.service.Object):
def __init__(self):
Index: conduit/dataproviders/FlickrModule/FlickrAPI/flickrapi.py
===================================================================
--- conduit/dataproviders/FlickrModule/FlickrAPI/flickrapi.py (revision 720)
+++ conduit/dataproviders/FlickrModule/FlickrAPI/flickrapi.py (working copy)
@@ -254,7 +254,7 @@
return self.__handlerCache[method]
#-------------------------------------------------------------------
- def __getAuthURL(self, perms, frob):
+ def getAuthURL(self, perms, frob):
"""Return the authorization URL to get a token.
This is the URL the app will launch a browser toward if it
@@ -444,7 +444,7 @@
#-----------------------------------------------------------------------
def validateFrob(self, frob, perms, browser):
- os.system("%s '%s'" % (browser, self.__getAuthURL(perms, frob)))
+ os.system("%s '%s'" % (browser, self.getAuthURL(perms, frob)))
#-----------------------------------------------------------------------
def getToken(self, username, perms="read", browser="lynx"):
@@ -467,6 +467,23 @@
"""
# see if we have a saved token
+ token = self.getCachedToken(username)
+
+ # get a new token if we need one
+ if token == None:
+ # get the frob
+ frob = self.getFrob()
+
+ # validate online
+ self.validateFrob(frob, perms, browser)
+
+ # get a token
+ token = self.getAuthToken(username, frob)
+
+ return token
+
+ def getCachedToken(self, username, perms="read"):
+ # see if we have a saved token
token = self.__getCachedToken(username)
# see if it's valid
@@ -477,31 +494,31 @@
else:
# see if we have enough permissions
tokenPerms = rsp.auth[0].perms[0].elementText
- if tokenPerms == "read" and perms != "read": token = None
- elif tokenPerms == "write" and perms == "delete": token = None
+ if tokenPerms == "read" and perms != "read":
+ token = None
+ elif tokenPerms == "write" and perms == "delete":
+ token = None
- # get a new token if we need one
- if token == None:
- # get the frob
- rsp = self.auth_getFrob(api_key=self.apiKey)
- self.testFailure(rsp)
+ return token
- frob = rsp.frob[0].elementText
+ def getFrob(self):
+ # get the frob
+ rsp = self.auth_getFrob(api_key=self.apiKey)
+ self.testFailure(rsp)
- # validate online
- self.validateFrob(frob, perms, browser)
+ return rsp.frob[0].elementText
- # get a token
- rsp = self.auth_getToken(api_key=self.apiKey, frob=frob)
- self.testFailure(rsp)
+ def getAuthToken(self, username, frob):
+ rsp = self.auth_getToken(api_key=self.apiKey, frob=frob)
+ self.testFailure(rsp)
- token = rsp.auth[0].token[0].elementText
+ token = rsp.auth[0].token[0].elementText
+ self.__setCachedToken(username, rsp.xml)
- # store the auth info for next time
- self.__setCachedToken(username, rsp.xml)
-
return token
+
+
########################################################################
# App functionality
########################################################################
Index: conduit/dataproviders/FlickrModule/FlickrModule.py
===================================================================
--- conduit/dataproviders/FlickrModule/FlickrModule.py (revision 720)
+++ conduit/dataproviders/FlickrModule/FlickrModule.py (working copy)
@@ -3,6 +3,7 @@
"""
import os, sys
import gtk
+import gnome
import traceback
import md5
@@ -92,9 +93,39 @@
def refresh(self):
DataProvider.ImageSink.refresh(self)
+ self._login()
+
+ def _login(self):
+ """
+ Get ourselves a token we can use to perform all calls
+ """
self.fapi = FlickrAPI(FlickrSink.API_KEY, FlickrSink.SHARED_SECRET)
- self.token = self.fapi.getToken(self.username, browser="gnome-www-browser -p", perms="delete")
-
+
+ # can we get a cached token?
+ self.token = self.fapi.getCachedToken(self.username, perms="delete")
+
+ # create a new one if not
+ if self.token == None:
+ # get frob and open it
+ self.frob = self.fapi.getFrob()
+ gnome.url_show (self.fapi.getAuthURL("delete", self.frob))
+
+ # wait for user to login
+ login_tester = Utils.LoginTester(self._try_login)
+ login_tester.wait_for_login()
+
+ def _try_login(self):
+ """
+ This function is used by the login tester, we try to get a token,
+ but return None if it does not succeed so login tester can keep trying
+ """
+ try:
+ self.token = self.fapi.getAuthToken(self.username, self.frob)
+ self.frob = None
+ return self.token
+ except:
+ return None
+
def delete(self, LUID):
if self._get_photo_info(LUID) != None:
ret = self.fapi.photos_delete(
Index: conduit/dataproviders/BoxDotNetModule/BoxDotNetAPI/boxdotnet.py
===================================================================
--- conduit/dataproviders/BoxDotNetModule/BoxDotNetAPI/boxdotnet.py (revision 720)
+++ conduit/dataproviders/BoxDotNetModule/BoxDotNetAPI/boxdotnet.py (working copy)
@@ -153,9 +153,7 @@
'delete' : 's_delete_node'
}
- def __init__(self, browser="firefox"):
- self.browser = browser
-
+ def __init__(self):
self.__handlerCache={}
@classmethod
@@ -179,19 +177,24 @@
raise BoxDotNetError ("Box.net returned [%s] for action [%s]" % (status, method))
- def login(self, api_key):
- # get ticket
- rsp = self.get_ticket (api_key=api_key)
- ticket = rsp.ticket[0].elementText
- # open url
- url = "http://www.box.net/api/1.0/auth/%s" % ticket
- os.system('%s "%s"' % (self.browser, url))
+ @classmethod
+ def get_login_url(cls, ticket):
+ return "http://www.box.net/api/1.0/auth/%s" % ticket
- # get token
- rsp = self.get_auth_token(api_key=api_key, ticket=ticket)
+ # def login(self, api_key):
+ # # get ticket
+ # rsp = self.get_ticket (api_key=api_key)
+ # ticket = rsp.ticket[0].elementText
+ # # open url
+ # url = "http://www.box.net/api/1.0/auth/%s" % ticket
+ # os.system('%s "%s"' % (self.browser, url))
- return rsp
+ # # get token
+ # rsp = self.get_auth_token(api_key=api_key, ticket=ticket)
+ # return rsp
+
+
def __getattr__(self, method, **arg):
"""
Handle all box.net calls
Index: conduit/dataproviders/BoxDotNetModule/BoxDotNetModule.py
===================================================================
--- conduit/dataproviders/BoxDotNetModule/BoxDotNetModule.py (revision 720)
+++ conduit/dataproviders/BoxDotNetModule/BoxDotNetModule.py (working copy)
@@ -3,6 +3,7 @@
"""
import os, sys
import gtk
+import gnome
import traceback
import md5
@@ -104,13 +105,6 @@
#------------------------------------------
# File info related functions
#------------------------------------------
- def _set_login_info (self, xml):
- """
- Read the user id and the auth_token from the xml node
- """
- self.user_id = xml.user[0].user_id[0].elementText
- self.token = xml.auth_token[0].elementText
-
def _get_folder_id(self):
"""
Returns a folder id for the configured folder name, it re-uses existing ones
@@ -164,14 +158,47 @@
def _login(self):
if self.boxapi == None:
- self.boxapi = BoxDotNet(browser="gnome-www-browser -p")
+ self.boxapi = BoxDotNet()
# login if not done yet, we only login once to prevent
# the browser for popping up each time
if not self.token:
- rsp = self.boxapi.login(BoxDotNetTwoWay.API_KEY)
- self._set_login_info(rsp)
+ # get the ticket and open login url
+ self._set_ticket()
+ gnome.url_show(BoxDotNet.get_login_url(self.ticket))
+ # wait for login
+ login_tester = Utils.LoginTester(self._try_login)
+ login_tester.wait_for_login()
+
+ def _try_login (self):
+ """
+ Try to perform a login, return None if it does not succeed
+ so the LoginTester can keep trying
+ """
+ try:
+ self._set_login_info(self.ticket)
+ return self.token
+ except:
+ return None
+
+ def _set_ticket(self):
+ """
+ Get the ticket that can be used for logging in for real
+ """
+ rsp = self.boxapi.get_ticket(api_key=self.API_KEY)
+ self.ticket = rsp.ticket[0].elementText
+
+ def _set_login_info (self, ticket):
+ """
+ Get a token and the user id
+ """
+ rsp = self.boxapi.get_auth_token(api_key=self.API_KEY, ticket=ticket)
+
+ self.user_id = xml.user[0].user_id[0].elementText
+ self.token = xml.auth_token[0].elementText
+ self.ticket = None
+
#------------------------------------------
# Dataprovider Functions
#------------------------------------------
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]