Re: Off For a Few Days (and TODO list)



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]