flexget.plugins.plugin_cookies
Covered: 24 lines
Missed: 106 lines
Skipped 36 lines
Percent: 18 %
  1
import logging
  2
import urllib2
  3
import cookielib
  4
from flexget.plugin import PluginWarning, PluginError, register_plugin
  6
log = logging.getLogger('cookies')
  9
class PluginCookies:
 10
    """
 11
        Adds cookie to all requests (rss, resolvers, download). Anything
 12
        that uses urllib2 to be exact.
 14
        Currently supports Firefox 3 cookies only.
 16
        Example:
 18
        cookies: /path/firefox/profile/something/cookies.sqlite
 19
    """
 21
    def validator(self):
 22
        from flexget import validator
 23
        root = validator.factory()
 24
        root.accept('file')
 25
        cookies = root.accept('dict')
 26
        cookies.accept('file', key='file', required=True)
 27
        cookies.accept('choice', key='type').accept_choices(['firefox3', 'mozilla', 'lwp'])
 28
        return root
 30
    def get_config(self, feed):
 31
        config = feed.config.get('cookies', {})
 32
        if isinstance(config, basestring):
 33
            config = {'file': config}
 34
        if config['file'].endswith('.txt'):
 35
            config.setdefault('type', 'mozilla')
 36
        elif config['file'].endswith('.lwp'):
 37
            config.setdefault('type', 'lwp')
 38
        else:
 39
            config.setdefault('type', 'firefox3')
 40
        return config
 42
    def sqlite2cookie(self, filename):
 43
        from cStringIO import StringIO
 44
        try:
 45
            from pysqlite2 import dbapi2 as sqlite
 46
        except ImportError:
 47
            try:
 48
                from sqlite3 import dbapi2 as sqlite # try the 2.5+ stdlib
 49
            except ImportError:
 50
                raise PluginWarning('Unable to use sqlite3 or pysqlite2', log)
 52
        log.debug('connecting: %s' % filename)
 53
        try:
 54
            con = sqlite.connect(filename)
 55
        except:
 56
            raise PluginError('Unable to open cookies sqlite database')
 58
        cur = con.cursor()
 59
        try:
 60
            cur.execute('select host, path, isSecure, expiry, name, value from moz_cookies')
 61
        except:
 62
            raise PluginError('%s does not appear to be a valid Firefox 3 cookies file' % filename, log)
 64
        ftstr = ['FALSE', 'TRUE']
 66
        s = StringIO()
 67
        s.write("""\
 71
""")
 72
        count = 0
 73
        failed = 0
 75
        log.debug('fetching all cookies')
 77
        def notabs(val):
 78
            if isinstance(val, basestring):
 79
                return val.replace('\t', '')
 80
            return val
 82
        while True:
 83
            try:
 84
                item = cur.next()
 86
                item = [notabs(field) for field in item]
 87
                try:
 88
                    s.write('%s\t%s\t%s\t%s\t%s\t%s\t%s\n' % (item[0], ftstr[item[0].startswith('.')], item[1],
 89
                                                              ftstr[item[2]], item[3], item[4], item[5]))
 91
                    log.trace('Adding cookie for %s. key: %s value: %s' % (item[0], item[4], item[5]))
 92
                    count += 1
 93
                except:
 94
                    to_hex = lambda x: ''.join([hex(ord(c))[2:].zfill(2) for c in x])
 95
                    i = 0
 96
                    for val in item:
 97
                        if isinstance(val, basestring):
 98
                            log.debug('item[%s]: %s' % (i, to_hex(val)))
 99
                        else:
100
                            log.debug('item[%s]: %s' % (i, val))
101
                        i += 1
102
                    failed += 1
104
            except UnicodeDecodeError:
106
                log.debug('got UnicodeDecodeError from sqlite, ignored')
107
                failed += 1
108
            except StopIteration:
109
                break
111
        log.debug('Added %s cookies to jar. %s failed (non-ascii)' % (count, failed))
113
        s.seek(0)
114
        con.close()
116
        cookie_jar = cookielib.MozillaCookieJar()
117
        cookie_jar._really_load(s, '', True, True)
118
        return cookie_jar
120
    def on_feed_start(self, feed):
121
        """Feed starting, install cookiejar"""
122
        import os
123
        config = self.get_config(feed)
124
        cookie_type = config.get('type')
125
        cookie_file = os.path.expanduser(config.get('file'))
126
        if cookie_type == 'firefox3':
127
            log.debug('Loading %s cookies' % cookie_type)
128
            cj = self.sqlite2cookie(cookie_file)
129
        else:
130
            if cookie_type == 'mozilla':
131
                log.debug('Loading %s cookies' % cookie_type)
132
                cj = cookielib.MozillaCookieJar()
133
            elif cookie_type == 'lwp':
134
                log.debug('Loading %s cookies' % cookie_type)
135
                cj = cookielib.LWPCookieJar()
136
            else:
137
                raise PluginError('Unknown cookie type %s' % cookie_type, log)
139
            try:
140
                cj.load(filename=cookie_file, ignore_expires=True)
141
                log.debug('%s cookies loaded' % cookie_type)
142
            except (cookielib.LoadError, IOError):
143
                import sys
144
                raise PluginError('Cookies could not be loaded: %s' % sys.exc_info()[1], log)
147
        feed.requests.add_cookiejar(cj)
149
        handler = urllib2.HTTPCookieProcessor(cj)
150
        if urllib2._opener:
151
            log.debug('Adding HTTPCookieProcessor to default opener')
152
            urllib2._opener.add_handler(handler)
153
        else:
154
            log.debug('Creating new opener and installing it')
155
            urllib2.install_opener(urllib2.build_opener(handler))
157
    def on_feed_exit(self, feed):
158
        """Feed exiting, remove cookiejar"""
159
        log.debug('Removing urllib2 opener')
160
        urllib2.install_opener(None)
163
    on_feed_abort = on_feed_exit
165
register_plugin(PluginCookies, 'cookies')