diff --git a/CHANGES.md b/CHANGES.md
index 4446ffc221b0d80ab1aa6dbf2559eb93ad270339..f6093aaadeeba0fe8db98284f7b1e181d7ad36e2 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,35 @@
+### 4.0.30 (2015-07-09)
+
+[full changelog](https://github.com/SiCKRAGETV/SickRage/compare/v4.0.29...v4.0.30)
+
+* Fixed: Misc. Trakt problems
+* Fixed: Search strings with airdate
+* Fixed: PP issues
+* Fixed: Glob issue
+* Fixed: Kodi single show library update
+* Fixed: HDTorrents provider (and some others)
+* Fixed: Maxage not honored for NZB, resulting in dead snatches
+* Fixed: Encoding problems and unicode conversion errors
+* Fixed: Proxy and session
+* Fixed: Manage of unaired episode according to trakt rolling download if enabled
+* Added: API methods to check for update and run potential update
+* Added: BTDigg, FNT, BlueTigers torrent providers
+* Added: Babelfish (Dependency of Guessit)
+* Added: Device parameter for pushover notifications
+* Added: Log message when ignoring result from provider
+* Added: itorrents.org torrent caching website
+* Removed: www from HDT
+* Change: Torrent caching site urls are now selected at random
+* Change: Enable SSL certificate verification
+* Changed default episode status,it is auto set to wanted after add to show, change it to whatever you want then.
+* Changed errors to warnings in updater, when commit is newer than master or network unavailable
+* Updated: Provider icons
+* Updated: Subliminal to 0.8.0
+* Updated: Guessit
+* Updated: Cachecontrol
+* Updated: Enzyme
+* Updated: Subtitle provider icons
+
 ### 4.0.29 (2015-06-26)
 
 [full changelog](https://github.com/SiCKRAGETV/SickRage/compare/v4.0.28...v4.0.29)
diff --git a/gui/slick/images/providers/freshontv.png b/gui/slick/images/providers/freshontv.png
old mode 100755
new mode 100644
diff --git a/gui/slick/images/providers/morethantv.png b/gui/slick/images/providers/morethantv.png
old mode 100755
new mode 100644
diff --git a/gui/slick/interfaces/default/config_search.tmpl b/gui/slick/interfaces/default/config_search.tmpl
old mode 100755
new mode 100644
diff --git a/lib/scene_exceptions/__init__.py b/lib/scene_exceptions/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0ceb39b11fbd73963b90cc128348e520dbc14b9
--- /dev/null
+++ b/lib/scene_exceptions/__init__.py
@@ -0,0 +1,3 @@
+from os.path import dirname, abspath
+TVDB_EXCEPTIONS = dirname(abspath(__file__)) + '/tvdb/exceptions.txt'
+TVRAGE_EXCEPTIONS = dirname(abspath(__file__)) + '/tvrage/exceptions.txt'
diff --git a/lib/trakt/trakt.py b/lib/trakt/trakt.py
index d9f9069ac6e7697fb7b5ae3d93ec36e66dcf1f87..08808bf2a786cb5009b7f9eadec1838e6241544e 100644
--- a/lib/trakt/trakt.py
+++ b/lib/trakt/trakt.py
@@ -95,11 +95,11 @@ class TraktAPI():
                 # This is pretty much a fatal error if there is no status_code
                 # It means there basically was no response at all
                 raise traktException(e)
-            elif code == 502:
+            elif code is 502:
                 # Retry the request, cloudflare had a proxying issue
                 logger.log(u'Retrying trakt api request: %s' % path, logger.WARNING)
                 return self.traktRequest(path, data, headers, url, method)
-            elif code == 401:
+            elif code is 401:
                 logger.log(u'Unauthorized. Please check your Trakt settings', logger.WARNING)
                 if self.traktToken(refresh=True, count=count):
                     return self.traktRequest(path, data, headers, url, method)
@@ -108,6 +108,9 @@ class TraktAPI():
                 #http://docs.trakt.apiary.io/#introduction/status-codes
                 logger.log(u'Trakt may have some issues and it\'s unavailable. Try again later please', logger.WARNING)
                 return {}
+            elif code is 404:
+                logger.log(u'Trakt error (404) the resource does not exist: %s' % url + path, logger.WARNING)
+                return {}
             else:
                 raise traktException(e)
 
diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py
old mode 100755
new mode 100644
diff --git a/sickbeard/clients/transmission.py b/sickbeard/clients/transmission.py
old mode 100755
new mode 100644
diff --git a/sickbeard/config.py b/sickbeard/config.py
index b43aa65d330c420bfe1b57810ef655769b60b1ed..60a53756012661e0ff9d45cf49c1618aae8ec364 100644
--- a/sickbeard/config.py
+++ b/sickbeard/config.py
@@ -511,7 +511,7 @@ def check_setting_str(config, cfg_name, item_name, def_val, silent=True, censor_
             config[cfg_name] = {}
             config[cfg_name][item_name] = helpers.encrypt(my_val, encryption_version)
 
-    if censor_log or (cfg_name, item_name) in logger.censoredItems.items():
+    if censor_log or (cfg_name, item_name) in logger.censoredItems.iteritems():
         logger.censoredItems[cfg_name, item_name] = my_val
 
     if not silent:
diff --git a/sickbeard/dailysearcher.py b/sickbeard/dailysearcher.py
index ebf305ac020a8ab691023c7f0c3cc6aac5de1ff9..bd72ab250f5fc0360b3137154496ce01bc5f68fc 100644
--- a/sickbeard/dailysearcher.py
+++ b/sickbeard/dailysearcher.py
@@ -40,6 +40,8 @@ class DailySearcher():
         self.amActive = False
 
     def run(self, force=False):
+        if self.amActive:
+            return
 
         self.amActive = True
 
diff --git a/sickbeard/databases/cache_db.py b/sickbeard/databases/cache_db.py
index 8cfe5a4167c00eea6387823db1a1188d28b0e3b9..9734be453c48afe4e03f25d0a6028bfb60a447b6 100644
--- a/sickbeard/databases/cache_db.py
+++ b/sickbeard/databases/cache_db.py
@@ -24,15 +24,14 @@ class InitialSchema(db.SchemaUpgrade):
         return self.hasTable("db_version")
 
     def execute(self):
-
         queries = [
-            ("CREATE TABLE db_version (db_version INTEGER);",),
             ("CREATE TABLE lastUpdate (provider TEXT, time NUMERIC);",),
             ("CREATE TABLE lastSearch (provider TEXT, time NUMERIC);",),
             ("CREATE TABLE scene_exceptions (exception_id INTEGER PRIMARY KEY, indexer_id INTEGER KEY, show_name TEXT, season NUMERIC DEFAULT -1, custom NUMERIC DEFAULT 0);",),
             ("CREATE TABLE scene_names (indexer_id INTEGER, name TEXT);",),
             ("CREATE TABLE network_timezones (network_name TEXT PRIMARY KEY, timezone TEXT);",),
             ("CREATE TABLE scene_exceptions_refresh (list TEXT PRIMARY KEY, last_refreshed INTEGER);",),
+            ("CREATE TABLE db_version (db_version INTEGER);",),
             ("INSERT INTO db_version(db_version) VALUES (1);",),
         ]
         for query in queries:
@@ -48,14 +47,14 @@ class AddSceneExceptions(InitialSchema):
 
     def execute(self):
         self.connection.action(
-            "CREATE TABLE scene_exceptions (exception_id INTEGER PRIMARY KEY, indexer_id INTEGER KEY, show_name TEXT)")
+            "CREATE TABLE scene_exceptions (exception_id INTEGER PRIMARY KEY, indexer_id INTEGER KEY, show_name TEXT);")
 
 class AddSceneNameCache(AddSceneExceptions):
     def test(self):
         return self.hasTable("scene_names")
 
     def execute(self):
-        self.connection.action("CREATE TABLE scene_names (indexer_id INTEGER, name TEXT)")
+        self.connection.action("CREATE TABLE scene_names (indexer_id INTEGER, name TEXT);")
 
 
 class AddNetworkTimezones(AddSceneNameCache):
@@ -63,16 +62,16 @@ class AddNetworkTimezones(AddSceneNameCache):
         return self.hasTable("network_timezones")
 
     def execute(self):
-        self.connection.action("CREATE TABLE network_timezones (network_name TEXT PRIMARY KEY, timezone TEXT)")
+        self.connection.action("CREATE TABLE network_timezones (network_name TEXT PRIMARY KEY, timezone TEXT);")
 
 class AddLastSearch(AddNetworkTimezones):
     def test(self):
         return self.hasTable("lastSearch")
 
     def execute(self):
-        self.connection.action("CREATE TABLE lastSearch (provider TEXT, time NUMERIC)")
+        self.connection.action("CREATE TABLE lastSearch (provider TEXT, time NUMERIC);")
 
-class AddSceneExceptionsSeasons(AddSceneNameCache):
+class AddSceneExceptionsSeasons(AddLastSearch):
     def test(self):
         return self.hasColumn("scene_exceptions", "season")
 
@@ -92,4 +91,4 @@ class AddSceneExceptionsRefresh(AddSceneExceptionsCustom):
 
     def execute(self):
         self.connection.action(
-            "CREATE TABLE scene_exceptions_refresh (list TEXT PRIMARY KEY, last_refreshed INTEGER)")
+            "CREATE TABLE scene_exceptions_refresh (list TEXT PRIMARY KEY, last_refreshed INTEGER);")
diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py
index 2c9aefbc7ae3a992cb5c410ce8ee803cac8fbccd..2742bc70bf916ddd7f79dcf58a183a5a86198d93 100644
--- a/sickbeard/databases/mainDB.py
+++ b/sickbeard/databases/mainDB.py
@@ -162,7 +162,7 @@ class MainSanityCheck(db.DBSanityCheck):
             '': 'Unknown',
         }
 
-        for old_status, new_status in status_map.items():
+        for old_status, new_status in status_map.iteritems():
             self.connection.action("UPDATE tv_shows SET status = ? WHERE LOWER(status) = ?", [new_status, old_status])
 
     def fix_episode_statuses(self):
diff --git a/sickbeard/generic_queue.py b/sickbeard/generic_queue.py
index f97e348a73cf20023aced3b45d21477a91d43ee3..166c8aaa434afc79692ae55b4be6bcc01aef623a 100644
--- a/sickbeard/generic_queue.py
+++ b/sickbeard/generic_queue.py
@@ -50,47 +50,50 @@ class GenericQueue(object):
         self.min_priority = 0
 
     def add_item(self, item):
-        item.added = datetime.datetime.now()
-        self.queue.append(item)
+        with self.lock:
+            item.added = datetime.datetime.now()
+            self.queue.append(item)
 
-        return item
+            return item
 
     def run(self, force=False):
-
-        # only start a new task if one isn't already going
-        if self.currentItem is None or not self.currentItem.isAlive():
-
-            # if the thread is dead then the current item should be finished
-            if self.currentItem:
-                self.currentItem.finish()
-                self.currentItem = None
-
-            # if there's something in the queue then run it in a thread and take it out of the queue
-            if len(self.queue) > 0:
-
-                # sort by priority
-                def sorter(x, y):
-                    """
-                    Sorts by priority descending then time ascending
-                    """
-                    if x.priority == y.priority:
-                        if y.added == x.added:
-                            return 0
-                        elif y.added < x.added:
-                            return 1
-                        elif y.added > x.added:
-                            return -1
-                    else:
-                        return y.priority - x.priority
-
-                self.queue.sort(cmp=sorter)
-                if self.queue[0].priority < self.min_priority:
-                    return
-
-                # launch the queue item in a thread
-                self.currentItem = self.queue.pop(0)
-                self.currentItem.name = self.queue_name + '-' + self.currentItem.name
-                self.currentItem.start()
+        with self.lock:
+            # only start a new task if one isn't already going
+            if self.currentItem is None or not self.currentItem.isAlive():
+
+                # if the thread is dead then the current item should be finished
+                if self.currentItem:
+                    self.currentItem.finish()
+                    self.currentItem = None
+
+                # if there's something in the queue then run it in a thread and take it out of the queue
+                if len(self.queue) > 0:
+
+                    # sort by priority
+                    def sorter(x, y):
+                        """
+                        Sorts by priority descending then time ascending
+                        """
+                        if x.priority == y.priority:
+                            if y.added == x.added:
+                                return 0
+                            elif y.added < x.added:
+                                return 1
+                            elif y.added > x.added:
+                                return -1
+                        else:
+                            return y.priority - x.priority
+
+                    self.queue.sort(cmp=sorter)
+                    if self.queue[0].priority < self.min_priority:
+                        return
+
+                    # launch the queue item in a thread
+                    self.currentItem = self.queue.pop(0)
+                    self.currentItem.name = self.queue_name + '-' + self.currentItem.name
+                    self.currentItem.start()
+
+        self.amActive = False
 
 class QueueItem(threading.Thread):
     def __init__(self, name, action_id=0):
diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py
index b9f50e394e5e42884a1d836d38a6e2968568979f..e8fde7c714da8a639911be11c20f2f11416dc0af 100644
--- a/sickbeard/helpers.py
+++ b/sickbeard/helpers.py
@@ -134,6 +134,7 @@ def remove_non_release_groups(name):
                        '-NZBGEEK$':        'searchre',
                        '-RP$':             'searchre',
                        '-20-40$':          'searchre',
+                       '\[NO-RAR\] - \[ www\.torrentday\.com \]$': 'searchre',
                        '^\[ www\.TorrentDay\.com \] - ': 'searchre',
                        '^\[ www\.Cpasbien\.pw \] ': 'searchre',
                       }
diff --git a/sickbeard/indexers/indexer_config.py b/sickbeard/indexers/indexer_config.py
index 35c15e9771e9dd2eb9cb493c174389afd5501d0f..71e4ddc86371275ab303e1f8979d923e3d1b3a2b 100644
--- a/sickbeard/indexers/indexer_config.py
+++ b/sickbeard/indexers/indexer_config.py
@@ -1,5 +1,6 @@
 from lib.tvdb_api.tvdb_api import Tvdb
 from lib.tvrage_api.tvrage_api import TVRage
+from scene_exceptions import TVDB_EXCEPTIONS, TVRAGE_EXCEPTIONS
 import requests
 
 INDEXER_TVDB = 1
@@ -43,7 +44,7 @@ indexerConfig[INDEXER_TVRAGE] = {
 indexerConfig[INDEXER_TVDB]['trakt_id'] = 'tvdb_id'
 indexerConfig[INDEXER_TVDB]['xem_origin'] = 'tvdb'
 indexerConfig[INDEXER_TVDB]['icon'] = 'thetvdb16.png'
-indexerConfig[INDEXER_TVDB]['scene_loc'] = '../lib/scene_exceptions/tvdb/exceptions.txt'
+indexerConfig[INDEXER_TVDB]['scene_loc'] = TVDB_EXCEPTIONS
 indexerConfig[INDEXER_TVDB]['show_url'] = 'http://thetvdb.com/?tab=series&id='
 indexerConfig[INDEXER_TVDB]['base_url'] = 'http://thetvdb.com/api/%(apikey)s/series/' % indexerConfig[INDEXER_TVDB]['api_params']
 
@@ -51,6 +52,6 @@ indexerConfig[INDEXER_TVDB]['base_url'] = 'http://thetvdb.com/api/%(apikey)s/ser
 indexerConfig[INDEXER_TVRAGE]['trakt_id'] = 'tvrage_id'
 indexerConfig[INDEXER_TVRAGE]['xem_origin'] = 'rage'
 indexerConfig[INDEXER_TVRAGE]['icon'] = 'tvrage16.png'
-indexerConfig[INDEXER_TVRAGE]['scene_loc'] = '../lib/scene_exceptions/tvrage/exceptions.txt'
+indexerConfig[INDEXER_TVRAGE]['scene_loc'] = TVRAGE_EXCEPTIONS
 indexerConfig[INDEXER_TVRAGE]['show_url'] = 'http://tvrage.com/shows/id-'
 indexerConfig[INDEXER_TVRAGE]['base_url'] = 'http://tvrage.com/showinfo.php?key=%(apikey)s&sid=' % indexerConfig[INDEXER_TVRAGE]['api_params']
diff --git a/sickbeard/logger.py b/sickbeard/logger.py
index f5e0d92ffbbda5e0fd300a9ff53922cd24fe0155..b991c9f6be4e3e7c30b5189c03709f4e819bb0bb 100644
--- a/sickbeard/logger.py
+++ b/sickbeard/logger.py
@@ -58,7 +58,7 @@ class CensoredFormatter(logging.Formatter, object):
 
     def format(self, record):
         msg = super(CensoredFormatter, self).format(record)
-        for k, v in censoredItems.items():
+        for k, v in censoredItems.iteritems():
             if v and len(v) > 0 and v in msg:
                 msg = msg.replace(v, len(v) * '*')
         # Needed because Newznab apikey isn't stored as key=value in a section.
diff --git a/sickbeard/name_cache.py b/sickbeard/name_cache.py
index eefa235285508082b4d69ce997915c7c1ae27c88..a349a8da6589ffc4a5521f634501c77b03e144d8 100644
--- a/sickbeard/name_cache.py
+++ b/sickbeard/name_cache.py
@@ -77,7 +77,7 @@ def clearCache(indexerid=0):
 def saveNameCacheToDb():
     cacheDB = db.DBConnection('cache.db')
 
-    for name, indexer_id in nameCache.items():
+    for name, indexer_id in nameCache.iteritems():
         cacheDB.action("INSERT OR REPLACE INTO scene_names (indexer_id, name) VALUES (?, ?)", [indexer_id, name])
 
 
diff --git a/sickbeard/network_timezones.py b/sickbeard/network_timezones.py
index 6a1805760f6be3d32c6a5ace9f87a01355ecc32e..b01d9a3a072bdb1a6ab3f4c6e7c3eafba81cea68 100644
--- a/sickbeard/network_timezones.py
+++ b/sickbeard/network_timezones.py
@@ -171,22 +171,22 @@ def update_network_dict():
 
     my_db = db.DBConnection('cache.db')
 
-    network_list = dict(my_db.select('SELECT * FROM network_timezones'))
+    network_list = dict(my_db.select('SELECT * FROM network_timezones;'))
 
     queries = []
     for network, timezone in d.iteritems():
         existing = network_list.has_key(network)
         if not existing:
-            queries.append(['INSERT OR IGNORE INTO network_timezones VALUES (?,?)', [network, timezone]])
+            queries.append(['INSERT OR IGNORE INTO network_timezones VALUES (?,?);', [network, timezone]])
         elif network_list[network] is not timezone:
-            queries.append(['UPDATE OR IGNORE network_timezones SET timezone = ? WHERE network_name = ?', [timezone, network]])
+            queries.append(['UPDATE OR IGNORE network_timezones SET timezone = ? WHERE network_name = ?;', [timezone, network]])
 
         if existing:
             del network_list[network]
 
     if network_list:
         purged = list(x for x in network_list)
-        queries.append(['DELETE FROM network_timezones WHERE network_name IN (%s)' % ','.join(['?'] * len(purged)), purged])
+        queries.append(['DELETE FROM network_timezones WHERE network_name IN (%s);' % ','.join(['?'] * len(purged)), purged])
 
     if queries:
         my_db.mass_action(queries)
@@ -197,10 +197,10 @@ def update_network_dict():
 def load_network_dict():
     try:
         my_db = db.DBConnection('cache.db')
-        cur_network_list = my_db.select('SELECT * FROM network_timezones')
+        cur_network_list = my_db.select('SELECT * FROM network_timezones;')
         if cur_network_list is None or len(cur_network_list) < 1:
             update_network_dict()
-            cur_network_list = my_db.select('SELECT * FROM network_timezones')
+            cur_network_list = my_db.select('SELECT * FROM network_timezones;')
         d = dict(cur_network_list)
     except:
         d = {}
diff --git a/sickbeard/notifiers/boxcar2.py b/sickbeard/notifiers/boxcar2.py
old mode 100755
new mode 100644
diff --git a/sickbeard/notifiers/plex.py b/sickbeard/notifiers/plex.py
index c67aa8f119dbed59dd70dcf551471e748ad874ad..de496dfef0211a8b4e526c6f2f835b8903f663e1 100644
--- a/sickbeard/notifiers/plex.py
+++ b/sickbeard/notifiers/plex.py
@@ -258,7 +258,7 @@ class PLEXNotifier:
 
             hosts_try = (hosts_all.copy(), hosts_match.copy())[len(hosts_match)]
             host_list = []
-            for section_key, cur_host in hosts_try.items():
+            for section_key, cur_host in hosts_try.iteritems():
 
                 url = 'http://%s/library/sections/%s/refresh%s' % (cur_host, section_key, token_arg)
                 try:
diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py
index 79fb54854f3efd8169401f459f7e226e60b29e31..a6e634812303ecfb1cc084315aa5e1d93a31ae13 100644
--- a/sickbeard/providers/__init__.py
+++ b/sickbeard/providers/__init__.py
@@ -68,6 +68,11 @@ def sortedProviderList(randomize=False):
         if curModule in providerDict:
             newList.append(providerDict[curModule])
 
+    # add all enabled providers first
+    for curModule in providerDict:
+        if providerDict[curModule] not in newList and providerDict[curModule].isEnabled():
+            newList.append(providerDict[curModule])
+
     # add any modules that are missing from that list
     for curModule in providerDict:
         if providerDict[curModule] not in newList:
diff --git a/sickbeard/providers/btn.py b/sickbeard/providers/btn.py
index 3bbab68f48389d69409053de284aad35c1e90613..5470838b4dbe407df2e252fc54d02576a870a32d 100644
--- a/sickbeard/providers/btn.py
+++ b/sickbeard/providers/btn.py
@@ -353,7 +353,7 @@ class BTNProvider(generic.TorrentProvider):
                     else:
                         items[quality].append(item)
 
-            itemList = list(itertools.chain(*[v for (k, v) in sorted(items.items(), reverse=True)]))
+            itemList = list(itertools.chain(*[v for (k, v) in sorted(items.iteritems(), reverse=True)]))
             itemList += itemsUnknown if itemsUnknown else []
 
         # filter results
diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py
index 86398aa4c378cdb90cb62dbec35617e4b61ec522..a183d7d2d68274988f379ccfb509aaa109895770 100644
--- a/sickbeard/providers/generic.py
+++ b/sickbeard/providers/generic.py
@@ -62,6 +62,8 @@ class GenericProvider:
 
         self.search_mode = None
         self.search_fallback = False
+
+        self.enabled = False
         self.enable_daily = False
         self.enable_backlog = False
 
@@ -375,7 +377,7 @@ class GenericProvider:
                     else:
                         items[quality].append(item)
 
-            itemList = list(itertools.chain(*[v for (k, v) in sorted(items.items(), reverse=True)]))
+            itemList = list(itertools.chain(*[v for (k, v) in sorted(items.iteritems(), reverse=True)]))
             itemList += itemsUnknown if itemsUnknown else []
 
         # filter results
diff --git a/sickbeard/providers/iptorrents.py b/sickbeard/providers/iptorrents.py
index 485459f3acbac95d36cf837b1583b663200d9b44..f2574442a79669e0db2c7008ca1d3d3912954cc0 100644
--- a/sickbeard/providers/iptorrents.py
+++ b/sickbeard/providers/iptorrents.py
@@ -186,7 +186,7 @@ class IPTorrentsProvider(generic.TorrentProvider):
                     else:
                         items[quality].append(item)
 
-            itemList = list(itertools.chain(*[v for (k, v) in sorted(items.items(), reverse=True)]))
+            itemList = list(itertools.chain(*[v for (k, v) in sorted(items.iteritems(), reverse=True)]))
             itemList += itemsUnknown if itemsUnknown else []
 
         # filter results
diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py
index 85db5e81c84cc5b77b9d7a091a38ed6a728c3bb8..58206969fb4e2b308454fbfcefc000c84cbf7c2a 100644
--- a/sickbeard/providers/newznab.py
+++ b/sickbeard/providers/newznab.py
@@ -107,9 +107,9 @@ class NewznabProvider(generic.NZBProvider):
             data = self.cache.getRSSFeed("%s/api?%s" % (self.url, urllib.urlencode(params)))
         except:
             logger.log(u"Error getting html for [%s]" % 
-                    ("%s/api?%s" % (self.url, '&'.join("%s=%s" % (x,y) for x,y in params.items())) ), logger.DEBUG)
+                    ("%s/api?%s" % (self.url, '&'.join("%s=%s" % (x,y) for x,y in params.iteritems())) ), logger.DEBUG)
             return (False, return_categories, "Error getting html for [%s]" % 
-                    ("%s/api?%s" % (self.url, '&'.join("%s=%s" % (x,y) for x,y in params.items()) )))
+                    ("%s/api?%s" % (self.url, '&'.join("%s=%s" % (x,y) for x,y in params.iteritems()) )))
 
         if not self._checkAuthFromData(data):
             logger.log(u"Error parsing xml for [%s]" % (self.name), logger.DEBUG)
@@ -198,7 +198,7 @@ class NewznabProvider(generic.NZBProvider):
             if add_string:
                 params['q'] += ' ' + add_string
 
-            to_return.append(params)
+            to_return.append(dict(params))
 
             if ep_obj.show.anime:
                 paramsNoEp = params.copy()
diff --git a/sickbeard/providers/tntvillage.py b/sickbeard/providers/tntvillage.py
index d8b2b9aa2feb969e0fad7c8eade4c17a9349e9b4..84d07f15510bc8df422173d8473946f07293456f 100644
--- a/sickbeard/providers/tntvillage.py
+++ b/sickbeard/providers/tntvillage.py
@@ -302,6 +302,9 @@ class TNTVillageProvider(generic.TorrentProvider):
 
         name = str(span_tag)
 
+        if not name:
+            return 0
+
         subFound=0
 
         for sub in self.sub_string:
diff --git a/sickbeard/scene_exceptions.py b/sickbeard/scene_exceptions.py
index ae1e920d0b63e122c4633d0b9e54b1d37c18e805..063ab210671150c89f3c0aad6845de97674f4e28 100644
--- a/sickbeard/scene_exceptions.py
+++ b/sickbeard/scene_exceptions.py
@@ -223,30 +223,22 @@ def retrieve_exceptions():
         else:
             exception_dict[anidb_ex] = anidb_exception_dict[anidb_ex]
 
-    changed_exceptions = False
-
-    # write all the exceptions we got off the net into the database
+    queries = []
     myDB = db.DBConnection('cache.db')
     for cur_indexer_id in exception_dict:
-
-        # get a list of the existing exceptions for this ID
-        existing_exceptions = [x["show_name"] for x in
-                               myDB.select("SELECT * FROM scene_exceptions WHERE indexer_id = ?", [cur_indexer_id])]
-
+        sql_ex = myDB.select("SELECT * FROM scene_exceptions WHERE indexer_id = ?;", [cur_indexer_id])
+        existing_exceptions = [x["show_name"] for x in sql_ex]
         if not cur_indexer_id in exception_dict:
             continue
 
         for cur_exception_dict in exception_dict[cur_indexer_id]:
-            cur_exception, curSeason = cur_exception_dict.items()[0]
-
-            # if this exception isn't already in the DB then add it
-            if cur_exception not in existing_exceptions:
-                myDB.action("INSERT INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?)",
-                            [cur_indexer_id, cur_exception, curSeason])
-                changed_exceptions = True
-
-    # since this could invalidate the results of the cache we clear it out after updating
-    if changed_exceptions:
+            for ex in cur_exception_dict.iteritems():
+                cur_exception, curSeason = ex
+                if cur_exception not in existing_exceptions:
+                    queries.append(["INSERT OR IGNORE INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?);",
+                            [cur_indexer_id, cur_exception, curSeason]])
+    if queries:
+        myDB.mass_action(queries)
         logger.log(u"Updated scene exceptions", logger.DEBUG)
     else:
         logger.log(u"No scene exceptions update needed", logger.DEBUG)
@@ -316,7 +308,7 @@ def _xem_exceptions_fetcher():
             if parsedJSON['result'] == 'failure':
                 continue
 
-            for indexerid, names in parsedJSON['data'].items():
+            for indexerid, names in parsedJSON['data'].iteritems():
                 try:
                     xem_exception_dict[int(indexerid)] = names
                 except Exception as e:
diff --git a/sickbeard/search.py b/sickbeard/search.py
index 5c3b8e8f7325a22c7a6a10f8daecc5821a8f1027..d56bfab67dc6d3ccf8ad88b90fdf40c8b7a64a03 100644
--- a/sickbeard/search.py
+++ b/sickbeard/search.py
@@ -321,19 +321,14 @@ def isFirstBestMatch(result):
     return False
 
 def wantedEpisodes(show, fromDate):
+
     anyQualities, bestQualities = common.Quality.splitQuality(show.quality) # @UnusedVariable
     allQualities = list(set(anyQualities + bestQualities))
 
     logger.log(u"Seeing if we need anything from " + show.name, logger.DEBUG)
     myDB = db.DBConnection()
 
-    if show.air_by_date:
-        sqlResults = myDB.select(
-            "SELECT ep.status, ep.season, ep.episode FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 AND ep.airdate > ? AND ep.showid = ? AND show.air_by_date = 1",
-        [fromDate.toordinal(), show.indexerid])
-    else:
-        sqlResults = myDB.select(
-            "SELECT status, season, episode FROM tv_episodes WHERE showid = ? AND season > 0 and airdate > ?",
+    sqlResults = myDB.select("SELECT status, season, episode FROM tv_episodes WHERE showid = ? AND season > 0 and airdate > ?",
             [show.indexerid, fromDate.toordinal()])
 
     # check through the list of statuses to see if we want any
diff --git a/sickbeard/searchBacklog.py b/sickbeard/searchBacklog.py
index fc50b66bfc517327f096a2d5306ed3f99a1ba023..0c36135bb080712f271c0235a726857bdd07cd1e 100644
--- a/sickbeard/searchBacklog.py
+++ b/sickbeard/searchBacklog.py
@@ -74,6 +74,9 @@ class BacklogSearcher:
             logger.log(u"Backlog is still running, not starting it again", logger.DEBUG)
             return
 
+        self.amActive = True
+        self.amPaused = False
+
         if which_shows:
             show_list = which_shows
         else:
@@ -84,13 +87,10 @@ class BacklogSearcher:
         curDate = datetime.date.today().toordinal()
         fromDate = datetime.date.fromordinal(1)
 
-        if not which_shows and not curDate - self._lastBacklog >= self.cycleTime:
+        if not which_shows and not ((curDate - self._lastBacklog) >= self.cycleTime):
             logger.log(u"Running limited backlog on missed episodes " + str(sickbeard.BACKLOG_DAYS) + " day(s) and older only")
             fromDate = datetime.date.today() - datetime.timedelta(days=sickbeard.BACKLOG_DAYS)
 
-        self.amActive = True
-        self.amPaused = False
-
         # go through non air-by-date shows and see if they need any episodes
         for curShow in show_list:
 
@@ -99,7 +99,7 @@ class BacklogSearcher:
 
             segments = self._get_segments(curShow, fromDate)
 
-            for season, segment in segments.items():
+            for season, segment in segments.iteritems():
                 self.currentSearchInfo = {'title': curShow.name + " Season " + str(season)}
 
                 backlog_queue_item = search_queue.BacklogQueueItem(curShow, segment)
@@ -135,19 +135,17 @@ class BacklogSearcher:
         return self._lastBacklog
 
     def _get_segments(self, show, fromDate):
+        if show.paused:
+            logger.log(u"Skipping backlog for {show_name} because the show is paused".format(show_name=show.name), logger.DEBUG)
+            return {}
+
         anyQualities, bestQualities = common.Quality.splitQuality(show.quality)  # @UnusedVariable
 
         logger.log(u"Seeing if we need anything from {show_name}".format(show_name=show.name), logger.DEBUG)
 
         myDB = db.DBConnection()
-        if show.air_by_date:
-            sqlResults = myDB.select(
-                "SELECT ep.status, ep.season, ep.episode FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 AND ep.airdate > ? AND ep.showid = ? AND show.air_by_date = 1",
+        sqlResults = myDB.select("SELECT status, season, episode FROM tv_episodes WHERE season > 0 AND airdate > ? AND showid = ?",
                 [fromDate.toordinal(), show.indexerid])
-        else:
-            sqlResults = myDB.select(
-                "SELECT status, season, episode FROM tv_episodes WHERE showid = ? AND season > 0 and airdate > ?",
-                [show.indexerid, fromDate.toordinal()])
 
         # check through the list of statuses to see if we want any
         wanted = {}
diff --git a/sickbeard/tv.py b/sickbeard/tv.py
index 57306807dfb86ce2c5cfaf21e75eae72ab595c8a..7e1b1c103ed1a4d0d81497d460cc98e281cc8c32 100644
--- a/sickbeard/tv.py
+++ b/sickbeard/tv.py
@@ -965,7 +965,7 @@ class TVShow(object):
 
             # Rename dict keys without spaces for DB upsert
             self.imdb_info = dict(
-                (k.replace(' ', '_'), k(v) if hasattr(v, 'keys') else v) for k, v in imdb_info.items())
+                (k.replace(' ', '_'), k(v) if hasattr(v, 'keys') else v) for k, v in imdb_info.iteritems())
             logger.log(str(self.indexerid) + u": Obtained info from IMDb ->" + str(self.imdb_info), logger.DEBUG)
 
     def nextEpisode(self):
@@ -1453,46 +1453,17 @@ class TVEpisode(object):
 
             providers = sickbeard.subtitles.getEnabledServiceList()
             vname = self.location
-            create_link = False
-            if self.release_name:
-                try:
-                    dir, name = ek.ek(os.path.split, self.location)
-                    tmp = ek.ek(os.path.join, dir, self.release_name)
-                    if ek.ek(os.path.splitext, tmp)[-1] is not ek.ek(os.path.splitext, self.location)[-1]:
-                        tmp += ek.ek(os.path.splitext, self.location)[-1]
-
-                    create_link = not ek.ek(os.path.exists, tmp)
-                    if create_link:
-                        ek.ek(helpers.link, self.location, tmp)
-                    vname = tmp
-                except Exception:
-                    create_link = False
-                    vname = self.location
-                    pass
-            else:
-                logger.log(u'%s: No release name for S%02dE%02d, using existing file name' %
-                      (self.show.indexerid, self.season, self.episode), logger.DEBUG)
-
             video = None
             try:
                 video = subliminal.scan_video(vname, subtitles=not force, embedded_subtitles=not sickbeard.EMBEDDED_SUBTITLES_ALL or not force)
             except Exception:
                 logger.log(u'%s: Exception caught in subliminal.scan_video for S%02dE%02d' %
                     (self.show.indexerid, self.season, self.episode), logger.DEBUG)
-                if create_link and vname is not self.location:
-                    ek.ek(os.unlink, vname)
                 return
                 pass
 
-            if create_link and vname is not self.location:
-                ek.ek(os.unlink, vname)
-
-            #video.tvdb_id = self.show.indexerid
-            #video.imdb_id = self.show.imdbid
-            #if not video.title and self.name:
-            #    video.title = self.name
-            #if not video.release_group and self.release_group:
-            #    video.release_group = self.release_group
+            if not video:
+                return
 
             # TODO: Add gui option for hearing_impaired parameter ?
             foundSubs = subliminal.download_best_subtitles([video], languages=languages, providers=providers, single=not sickbeard.SUBTITLES_MULTI, hearing_impaired=False)
@@ -1504,35 +1475,20 @@ class TVEpisode(object):
                 # absolute path (GUI 'Browse' button, or typed absolute path) - sillyness?
                 if ek.ek(os.path.exists, sickbeard.SUBTITLES_DIR):
                     subs_new_path = ek.ek(os.path.join, sickbeard.SUBTITLES_DIR, self.show.name)
-                    dir_exists = True
                 else:
                     # relative to the folder the episode is in - sillyness?
-                    subs_new_path = ek.ek(os.path.join, os.path.dirname(self.location), sickbeard.SUBTITLES_DIR)
+                    subs_new_path = ek.ek(os.path.join, ek.ek(os.path.dirname, self.location), sickbeard.SUBTITLES_DIR)
                     dir_exists = helpers.makeDir(subs_new_path)
 
-                if not dir_exists:
-                    logger.log(u'Unable to create subtitles folder ' + subs_new_path, logger.ERROR)
-                else:
-                    helpers.chmodAsParent(subs_new_path)
+                    if not dir_exists:
+                        logger.log(u'Unable to create subtitles folder ' + subs_new_path, logger.ERROR)
+                    else:
+                        helpers.chmodAsParent(subs_new_path)
             else:
-                # let subliminal save the subtitles next to the episode
                 subs_new_path = None
 
             subliminal.save_subtitles(foundSubs, directory=subs_new_path, single=not sickbeard.SUBTITLES_MULTI)
 
-            # rename the subtitles if needed
-            if create_link:
-                for video, subs in foundSubs.items():
-                    for sub in subs:
-                        path = subliminal.subtitle.get_subtitle_path(video.name, sub.language if sickbeard.SUBTITLES_MULTI else None)
-                        if subs_new_path:
-                            path = ek.ek(os.path.join, subs_new_path, ek.ek(os.path.split, path)[1])
-
-                        new_path = path.replace(ek.ek(os.path.splitext, vname)[0],
-                        ek.ek(os.path.splitext, ek.ek(os.path.basename, self.location))[0])
-                        if ek.ek(os.path.exists, path) and not ek.ek(os.path.exists, new_path):
-                            ek.ek(os.rename, path, new_path)
-
         except Exception as e:
             logger.log("Error occurred when downloading subtitles: " + traceback.format_exc(), logger.ERROR)
             return
@@ -1555,7 +1511,7 @@ class TVEpisode(object):
                     (self.show.indexerid, self.season, self.episode), logger.DEBUG)
 
         if sickbeard.SUBTITLES_HISTORY:
-            for video, subs in foundSubs.items():
+            for video, subs in foundSubs.iteritems():
                 for sub in subs:
                     logger.log(u'history.logSubtitle %s, %s' % (sub.provider_name, sub.language.alpha3), logger.DEBUG)
                     history.logSubtitle(self.show.indexerid, self.season, self.episode, self.status, sub)
diff --git a/sickbeard/webapi.py b/sickbeard/webapi.py
index 0c62e0d4c7e72a95cd060ffaece781774df2abd2..c3c0eba0edd92afbd5ba2dc612b0f58168a113a8 100644
--- a/sickbeard/webapi.py
+++ b/sickbeard/webapi.py
@@ -85,7 +85,7 @@ class ApiHandler(RequestHandler):
 
     def get(self, *args, **kwargs):
         kwargs = self.request.arguments
-        for arg, value in kwargs.items():
+        for arg, value in kwargs.iteritems():
             if len(value) == 1:
                 kwargs[arg] = value[0]
 
@@ -1025,7 +1025,7 @@ class CMD_EpisodeSetStatus(ApiCall):
 
         extra_msg = ""
         if start_backlog:
-            for season, segment in segments.items():
+            for season, segment in segments.iteritems():
                 cur_backlog_queue_item = search_queue.BacklogQueueItem(showObj, segment)
                 sickbeard.searchQueueScheduler.action.add_item(cur_backlog_queue_item)  # @UndefinedVariable
 
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index d769133549867c3dc0de7f4714d80faec068e3f2..144dcf24dc67a413402ab645fe134caad6390169 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -262,7 +262,7 @@ class WebHandler(BaseHandler):
     def async_call(self, function):
         try:
             kwargs = self.request.arguments
-            for arg, value in kwargs.items():
+            for arg, value in kwargs.iteritems():
                 if len(value) == 1:
                     kwargs[arg] = value[0]
 
@@ -1784,7 +1784,7 @@ class Home(WebRoot):
             msg = "Backlog was automatically started for the following seasons of <b>" + showObj.name + "</b>:<br />"
             msg += '<ul>'
 
-            for season, segment in segments.items():
+            for season, segment in segments.iteritems():
                 cur_backlog_queue_item = search_queue.BacklogQueueItem(showObj, segment)
                 sickbeard.searchQueueScheduler.action.add_item(cur_backlog_queue_item)
 
@@ -1803,7 +1803,7 @@ class Home(WebRoot):
             msg = "Retrying Search was automatically started for the following season of <b>" + showObj.name + "</b>:<br />"
             msg += '<ul>'
 
-            for season, segment in segments.items():
+            for season, segment in segments.iteritems():
                 cur_failed_queue_item = search_queue.FailedQueueItem(showObj, segment)
                 sickbeard.searchQueueScheduler.action.add_item(cur_failed_queue_item)
 
@@ -2033,12 +2033,10 @@ class Home(WebRoot):
         newSubtitles = frozenset(ep_obj.subtitles).difference(previous_subtitles)
         if newSubtitles:
             newLangs = [subtitles.fromietf(newSub) for newSub in newSubtitles]
-            status = 'New subtitles downloaded: %s' % ' '.join([
-                "<img src='" + sickbeard.WEB_ROOT + "/images/flags/" + newLang.alpha3 +
-                ".png' alt='" + newLang.name + "'/>" for newLang in newLangs])
+            status = 'New subtitles downloaded: %s' % ', '.join([newLang.name for newLang in newLangs])
         else:
             status = 'No subtitles downloaded'
-        ui.notifications.message('Subtitles Search', status)
+        ui.notifications.message(ep_obj.show.name, status)
         return json.dumps({'result': status, 'subtitles': ','.join(ep_obj.subtitles)})
 
     def setSceneNumbering(self, show, indexer, forSeason=None, forEpisode=None, forAbsolute=None, sceneSeason=None,
@@ -2235,7 +2233,7 @@ class HomeAddShows(Home):
 
         map(final_results.extend,
             ([[sickbeard.indexerApi(id).name, id, sickbeard.indexerApi(id).config["show_url"], int(show['id']),
-               show['seriesname'], show['firstaired']] for show in shows] for id, shows in results.items()))
+               show['seriesname'], show['firstaired']] for show in shows] for id, shows in results.iteritems()))
 
         lang_id = sickbeard.indexerApi().config['langabbv_to_id'][lang]
         return json.dumps({'results': final_results, 'langid': lang_id})
@@ -4406,6 +4404,7 @@ class ConfigProviders(Config):
             if curProvider.getID() not in finishedNames:
                 sickbeard.torrentRssProviderList.remove(curProvider)
 
+        disabled_list = []
         # do the enable/disable
         for curProviderStr in provider_str_list:
             curProvider, curEnabled = curProviderStr.split(':')
@@ -4416,12 +4415,18 @@ class ConfigProviders(Config):
             if curProvObj:
                 curProvObj[0].enabled = bool(curEnabled)
 
-            provider_list.append(curProvider)
+            if curEnabled:
+                provider_list.append(curProvider)
+            else:
+                disabled_list.append(curProvider)
+
             if curProvider in newznabProviderDict:
                 newznabProviderDict[curProvider].enabled = bool(curEnabled)
             elif curProvider in torrentRssProviderDict:
                 torrentRssProviderDict[curProvider].enabled = bool(curEnabled)
 
+        provider_list = provider_list + disabled_list
+
         # dynamically load provider settings
         for curTorrentProvider in [curProvider for curProvider in sickbeard.providers.sortedProviderList() if
                                    curProvider.providerType == sickbeard.GenericProvider.TORRENT]: