The branch, frodo has been updated
       via  9c522f623253ca05e788610feacf8087fc5798ed (commit)
      from  c059985c3bff77d67b48afa13fbff802503ecb1c (commit)

- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/plugins;a=commit;h=9c522f623253ca05e788610feacf8087fc5798ed

commit 9c522f623253ca05e788610feacf8087fc5798ed
Author: Martijn Kaijser <[email protected]>
Date:   Thu May 29 18:02:06 2014 +0200

    [plugin.video.youtube] 4.4.8

diff --git a/plugin.video.youtube/YouTubeCore.py 
b/plugin.video.youtube/YouTubeCore.py
index b1b3758..2bb7e09 100644
--- a/plugin.video.youtube/YouTubeCore.py
+++ b/plugin.video.youtube/YouTubeCore.py
@@ -139,7 +139,7 @@ class YouTubeCore():
     def del_playlist(self, params={}):
         self.common.log("")
         get = params.get
-        url = 
u"http://gdata.youtube.com/feeds/api/users/default/playlists/{0}".format(get("playlist"))
+        url = "http://gdata.youtube.com/feeds/api/users/default/playlists/%s"; 
% (get("playlist"))
         result = self._fetchPage({"link": url, "api": "true", "login": "true", 
"auth": "true", "method": "DELETE"})
         return (result["content"], result["status"])
 
@@ -180,9 +180,10 @@ class YouTubeCore():
         folders = []
         for node in entries:
             folder = {}
-
-            if len(self.common.parseDOM(node, "yt:deprecated")):
+            print repr(node)
+            if 'yt:deprecated' in node:
                 continue
+
             title = self.common.parseDOM(node, "atom:category", ret="label")[0]
 
             if title:
@@ -220,7 +221,7 @@ class YouTubeCore():
             if title.find(": ") > 0:
                 title = title[title.find(": ") + 2:]
                 title = self.common.replaceHTMLCodes(title)
-
+                
             folder['Title'] = title
             for tmp in self.common.parseDOM(node, "published"):
                 folder['published'] = tmp
@@ -397,13 +398,12 @@ class YouTubeCore():
             return ret_obj
 
         if get("url_data"):
-            urldata = get("url_data")
-            url_data = {}
-
-            for key in urldata:
-                url_data[key.encode('UTF-8')] = urldata[key].encode('UTF-8')
+            url_data = get("url_data")
+            url_data_encoded = {}
+            for k, v in url_data.iteritems():
+                url_data_encoded[k] = unicode(v).encode('utf-8')
 
-            request = urllib2.Request(link, urllib.urlencode(url_data))
+            request = urllib2.Request(link, urllib.urlencode(url_data_encoded))
             request.add_header('Content-Type', 
'application/x-www-form-urlencoded')
         elif get("request", "false") == "false":
             if get("proxy"):
@@ -462,7 +462,6 @@ class YouTubeCore():
             if cookie:
                 self.common.log("Setting cookie: " + cookie)
                 request.add_header('Cookie', cookie)
-
             con = urllib2.urlopen(request)
 
             inputdata = con.read()
@@ -545,6 +544,25 @@ class YouTubeCore():
             self.common.log("4")
             error = self.common.parseDOM(ret['content'], "div", attrs={"id": 
"watch7-player-age-gate-content"})
 
+        if len(error) == 0:
+            self.common.log("5")
+            if len(self.common.parseDOM(ret['content'], "input", attrs={"id": 
"send-code-button"})):
+                error = [self.language(30630)]
+
+        if len(error) == 0:
+            self.common.log("6")
+            if len(self.common.parseDOM(ret['content'], "h1", attrs={"id": 
"login-challenge-heading"})):
+                error = [self.language(30630)]
+
+        if len(error) == 0:
+            self.common.log("7")
+            if len(self.common.parseDOM(ret['content'], "h2", attrs={"class": 
"smsauth-interstitial-heading"})):
+                error = [self.language(30630)]
+
+        if len(error) == 0:
+            self.common.log("8")
+            error = self.common.parseDOM(ret['content'], "span", 
attrs={"class": "error-msg"})
+
         if len(error) > 0:
             self.common.log("Found error: " + repr(error))
             error = self.common.stripTags(error[0])
@@ -761,7 +779,6 @@ class YouTubeCore():
         result = 1
 
         for tmp in self.common.parseDOM(node, "yt:duration", ret="seconds"):
-            tmp = int(tmp) / 60
             if tmp:
                 result = tmp
 
diff --git a/plugin.video.youtube/YouTubeLogin.py 
b/plugin.video.youtube/YouTubeLogin.py
index 3a5d0aa..f4212f5 100644
--- a/plugin.video.youtube/YouTubeLogin.py
+++ b/plugin.video.youtube/YouTubeLogin.py
@@ -188,8 +188,10 @@ class YouTubeLogin():
             fetch_options = False
 
             # Check if we are logged in.
+#            nick = self.common.parseDOM(ret["content"], "p", attrs={"class": 
"masthead-expanded-acct-sw-id2"})
             nick = self.common.parseDOM(ret["content"], "span", attrs={"id": 
"yt-masthead-user-displayname"})
 
+
             # Check if there are any errors to report
             errors = self.core._findErrors(ret, silent=True)
             if errors:
@@ -224,41 +226,42 @@ class YouTubeLogin():
             newurl = self.common.parseDOM(ret["content"], "meta", 
attrs={"http-equiv": "refresh"}, ret="content")
             if len(newurl) > 0:
                 newurl = newurl[0].replace("&amp;", "&")
-                newurl = newurl.replace("0; url=&#39;", "")
+                newurl = newurl[newurl.find("&#39;") + 5:newurl.rfind("&#39;")]
                 fetch_options = {"link": newurl, "referer": ret["location"]}
                 self.common.log("Part C: "  + repr(fetch_options))
                 continue
 
             ## 2-factor login start
-            #if ret["content"].find("smsUserPin") > -1:
-            #    url_data = self._fillUserPin(ret["content"])
-            #    if len(url_data) == 0:
-            #        return (False, 500)
+            if ret["content"].find("smsUserPin") > -1:
+                url_data = self._fillUserPin(ret["content"])
+                if len(url_data) == 0:
+                    return (False, 500)
 
-            #    self.common.log("RETURNED CONTENT" + ret["content"])
-            #    new_part = self.common.parseDOM(ret["content"], "input", 
attrs={"name": "continue"}, ret="value")
-            #    fetch_options = {"link": new_part[0].replace("&amp;", "&"), 
"url_data": url_data, "referer": ret["location"]}
+                new_part = self.common.parseDOM(ret["content"], "form", 
attrs={"id": "gaia_secondfactorform"}, ret="action")
+                t_url = ret["new_url"]
+                t_url = t_url[:t_url.find("/", 10) + 1] + 
new_part[0].replace("&amp;", "&")
+                fetch_options = {"link": t_url, "url_data": url_data, 
"referer": ret["new_url"]}
 
-            #    self.common.log("Part D: " + repr(fetch_options))
-            #    continue
+                self.common.log("Part D: " + repr(fetch_options))
+                continue
 
-            #smsToken = self.common.parseDOM(ret["content"].replace("\n", ""), 
"input", attrs={"name": "smsToken"}, ret="value")
+            smsToken = self.common.parseDOM(ret["content"].replace("\n", ""), 
"input", attrs={"name": "smsToken"}, ret="value")
 
-            #if len(smsToken) > 0 and galx != "":
-            #    url_data = {"smsToken": smsToken[0],
-            #                "PersistentCookie": "yes",
-            #                "service": "youtube",
-            #                "GALX": galx}
+            if len(smsToken) > 0 and galx != "":
+                url_data = {"smsToken": smsToken[0],
+                            "PersistentCookie": "yes",
+                            "service": "youtube",
+                            "GALX": galx}
 
-            #    target_url = self.common.parseDOM(ret["content"], "form", 
attrs={"name": "hiddenpost"}, ret="action")
-            #    fetch_options = {"link": target_url[0], "url_data": url_data, 
"referer": ret["location"]}
-            #    self.common.log("Part E: " + repr(fetch_options))
-            #    continue
+                target_url = self.common.parseDOM(ret["content"], "form", 
attrs={"name": "hiddenpost"}, ret="action")
+                fetch_options = {"link": target_url[0], "url_data": url_data, 
"referer": ret["location"]}
+                self.common.log("Part E: " + repr(fetch_options))
+                continue
 
             ## 2-factor login finish
-            #if not fetch_options:
+            if not fetch_options:
                 # Check for errors.
-            #    return (self.core._findErrors(ret), 303)
+                return (self.core._findErrors(ret), 303)
 
         return (ret, 500)
 
@@ -270,7 +273,7 @@ class YouTubeLogin():
 
         for name in self.common.parseDOM(content, "input", ret="name"):
             for val in self.common.parseDOM(content, "input", attrs={"name": 
name}, ret="value"):
-                url_data[name] = val
+                url_data[name] = self.common.makeAscii(val)
 
         self.common.log("Extracted url_data: " + repr(url_data), 0)
         url_data["Email"] = self.pluginsettings.userName()
@@ -283,12 +286,18 @@ class YouTubeLogin():
 
     def _fillUserPin(self, content):
         self.common.log("")
+        #form = self.common.parseDOM(content, "form", attrs={"id": 
"gaia_secondfactorform"}, ret=True)
         form = self.common.parseDOM(content, "form", attrs={"id": 
"gaia_secondfactorform"}, ret=True)
 
         url_data = {}
         for name in self.common.parseDOM(form, "input", ret="name"):
-            for val in self.common.parseDOM(form, "input", attrs={"name": 
name}, ret="value"):
-                url_data[name] = val
+            if name not in ["smsSend", "retry"]:
+                #for val in self.common.parseDOM(form, "input", attrs={"name": 
name}, ret="value"):
+                #    url_data[name] = self.common.makeAscii(val)
+             if name not in ["smsSend", "retry"]:
+                 for val in self.common.parseDOM(form, "input", attrs={"name": 
name}, ret="value"):
+                     url_data[name] = self.common.makeAscii(val)
+                
 
         self.common.log("url_data: " + repr(form), 0)
 
diff --git a/plugin.video.youtube/YouTubeNavigation.py 
b/plugin.video.youtube/YouTubeNavigation.py
index e4c3a7c..dcd67ad 100644
--- a/plugin.video.youtube/YouTubeNavigation.py
+++ b/plugin.video.youtube/YouTubeNavigation.py
@@ -167,7 +167,7 @@ class YouTubeNavigation():
         results = []
         if (get("feed") == "search" or get("scraper") == "search_disco"):
             if not get("search"):
-                query = self.common.getUserInput(self.language(30006), '')
+                query = self.common.getUserInput(self.language(30006), 
'').strip()
                 if not query:
                     return False
                 params["search"] = query
@@ -442,6 +442,7 @@ class YouTubeNavigation():
 
         listitem.setProperty("Video", "true")
         listitem.setProperty("IsPlayable", "true")
+        listitem.addStreamInfo('video', {'duration': item('Duration')})
         listitem.setInfo(type='Video', infoLabels=item_params)
         self.xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, 
listitem=listitem, isFolder=False, totalItems=listSize + 1)
         self.common.log("Done", 5)
diff --git a/plugin.video.youtube/YouTubePlayer.py 
b/plugin.video.youtube/YouTubePlayer.py
index cae01dd..539aa67 100644
--- a/plugin.video.youtube/YouTubePlayer.py
+++ b/plugin.video.youtube/YouTubePlayer.py
@@ -16,14 +16,13 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 '''
 
+import re
 import sys
-import urllib
 import cgi
+import urllib
 try: import simplejson as json
 except ImportError: import json
 
-import urllib2, re
-
 class YouTubePlayer():
     fmt_value = {
         5: "240p h263 flv container",
@@ -52,15 +51,13 @@ class YouTubePlayer():
         121: "hd1080"
         }
 
-    # MAX RECURSION Depth for security
-    MAX_REC_DEPTH = 5
-
     # YouTube Playback Feeds
     urls = {}
     urls['video_stream'] = "http://www.youtube.com/watch?v=%s&safeSearch=none";
     urls['embed_stream'] = "http://www.youtube.com/get_video_info?video_id=%s";
     urls['video_info'] = "http://gdata.youtube.com/feeds/api/videos/%s";
 
+
     def __init__(self):
         self.xbmcgui = sys.modules["__main__"].xbmcgui
         self.xbmcplugin = sys.modules["__main__"].xbmcplugin
@@ -77,9 +74,8 @@ class YouTubePlayer():
         self.core = sys.modules["__main__"].core
         self.login = sys.modules["__main__"].login
         self.subtitles = sys.modules["__main__"].subtitles
-        
+
         self.algoCache = {}
-        self._cleanTmpVariables()
 
     def playVideo(self, params={}):
         self.common.log(repr(params), 3)
@@ -101,7 +97,6 @@ class YouTubePlayer():
         self.xbmcplugin.setResolvedUrl(handle=int(sys.argv[1]), 
succeeded=True, listitem=listitem)
 
         if self.settings.getSetting("lang_code") != "0" or 
self.settings.getSetting("annotations") == "true":
-            self.common.log("BLAAAAAAAAAAAAAAAAAAAAAA: " + 
repr(self.settings.getSetting("lang_code")))
             self.subtitles.addSubtitles(video)
 
         if (get("watch_later") == "true" and get("playlist_entry_id")):
@@ -317,7 +312,7 @@ class YouTubePlayer():
             url = "http:" + url
         return url
 
-    def extractFlashVars(self, data, assets):
+    def extractFlashVars(self, data, assets=0):
         flashvars = {}
         found = False
 
@@ -343,7 +338,7 @@ class YouTubePlayer():
             if k in flashvars:
                 flashvars[k] = self.normalizeUrl(flashvars[k])
 
-        self.common.log("Step2: " + repr(data))
+        self.common.log("Step2: " + repr(data), 4)
 
         self.common.log(u"flashvars: " + repr(flashvars), 2)
         return flashvars
@@ -352,7 +347,7 @@ class YouTubePlayer():
         self.common.log(u"")
         links = {}
 
-        flashvars = self.extractFlashVars(result[u"content"], 0)
+        flashvars = self.extractFlashVars(result[u"content"])
         if not flashvars.has_key(u"url_encoded_fmt_stream_map"):
             return links
 
@@ -385,24 +380,14 @@ class YouTubePlayer():
             elif url_desc_map.has_key(u"s"):
                 sig = url_desc_map[u"s"][0]
                 flashvars = self.extractFlashVars(result[u"content"], 1)
-                js = flashvars[u"js"]
-                url = url + u"&signature=" + self.decrypt_signature(sig, js)
+                url = url + u"&signature=" + self.decrypt_signature(sig, 
flashvars[u"js"])
 
             links[key] = url
 
         return links
 
-    @staticmethod
-    def printDBG(s):
-        print(s)
-
-    def _cleanTmpVariables(self):
-        self.fullAlgoCode = ''
-        self.allLocalFunNamesTab = []
-        self.playerData = ''
-
     def _jsToPy(self, jsFunBody):
-       pythonFunBody = re.sub(r'function (\w*)\$(\w*)', r'function \1_S_\2', 
jsFunBody)
+        pythonFunBody = re.sub(r'function (\w*)\$(\w*)', r'function \1_S_\2', 
jsFunBody)
         pythonFunBody = pythonFunBody.replace('function', 'def').replace('{', 
':\n\t').replace('}', '').replace(';', '\n\t').replace('var ', '')
         pythonFunBody = pythonFunBody.replace('.reverse()', '[::-1]')
 
@@ -426,10 +411,10 @@ class YouTubePlayer():
                 lines[i] = lines[i].replace( match.group(0), match.group(2) + 
'.join(' + match.group(1) + ')' )
         return "\n".join(lines)
 
-    def _getLocalFunBody(self, funName):
+    def _getLocalFunBody(self, funName, playerData):
         # get function body
         funName=funName.replace('$', '\\$')
-        match = re.search('(function %s\([^)]+?\){[^}]+?})' % funName, 
self.playerData)
+        match = re.search('(function %s\([^)]+?\){[^}]+?})' % funName, 
playerData)
         if match:
             # return jsFunBody
             return match.group(1)
@@ -444,59 +429,56 @@ class YouTubePlayer():
         return set()
 
     def decrypt_signature(self, s, playerUrl):
-        self.printDBG("decrypt_signature sign_len[%d] playerUrl[%s]" % 
(len(s), playerUrl) )
-
-        # clear local data
-        self._cleanTmpVariables()
+        self.common.log("decrypt_signature sign_len[%d] playerUrl[%s]" % 
(len(s), playerUrl) )
 
         # use algoCache
         if playerUrl not in self.algoCache:
             # get player HTML 5 sript
-            request = urllib2.Request(playerUrl)
+            res = self.core._fetchPage({u"link": playerUrl})
+            playerData = res["content"]
             try:
-                self.playerData = urllib2.urlopen(request).read()
-                self.playerData = self.playerData.decode('utf-8', 'ignore')
+                playerData = playerData.decode('utf-8', 'ignore')
             except Exception as ex:
-                self.printDBG("Error: " + str(sys.exc_info()[0]) + " - " + 
str(ex))
-                self.printDBG('Unable to download playerUrl webpage')
+                self.common.log("Error: " + str(sys.exc_info()[0]) + " - " + 
str(ex))
+                self.common.log('Unable to download playerUrl webpage')
                 return ''
 
-            # get main function name 
-            match = re.search("signature=(\w+?)\([^)]\)", self.playerData)
+            # get main function name
+            match = re.search("signature=(\w+?)\([^)]\)", playerData)
             if match:
                 mainFunName = match.group(1)
-                self.printDBG('Main signature function name = "%s"' % 
mainFunName)
-            else: 
-                self.printDBG('Can not get main signature function name')
+                self.common.log('Main signature function name = "%s"' % 
mainFunName)
+            else:
+                self.common.log('Can not get main signature function name')
                 return ''
 
-            self._getfullAlgoCode( mainFunName )
+            fullAlgoCode = self._getfullAlgoCode( mainFunName, playerData )
 
             # wrap all local algo function into one function 
extractedSignatureAlgo()
-            algoLines = self.fullAlgoCode.split('\n')
+            algoLines = fullAlgoCode.split('\n')
             for i in range(len(algoLines)):
                 algoLines[i] = '\t' + algoLines[i]
-            self.fullAlgoCode  = 'def extractedSignatureAlgo(param):'
-            self.fullAlgoCode += '\n'.join(algoLines)
-            self.fullAlgoCode += '\n\treturn %s(param)' % mainFunName
-            self.fullAlgoCode += '\noutSignature = extractedSignatureAlgo( 
inSignature )\n'
+            fullAlgoCode  = 'def extractedSignatureAlgo(param):'
+            fullAlgoCode += '\n'.join(algoLines)
+            fullAlgoCode += '\n\treturn %s(param)' % mainFunName
+            fullAlgoCode += '\noutSignature = extractedSignatureAlgo( 
inSignature )\n'
 
-            # after this function we should have all needed code in 
self.fullAlgoCode
+            # after this function we should have all needed code in 
fullAlgoCode
 
-            self.printDBG( "---------------------------------------" )
-            self.printDBG( "|    ALGO FOR SIGNATURE DECRYPTION    |" )
-            self.printDBG( "---------------------------------------" )
-            self.printDBG( self.fullAlgoCode                         )
-            self.printDBG( "---------------------------------------" )
+            self.common.log( "---------------------------------------" )
+            self.common.log( "|    ALGO FOR SIGNATURE DECRYPTION    |" )
+            self.common.log( "---------------------------------------" )
+            self.common.log( fullAlgoCode                         )
+            self.common.log( "---------------------------------------" )
 
             try:
-                algoCodeObj = compile(self.fullAlgoCode, '', 'exec')
+                algoCodeObj = compile(fullAlgoCode, '', 'exec')
             except:
-                self.printDBG('decryptSignature compile algo code EXCEPTION')
+                self.common.log('decryptSignature compile algo code EXCEPTION')
                 return ''
         else:
             # get algoCodeObj from algoCache
-            self.printDBG('Algo taken from cache')
+            self.common.log('Algo taken from cache')
             algoCodeObj = self.algoCache[playerUrl]
 
         # for security alow only flew python global function in algo code
@@ -509,50 +491,51 @@ class YouTubePlayer():
         try:
             exec( algoCodeObj, vGlobals, vLocals )
         except:
-            self.printDBG('decryptSignature exec code EXCEPTION')
+            self.common.log('decryptSignature exec code EXCEPTION')
             return ''
 
-        self.printDBG('Decrypted signature = [%s]' % vLocals['outSignature'])
+        self.common.log('Decrypted signature = [%s]' % vLocals['outSignature'])
         # if algo seems ok and not in cache, add it to cache
         if playerUrl not in self.algoCache and '' != vLocals['outSignature']:
-            self.printDBG('Algo from player [%s] added to cache' % playerUrl)
+            self.common.log('Algo from player [%s] added to cache' % playerUrl)
             self.algoCache[playerUrl] = algoCodeObj
 
-        # free not needed data
-        self._cleanTmpVariables()
-
         return vLocals['outSignature']
 
     # Note, this method is using a recursion
-    def _getfullAlgoCode( self, mainFunName, recDepth = 0 ):
-        if self.MAX_REC_DEPTH <= recDepth:
-            self.printDBG('_getfullAlgoCode: Maximum recursion depth exceeded')
-            return 
+    def _getfullAlgoCode( self, mainFunName, playerData, recDepth = 0, 
allLocalFunNamesTab=[] ):
+        # Max recursion of 5
+        if 5 <= recDepth:
+            self.common.log('_getfullAlgoCode: Maximum recursion depth 
exceeded')
+            return
 
-        funBody = self._getLocalFunBody( mainFunName )
+        funBody = self._getLocalFunBody( mainFunName, playerData)
         if '' != funBody:
             funNames = self._getAllLocalSubFunNames(funBody)
             if len(funNames):
                 for funName in funNames:
-                   funName_=funName.replace('$','_S_')
-                    if funName not in self.allLocalFunNamesTab:
-                       funBody=funBody.replace(funName,funName_)
-                        self.allLocalFunNamesTab.append(funName)
-                        self.printDBG("Add local function %s to known 
functions" % mainFunName)
-                        self._getfullAlgoCode( funName, recDepth + 1 )
-
-            # conver code from javascript to python 
+                    funName_=funName.replace('$','_S_')
+                    if funName not in allLocalFunNamesTab:
+                        funBody=funBody.replace(funName,funName_)
+                        allLocalFunNamesTab.append(funName)
+                        self.common.log("Add local function %s to known 
functions" % mainFunName)
+                        funBody = self._getfullAlgoCode( funName, playerData, 
recDepth + 1, allLocalFunNamesTab ) + "\n" + funBody
+
+            # conver code from javascript to python
             funBody = self._jsToPy(funBody)
-            self.fullAlgoCode += '\n' + funBody + '\n'
-        return
+            return '\n' + funBody + '\n'
+        return funBody
 
-    def getVideoPageFromYoutube(self, get):
+    def getVideoPageFromYoutube(self, get, has_verified = False):
         login = "false"
+        verify = ""
 
         if self.pluginsettings.userHasProvidedValidCredentials():
             login = "true"
+            if has_verified:
+                verify = u"&has_verified=1"
 
-        page = self.core._fetchPage({u"link": self.urls[u"video_stream"] % 
get(u"videoid"), "login": login})
+        page = self.core._fetchPage({u"link": (self.urls[u"video_stream"] % 
get(u"videoid")) + verify, "login": login})
         self.common.log("Step1: " + repr(page["content"].find("ytplayer")))
 
         if not page:
@@ -573,8 +556,7 @@ class YouTubePlayer():
         if self.isVideoAgeRestricted(result):
             self.common.log(u"Age restricted video")
             if self.pluginsettings.userHasProvidedValidCredentials():
-                self.login._httpLogin({"new":"true"})
-                result = self.getVideoPageFromYoutube(get)
+                result = self.getVideoPageFromYoutube(get, True)
             else:
                 video[u"apierror"] = self.language(30622)
 
diff --git a/plugin.video.youtube/YouTubePlaylistControl.py 
b/plugin.video.youtube/YouTubePlaylistControl.py
index b35f98f..5757daf 100644
--- a/plugin.video.youtube/YouTubePlaylistControl.py
+++ b/plugin.video.youtube/YouTubePlaylistControl.py
@@ -83,7 +83,7 @@ class YouTubePlaylistControl():
         playlist = self.xbmc.PlayList(self.xbmc.PLAYLIST_VIDEO)
         playlist.clear()
 
-        video_url = "%s?path=/root&action=play_video&videoid=%s"
+        video_url = "%s?path=/root/video&action=play_video&videoid=%s"
         # queue all entries
         for entry in result:
             video = entry.get
diff --git a/plugin.video.youtube/YouTubeSubtitleControl.py 
b/plugin.video.youtube/YouTubeSubtitleControl.py
index 8909440..0aa4bec 100644
--- a/plugin.video.youtube/YouTubeSubtitleControl.py
+++ b/plugin.video.youtube/YouTubeSubtitleControl.py
@@ -139,10 +139,14 @@ class YouTubeSubtitleControl():
         w = self.storage.openFile(path, "w")
         try:
             w.write(result.encode("utf-8")) # WTF, didn't have to do this 
before, did i?
-        except:
-            w.write(result)
-            self.common.log(u"NOT utf-8 WRITE!!!: " + path + " - " + 
repr(result))
-            time.sleep(20)
+        except Exception as e:
+            self.common.log("Exception: " + repr(e))
+            try:
+                w.write(result)
+                self.common.log(u"NOT utf-8 WRITE!!!: " + path + " - " + 
repr(result))
+            except Exception as de:
+                self.common.log("Exception2: " + repr(de))
+            time.sleep(5)
 
         w.close()
 
diff --git a/plugin.video.youtube/addon.xml b/plugin.video.youtube/addon.xml
index 31c157a..1e8ea4f 100644
--- a/plugin.video.youtube/addon.xml
+++ b/plugin.video.youtube/addon.xml
@@ -1,10 +1,10 @@
-<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
-<addon id="plugin.video.youtube" name="YouTube" provider-name="TheCollective, 
Skipmode A1" version="4.4.7">
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<addon id="plugin.video.youtube" name="YouTube" provider-name="TheCollective" 
version="4.4.8">
   <requires>
     <import addon="xbmc.python" version="2.1.0" />
     <import addon="script.module.simplejson" version="2.0.10" />
     <import addon="script.common.plugin.cache" version="2.5.2" />
-    <import addon="script.module.parsedom" version="2.5.1" />
+    <import addon="script.module.parsedom" version="2.5.2" />
     <import addon="script.module.simple.downloader" version="1.9.4" />
   </requires>
   <extension library="default.py" point="xbmc.python.pluginsource">
@@ -117,12 +117,7 @@ Raadpleeg de lokale wetgeving voordat u deze plugin 
installeert.</disclaimer>
     <disclaimer lang="sv">Någon del av detta tillägg kanske är olagligt i 
ditt land - kontrollera dina lokala lagar innan installation.</disclaimer>
     <disclaimer 
lang="th">บางส่วนจากส่วนขยายนี้อาจไม่ถูกต้องตามกฏหมายในประเทศของคุณ
 
กรุณาตรวจสอบกฏหมายในประเทศของคุณก่อนทำการติดตั้ง</disclaimer>
     <disclaimer lang="zh">这个插件的某些内容可能不符合你
所在国家的法律规定 - 请在在安装
前确认符合当地法律。</disclaimer>
-    <language></language>
     <platform>all</platform>
-    <license>GNU GENERAL PUBLIC LICENSE. Version 2, June 1991</license>
-    <forum>http://forum.xbmc.org/showthread.php?tid=79487</forum>
-    <website>http://www.youtube.com</website>
-    <email></email>
-    <source>git://github.com/skipmodea1/plugin.video.youtube.git</source>
+    <language />
   </extension>
 </addon>
\ No newline at end of file
diff --git a/plugin.video.youtube/changelog.txt 
b/plugin.video.youtube/changelog.txt
index 7a97afe..c59d967 100644
--- a/plugin.video.youtube/changelog.txt
+++ b/plugin.video.youtube/changelog.txt
@@ -1,12 +1,23 @@
-[B]Known Errors[/B]
-- Google's two-step verification is NOT working at the moment for this addon: 
until it gets fixed, either create a second google account for youtube viewing 
in xbmc or turn 2-step off. 
-
-[B]Version 4.4.7[/B]
-This version contains the sources by sogopot 
(http://forum.xbmc.org/showthread.php?tid=79487&page=271) and jded 
(http://forum.xbmc.org/showthread.php?tid=79487&page=276), thanks both :). I 
(Skipmode A1) pushed it to the officials XMBC repo so it will install for 
everybody.
-- Fixed: To solve the login problems, I added the fix from this post: Reply 
#52 (http://code.google.com/p/youtubexbmc/issues/detail?id=115#c52). If you 
continue to have login problems, you may have to find a different fix.
-- Fixed: To fix a problem with VEVO videos not playing, as well as certain 
videos added to favorites not playing, I added the YouTubePlayer.py from this 
post: Reply #217 
(http://code.google.com/p/youtubexbmc/issues/detail?id=95#c217).
-- Fixed: To fix a problem with LIVE streams not playing, I compared an addon 
sent to from member RedPenguin, and found a duplicated entry at line 362 & 363 
and replaced with the necessary code in YouTubePlayer.py.
-- Fixed: Fix Login Problem with non English languages.
+[B]TODO:[/B]
+- Fix RTMP support.
+- UTF8/16 does not work consistently(Verify failures against minidom 
implementation)
+- Embed playback fallback
+
+[B]Errata[/B]
+- [XBMC] Thumbnails sometimes turns into black box or Folder (XBMC not 
detecting when thumbnail is set and defaulting to icon?)
+- [XBMC] When sorting items, it's impossible to get them to return to their 
original order
+- [XBMC] Has Excessive Memory use after running the plugin for prolonged 
periods of time
+- [RTMPDUMP] Doesn't support handshake type 10 which is required by youtube.
+- [YOUTUBE] Requesting suggestions/recommendations from youtube sometimes 
stalls.
+
+[B]Version 3.4.8[/B]
+- Fixed login issues for all five login methods.
+- Refactored VEVO video playback code.
+
+[B]Version 3.4.7[/B]
+- Fixed a problem with VEVO videos not playing
+- Fixed a problem with LIVE streams not playing.
+- Fixed Login Problem with non English languages.
 - Fixed: When you are in a non English speaking country, youtube returns the 
pages by default in your language. The plugin sometimes gave an error in this 
situation.
 
 [B]Version 3.4.6[/B]
@@ -371,17 +382,3 @@ This version contains the sources by sogopot 
(http://forum.xbmc.org/showthread.p
 - Cleanup of listFeedFolder
 - Cleanup of listUserFolder
 - Added Viewed and Downloaded overlay to video items.
-
-Not current anymore:
-[B]TODO:[/B]
-- Fix RTMP support.
-- UTF8/16 does not work consistently(Verify failures against minidom 
implementation)
-- Embed playback fallback
-
-Not current anymore:
-[B]Errata[/B]
-- [XBMC] Thumbnails sometimes turns into black box or Folder (XBMC not 
detecting when thumbnail is set and defaulting to icon?)
-- [XBMC] When sorting items, it's impossible to get them to return to their 
original order
-- [XBMC] Has Excessive Memory use after running the plugin for prolonged 
periods of time
-- [RTMPDUMP] Doesn't support handshake type 10 which is required by youtube.
-- Youtube implemented encryption of signatures, without knowing the proper 
decryption method this VEVO content will remain unstable
diff --git a/plugin.video.youtube/default.py b/plugin.video.youtube/default.py
index dcfb5d0..f38ea0f 100644
--- a/plugin.video.youtube/default.py
+++ b/plugin.video.youtube/default.py
@@ -30,9 +30,9 @@ except ImportError:
     import xbmcvfsdummy as xbmcvfs
 
 # plugin constants
-version = "4.4.7"
+version = "4.4.8"
 plugin = "YouTube-" + version
-author = "TheCollective, Skipmode A1"
+author = "TheCollective"
 url = "www.xbmc.com"
 
 # xbmc hooks
diff --git a/plugin.video.youtube/resources/language/English/strings.xml 
b/plugin.video.youtube/resources/language/English/strings.xml
index 65dbcd7..6c2cd1a 100644
--- a/plugin.video.youtube/resources/language/English/strings.xml
+++ b/plugin.video.youtube/resources/language/English/strings.xml
@@ -220,4 +220,5 @@
     <string id="30627">Please provide 2-factor authentication PIN</string>
     <string id="30628">Please provide your password</string>
     <string id="30629">SSL protocol not supported.</string>
+    <string id="30630">Please re-login in your browser and retry</string>
 </strings>

-----------------------------------------------------------------------

Summary of changes:
 plugin.video.youtube/YouTubeCore.py                |   41 ++++--
 plugin.video.youtube/YouTubeLogin.py               |   59 +++++----
 plugin.video.youtube/YouTubeNavigation.py          |    3 +-
 plugin.video.youtube/YouTubePlayer.py              |  142 +++++++++-----------
 plugin.video.youtube/YouTubePlaylistControl.py     |    2 +-
 plugin.video.youtube/YouTubeSubtitleControl.py     |   12 +-
 plugin.video.youtube/addon.xml                     |   13 +--
 plugin.video.youtube/changelog.txt                 |   43 +++---
 plugin.video.youtube/default.py                    |    4 +-
 .../resources/language/English/strings.xml         |    1 +
 10 files changed, 163 insertions(+), 157 deletions(-)


hooks/post-receive
-- 
Plugins

------------------------------------------------------------------------------
Time is money. Stop wasting it! Get your web API in 5 minutes.
www.restlet.com/download
http://p.sf.net/sfu/restlet
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons

Reply via email to