diff --git a/data/images/scn-no.gif b/data/images/scn-no.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d85c844f693dcc63e26e96a0fce8d1e22035b326
Binary files /dev/null and b/data/images/scn-no.gif differ
diff --git a/data/images/scn.gif b/data/images/scn.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f345d2147a013cfdd542443447be220ac9ce3ebc
Binary files /dev/null and b/data/images/scn.gif differ
diff --git a/data/interfaces/default/displayShow.tmpl b/data/interfaces/default/displayShow.tmpl
index 6d80153187262e90aa9ac8cd9b32974f2aad9f7b..d9461bfab80a9392fd28a407470b72a18219eaf7 100644
--- a/data/interfaces/default/displayShow.tmpl
+++ b/data/interfaces/default/displayShow.tmpl
@@ -293,13 +293,17 @@
   #end if	
 
   #if int($epResult["season"]) != $curSeason:
-  <tr><td colspan="9"  style="height: 0px; padding:0; margin:0;"><a name="season-$epResult["season"]"></a></td></tr>
+  <tr><td colspan="#if $showSceneNumberColum then "10" else "9"#"  style="height: 0px; padding:0; margin:0;"><a name="season-$epResult["season"]"></a></td></tr>
   <tr class="seasonheader" id="season-$epResult["season"]" >
-    <td colspan="9">
+    <td colspan="#if $showSceneNumberColum then "10" else "9"#">
         <h2>#if int($epResult["season"]) == 0 then "Specials" else "Season "+str($epResult["season"])#</h2>
     </td>
   </tr>
-  <tr id="season-$epResult["season"]-cols"><th width="1%"><input type="checkbox" class="seasonCheck" id="$epResult["season"]" /></th><th>Episode</th><th>Name</th><th class="nowrap">Airdate</th><th>Filename</th><th>Audio</th>#if $sickbeard.USE_SUBTITLES and $show.subtitles then "<th>Subs</th>" else ""#<th>Status</th><th>Search</th><th>Hist</th></tr>
+  <tr id="season-$epResult["season"]-cols"><th width="1%"><input type="checkbox" class="seasonCheck" id="$epResult["season"]" />
+  #if $showSceneNumberColum
+  <th>XEM</th>
+  #end if
+  </th><th>Episode</th><th>Name</th><th class="nowrap">Airdate</th><th>Filename</th><th>Audio</th>#if $sickbeard.USE_SUBTITLES and $show.subtitles then "<th>Subs</th>" else ""#<th>Status</th><th>Search</th><th>Hist</th></tr>
         #set $curSeason = int($epResult["season"])
   #end if    
 
@@ -311,6 +315,15 @@
       <input type="checkbox" class="epCheck" id="<%=str(epResult["season"])+'x'+str(epResult["episode"])%>" name="<%=str(epResult["season"]) +"x"+str(epResult["episode"]) %>" />
 #end if
     </td>
+    #if $showSceneNumberColum
+    <td align="center">
+    #if isinstance($epResult["scene_season"], int) and isinstance($epResult["scene_episode"], int)
+    <img src="$sbRoot/images/scn.gif" alt="Y" width="16" height="16" title="Scene number $epResult["scene_season"] x $epResult["scene_episode"]"/>
+    #else
+    <img src="$sbRoot/images/scn-no.gif" alt="N" width="16" height="16" title="No scene number" />
+    #end if
+    </td>
+    #end if
     <td align="center">$epResult["episode"]</td>
     <td class="title">
     #if $epResult["description"] != "" and $epResult["description"] != None:
diff --git a/lib/dateutil/zoneinfo/zoneinfo-2013g.tar.gz b/lib/dateutil/zoneinfo/zoneinfo-2013g.tar.gz
deleted file mode 100644
index a3bce5b9d668a864ecc7d6299eae3ca83d596e63..0000000000000000000000000000000000000000
Binary files a/lib/dateutil/zoneinfo/zoneinfo-2013g.tar.gz and /dev/null differ
diff --git a/lib/dateutil/zoneinfo/zoneinfo-2013h.tar.gz b/lib/dateutil/zoneinfo/zoneinfo-2013h.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..53303b1a83fdf2b72777d266cf953cdc4111438e
Binary files /dev/null and b/lib/dateutil/zoneinfo/zoneinfo-2013h.tar.gz differ
diff --git a/sickbeard/databases/cache_db.py b/sickbeard/databases/cache_db.py
index 5675ab8b745db0f04689d8cd8f9c22cd03e96948..97a71c495e92dd3e756c45714dbd838fa2cc8f75 100644
--- a/sickbeard/databases/cache_db.py
+++ b/sickbeard/databases/cache_db.py
@@ -55,4 +55,10 @@ 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)")
\ No newline at end of file
+        self.connection.action("CREATE TABLE network_timezones (network_name TEXT PRIMARY KEY, timezone TEXT)")
+
+class AddSceneExceptionsSeasons(AddNetworkTimezones):
+    def test(self):
+        return self.hasColumn("scene_exceptions", "season")
+    def execute(self):
+        self.addColumn("scene_exceptions", "season", "NUMERIC", -1)
diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py
index 83ce8c644dae5c06e0ec3ff2a6277f1a480345ee..7b5ab5bb16eb80ecd998fc60388ec1fca413f2e3 100644
--- a/sickbeard/databases/mainDB.py
+++ b/sickbeard/databases/mainDB.py
@@ -25,7 +25,7 @@ from sickbeard.providers.generic import GenericProvider
 from sickbeard import encodingKludge as ek
 from sickbeard.name_parser.parser import NameParser, InvalidNameException
 
-MAX_DB_VERSION = 17
+MAX_DB_VERSION = 18
 
 
 class MainSanityCheck(db.DBSanityCheck):
@@ -744,4 +744,14 @@ class AddFrenchSearch (AddProcessedFilesTable):
         if self.hasColumn("tv_shows", "frenchsearch") != True:
             self.addColumn("tv_shows", "frenchsearch", "NUMERIC", 0)
         self.incDBVersion()
-   
\ No newline at end of file
+class AddSceneNumbers(FixAirByDateSetting):
+
+    def test(self):
+        return self.checkDBVersion() >= 18
+
+    def execute(self):
+
+        self.addColumn("tv_episodes", "scene_episode", "NUMERIC", "NULL")
+        self.addColumn("tv_episodes", "scene_season", "NUMERIC", "NULL")
+
+        self.incDBVersion()
diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py
index e1fedefefe21b26f56b9e8dc7eb3eb772ad37274..96b49884b2caccd227d825eaf0dc7f7b1e95d47a 100755
--- a/sickbeard/postProcessor.py
+++ b/sickbeard/postProcessor.py
@@ -658,11 +658,22 @@ class PostProcessor(object):
                     season = 1
             
             if tvdb_id and season != None and episodes:
+                season, episodes = self._sceneToTVDBNumbers(tvdb_id, season, episodes)
                 return (tvdb_id, season, episodes)
-    
+        season, episodes = self._sceneToTVDBNumbers(tvdb_id, season, episodes)
         return (tvdb_id, season, episodes)
-    
-    def _get_ep_obj(self, tvdb_id, season, episodes):
+    def _sceneToTVDBNumbers(self, tvdb_id, season, episodes):
+        
+        self._log(u"This looks like a scene release converting scene numbers to tvdb numbers", logger.DEBUG)
+        ep_obj = self._get_ep_obj(tvdb_id, season, episodes, scene=True)
+        if ep_obj:
+            newEpisodeNumbers = []
+            for curEp in [ep_obj] + ep_obj.relatedEps:
+                newEpisodeNumbers.append(curEp.episode)
+            return (ep_obj.season, newEpisodeNumbers)
+        return (season, episodes)
+   
+    def _get_ep_obj(self, tvdb_id, season, episodes, scene=False):
         """
         Retrieve the TVEpisode object requested.
         
@@ -675,7 +686,9 @@ class PostProcessor(object):
         """
 
         show_obj = None
-
+        sceneMsg = ""
+        if scene:
+            sceneMsg = "(scene numbers) "
         self._log(u"Loading show object for tvdb_id "+str(tvdb_id), logger.DEBUG)
         # find the show in the showlist
         try:
@@ -692,11 +705,11 @@ class PostProcessor(object):
         for cur_episode in episodes:
             episode = int(cur_episode)
     
-            self._log(u"Retrieving episode object for " + str(season) + "x" + str(episode), logger.DEBUG)
+            self._log(u"Retrieving episode object for " + sceneMsg + str(season) + "x" + str(episode), logger.DEBUG)
     
             # now that we've figured out which episode this file is just load it manually
             try:
-                curEp = show_obj.getEpisode(season, episode)
+                curEp = show_obj.getEpisode(season, episode, scene=scene)
             except exceptions.EpisodeNotFoundException, e:
                 self._log(u"Unable to create episode: "+ex(e), logger.DEBUG)
                 raise exceptions.PostProcessingFailed()
@@ -704,8 +717,10 @@ class PostProcessor(object):
             # associate all the episodes together under a single root episode
             if root_ep == None:
                 root_ep = curEp
-                root_ep.relatedEps = []
+                if not scene:
+                    root_ep.relatedEps = []
             elif curEp not in root_ep.relatedEps:
+                self._log("Adding a related episode: " + str(curEp.season) + "x" + str(curEp.episode))
                 root_ep.relatedEps.append(curEp)
         
         return root_ep
diff --git a/sickbeard/providers/binnewz/__init__.py b/sickbeard/providers/binnewz/__init__.py
index af1f24267fcbadd0ceea373a9d785ee308a81a60..6058790701a9f5a861f9f479327d944e4ae1ba07 100644
--- a/sickbeard/providers/binnewz/__init__.py
+++ b/sickbeard/providers/binnewz/__init__.py
@@ -106,22 +106,22 @@ class BinNewzProvider(generic.NZBProvider):
         epidr = myDB.select("SELECT episode_id from tv_episodes where tvdbid=?", [ep_obj.tvdbid])
         globepid = epidr[0][0]
         for showName in showNames:
-            strings.append("%s S%02dE%02d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%02dE%d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%dE%02d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s %dx%d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%02d E%02d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%02d E%d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%d E%02d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%02dEp%02d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%02dEp%d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%dEp%02d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%02d Ep%02d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%02d Ep%d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%d Ep%02d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%02d Ep %02d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%02d Ep %d" % (showName, ep_obj.season, ep_obj.episode))
-            strings.append("%s S%d Ep %02d" % (showName, ep_obj.season, ep_obj.episode))
+            strings.append("%s S%02dE%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%02dE%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%dE%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s %dx%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%02d E%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%02d E%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%d E%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%02dEp%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%02dEp%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%dEp%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%02d Ep%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%02d Ep%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%d Ep%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%02d Ep %02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%02d Ep %d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
+            strings.append("%s S%d Ep %02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode))
         return strings
 
     def _get_title_and_url(self, item):
@@ -144,7 +144,7 @@ class BinNewzProvider(generic.NZBProvider):
         if searchString is None:
             return []
         logger.log("BinNewz : Searching for " + searchString, logger.DEBUG)
-        data = self.buildUrl(searchString, show.quality)
+        data = self.buildUrl(searchString.replace('!',''), show.quality)
         try:
             soup = BeautifulSoup(urllib2.urlopen("http://www.binnews.in/_bin/search2.php",
                                                  urllib.urlencode(data, True)))
diff --git a/sickbeard/providers/cpasbien.py b/sickbeard/providers/cpasbien.py
index 483542e92aaf23de078f1ff4ea5719e7edd2ca55..cc1c38fe4e590afbe78a0084617b1c4a9bb302f0 100644
--- a/sickbeard/providers/cpasbien.py
+++ b/sickbeard/providers/cpasbien.py
@@ -60,8 +60,8 @@ class CpasbienProvider(generic.TorrentProvider):
 
         showNames = show_name_helpers.allPossibleShowNames(ep_obj.show)
         for showName in showNames:
-            strings.append("%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode) )
-            strings.append("%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ) )
+            strings.append("%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode) )
+            strings.append("%s %dx%d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ) )
 
         return strings
     
@@ -76,7 +76,7 @@ class CpasbienProvider(generic.TorrentProvider):
         results = []
         searchUrl = self.url + '/recherche/'
         
-        data = urllib.urlencode({'champ_recherche': searchString})
+        data = urllib.urlencode({'champ_recherche': searchString.replace('!','')})
         req = urllib2.Request(searchUrl, data, headers={'User-Agent' : "Mozilla/5.0"})
         try:
             soup = BeautifulSoup( urllib2.urlopen(req) )
diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py
index 84d7dd19bd64486c924e1fffd2897befb86864eb..babcadba620a678b30d9c691287dd45ca82b0264 100644
--- a/sickbeard/providers/generic.py
+++ b/sickbeard/providers/generic.py
@@ -262,10 +262,11 @@ class GenericProvider:
                 if parse_result.air_date != episode.airdate:
                     logger.log("Episode "+title+" didn't air on "+str(episode.airdate)+", skipping it", logger.DEBUG)
                     continue
-            elif parse_result.season_number != episode.season or episode.episode not in parse_result.episode_numbers:
-                logger.log("Episode "+title+" isn't "+str(episode.season)+"x"+str(episode.episode)+", skipping it", logger.DEBUG)
+            elif parse_result.season_number != episode.scene_season or episode.scene_episode not in parse_result.episode_numbers:
+                logger.log("Episode "+title+" isn't "+str(episode.scene_season)+"x"+str(episode.scene_episode)+", skipping it", logger.DEBUG)
                 continue
 
+
             quality = self.getQuality(item)
 
             if not episode.show.wantEpisode(episode.season, episode.episode, quality, manualSearch):
diff --git a/sickbeard/providers/gks.py b/sickbeard/providers/gks.py
index 45762f800dfbc43ccb4a871ba3a81f0617a0fbe8..adea259264a823c7d8dbc41b99f4c4a5248331f1 100644
--- a/sickbeard/providers/gks.py
+++ b/sickbeard/providers/gks.py
@@ -52,12 +52,15 @@ class GksProvider(generic.TorrentProvider):
         else:
             if audio_lang == "en":
                 results.append( urllib.urlencode( {'q': searchString, 'category' : 22, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" )
+                results.append( urllib.urlencode( {'q': searchString, 'category' : 21, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" )
                 if sickbeard.USE_SUBTITLES :
                     results.append( urllib.urlencode( {'q': searchString, 'category' : 11, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" )
                     results.append( urllib.urlencode( {'q': searchString, 'category' : 13, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" )
+                    results.append( urllib.urlencode( {'q': searchString, 'category' : 13, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" )
             elif audio_lang == "fr":
                 results.append( urllib.urlencode( {'q': searchString, 'category' : 12, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" )
                 results.append( urllib.urlencode( {'q': searchString, 'category' : 14, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" )
+                results.append( urllib.urlencode( {'q': searchString, 'category' : 21, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" )
             else:
                 results.append( urllib.urlencode( {'q': searchString, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" )
         return results
@@ -84,13 +87,13 @@ class GksProvider(generic.TorrentProvider):
                 lang='fr'
             else:
                 lang=ep_obj.show.audio_lang
-            for result in self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), lang) :
+            for result in self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), lang) :
                 results.append(result)
         return results
         
     def _doSearch(self, searchString, show=None, season=None, french=None):
         results = []
-        searchUrl = self.url+'rdirect.php?type=search&'+searchString
+        searchUrl = self.url+'rdirect.php?type=search&'+searchString.replace('!','')
         logger.log(u"Search URL: " + searchUrl, logger.DEBUG)
         
         data = self.getURL(searchUrl)
diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py
index f57d6f53890e6c80a90b90302febfa5b7cae1b20..8a40b10a11be0a6ba45ea6314ed1e8eaaf611a36 100644
--- a/sickbeard/providers/kat.py
+++ b/sickbeard/providers/kat.py
@@ -84,7 +84,7 @@ class KATProvider(generic.TorrentProvider):
             return params
         global lang
         lang = show.audio_lang
-        params['show_name'] = helpers.sanitizeSceneName(show.name).replace('.',' ').encode('utf-8')
+        params['show_name'] = helpers.sanitizeSceneName(show.name).replace('.',' ').replace('!','').encode('utf-8')
           
         if season != None:
             params['season'] = season
@@ -100,13 +100,13 @@ class KATProvider(generic.TorrentProvider):
         if not ep_obj:
             return [params]
 
-        params['show_name'] = helpers.sanitizeSceneName(ep_obj.show.name).replace('.',' ').encode('utf-8')
+        params['show_name'] = helpers.sanitizeSceneName(ep_obj.show.name).replace('.',' ').replace('!','').encode('utf-8')
         
         if ep_obj.show.air_by_date:
             params['date'] = str(ep_obj.airdate)
         else:
-            params['season'] = ep_obj.season
-            params['episode'] = ep_obj.episode
+            params['season'] = ep_obj.scene_season
+            params['episode'] = ep_obj.scene_episode
 
         to_return = [params]
 
diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py
index 378266a1f1c0a3f8d105d8ac88a5c662857a61a8..bb80e5588956d90fc736b71231f1f974cb43b42f 100644
--- a/sickbeard/providers/newznab.py
+++ b/sickbeard/providers/newznab.py
@@ -140,8 +140,8 @@ class NewznabProvider(generic.NZBProvider):
                 params['ep'] = date_str.partition('-')[2].replace('-', '/')
                 
             else:
-                params['season'] = ep_obj.season
-                params['ep'] = ep_obj.episode
+                params['season'] = ep_obj.scene_season
+                params['ep'] = ep_obj.scene_episode
 
                 to_return = [params]
 
@@ -176,7 +176,7 @@ class NewznabProvider(generic.NZBProvider):
         return parse_result.audio_langs    
 
     def _doGeneralSearch(self, search_string):
-        return self._doSearch({'q': search_string})
+        return self._doSearch({'q': search_string.replace('!','')})
 
     def _checkAuthFromData(self, data):
 
diff --git a/sickbeard/providers/piratebay/__init__.py b/sickbeard/providers/piratebay/__init__.py
index 35ffe0d9d1d5ad4b287ab1a578b6d2bb7eeb62da..288acd2fdc9bfb2ab8d5a979bb97734ff823b3fd 100644
--- a/sickbeard/providers/piratebay/__init__.py
+++ b/sickbeard/providers/piratebay/__init__.py
@@ -190,9 +190,9 @@ class ThePirateBayProvider(generic.TorrentProvider):
         else:
             for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
                 ep_string = show_name_helpers.sanitizeSceneName(show_name) +' '+ \
-                sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.season, 'episodenumber': ep_obj.episode} +'|'+\
-                sickbeard.config.naming_ep_type[0] % {'seasonnumber': ep_obj.season, 'episodenumber': ep_obj.episode} +'|'+\
-                sickbeard.config.naming_ep_type[3] % {'seasonnumber': ep_obj.season, 'episodenumber': ep_obj.episode} \
+                sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season, 'episodenumber': ep_obj.scene_episode} +'|'+\
+                sickbeard.config.naming_ep_type[0] % {'seasonnumber': ep_obj.scene_season, 'episodenumber': ep_obj.scene_episode} +'|'+\
+                sickbeard.config.naming_ep_type[3] % {'seasonnumber': ep_obj.scene_season, 'episodenumber': ep_obj.scene_episode} \
 
                 search_string['Episode'].append(ep_string)
     
@@ -206,7 +206,7 @@ class ThePirateBayProvider(generic.TorrentProvider):
         for mode in search_params.keys():
             for search_string in search_params[mode]:
 
-                searchURL = self.proxy._buildURL(self.searchurl %(urllib.quote(search_string.encode("utf-8"))))    
+                searchURL = self.proxy._buildURL(self.searchurl %(urllib.quote(search_string.replace('!','').encode("utf-8"))))    
         
                 logger.log(u"Search string: " + searchURL, logger.DEBUG)
         
diff --git a/sickbeard/providers/t411.py b/sickbeard/providers/t411.py
index b443c136828c35622fd71da58e50c10615e47c8f..d2c9c7f74d12598878c8f685ec2d50e66725e8f1 100644
--- a/sickbeard/providers/t411.py
+++ b/sickbeard/providers/t411.py
@@ -84,19 +84,19 @@ class T411Provider(generic.TorrentProvider):
         showNames = list(set(showNam))
         results = []
         for showName in showNames:
-            results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 433, french ))
-            if (int(ep_obj.season) < 31 and int(ep_obj.episode) < 61):
-                results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 433, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.episode), 'term[45][]': self.seasonValue(ep_obj.season)}))
+            results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), ep_obj.show.audio_lang, 433, french ))
+            if (int(ep_obj.scene_season) < 31 and int(ep_obj.scene_episode) < 61):
+                results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 433, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.scene_episode), 'term[45][]': self.seasonValue(ep_obj.scene_season)}))
             #results.append( self.getSearchParams( "%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang , 433 )) MAY RETURN 1x12 WHEN SEARCHING 1x1
-            results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 433, french ))
-            results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 637, french ))
-            if (int(ep_obj.season) < 31 and int(ep_obj.episode) < 61):
-                results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 637, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.episode), 'term[45][]': self.seasonValue(ep_obj.season)}))
+            results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ), ep_obj.show.audio_lang, 433, french ))
+            results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), ep_obj.show.audio_lang, 637, french ))
+            if (int(ep_obj.scene_season) < 31 and int(ep_obj.scene_episode) < 61):
+                results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 637, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.scene_episode), 'term[45][]': self.seasonValue(ep_obj.scene_season)}))
             #results.append( self.getSearchParams( "%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 637 ))
-            results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 637, french ))
-            results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 634, french))
+            results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ), ep_obj.show.audio_lang, 637, french ))
+            results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), ep_obj.show.audio_lang, 634, french))
             #results.append( self.getSearchParams( "%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 634 ))
-            results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 634, french ))
+            results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ), ep_obj.show.audio_lang, 634, french ))
         return results
     
     def _get_title_and_url(self, item):
@@ -116,7 +116,7 @@ class T411Provider(generic.TorrentProvider):
             self._doLogin( sickbeard.T411_USERNAME, sickbeard.T411_PASSWORD )
 
         results = []
-        searchUrl = self.url + '/torrents/search/?' + searchString
+        searchUrl = self.url + '/torrents/search/?' + searchString.replace('!','')
         logger.log(u"Search string: " + searchUrl, logger.DEBUG)
         
         r = self.opener.open( searchUrl )
diff --git a/sickbeard/scene_exceptions.py b/sickbeard/scene_exceptions.py
index e94d57772493b9df0ac37422d19937af0db5a20d..a6c48acb559c3a66ace3fbc9d9e756cd57eb39d0 100644
--- a/sickbeard/scene_exceptions.py
+++ b/sickbeard/scene_exceptions.py
@@ -18,19 +18,25 @@
 
 import re
 import os
+import urllib, urllib2, httplib
 import sickbeard
 from sickbeard import helpers
 from sickbeard import name_cache
 from sickbeard import logger
 from sickbeard import db
+try:
+    import json
+except ImportError:
+    from lib import simplejson as json
+from sickbeard.exceptions import ex
 
-def get_scene_exceptions(tvdb_id):
+def get_scene_exceptions(tvdb_id, season=-1):
     """
     Given a tvdb_id, return a list of all the scene exceptions.
     """
 
     myDB = db.DBConnection("cache.db")
-    exceptions = myDB.select("SELECT show_name FROM scene_exceptions WHERE tvdb_id = ?", [tvdb_id])
+    exceptions = myDB.select("SELECT show_name FROM scene_exceptions WHERE tvdb_id = ? and season= ?", [tvdb_id, season])
     return [cur_exception["show_name"] for cur_exception in exceptions]
 
 
@@ -94,34 +100,27 @@ def retrieve_exceptions():
             tvdb_id = int(tvdb_id)
 
             # regex out the list of shows, taking \' into account
-            alias_list = [re.sub(r'\\(.)', r'\1', x) for x in re.findall(r"'(.*?)(?<!\\)',?", aliases)]
+            alias_list = [{re.sub(r'\\(.)', r'\1', x):-1} for x in re.findall(r"'(.*?)(?<!\\)',?", aliases)]
 
             exception_dict[tvdb_id] = alias_list
 
-        myDB = db.DBConnection("cache.db")
+        xem_exceptions = _xem_excpetions_fetcher()
+        exception_dict = dict(xem_exceptions.items() + exception_dict.items())
+
+        if not len(exception_dict):
+            logger.log("Retreived exception list is totally empty. Assuming remote server error not flushing local and stoping now")
+            return False
 
-        changed_exceptions = False
+        myDB = db.DBConnection("cache.db")
+        myDB.action("DELETE FROM scene_exceptions") # flush current list
 
         # write all the exceptions we got off the net into the database
         for cur_tvdb_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 tvdb_id = ?", [cur_tvdb_id])]
-
-            for cur_exception in exception_dict[cur_tvdb_id]:
-                # 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 (tvdb_id, show_name) VALUES (?,?)", [cur_tvdb_id, cur_exception])
-                    changed_exceptions = True
-
-        # since this could invalidate the results of the cache we clear it out after updating
-        if changed_exceptions:
-            logger.log(u"Updated scene exceptions")
-            name_cache.clearCache()
-            f.close()
-        else:
-            logger.log(u"No scene exceptions update needed")
-            f.close()
+            for cur_exception_dict in exception_dict[cur_tvdb_id]:
+                cur_exception, curSeason = cur_exception_dict.items()[0]
+                myDB.action("INSERT INTO scene_exceptions (tvdb_id, show_name, season) VALUES (?,?,?)", [cur_tvdb_id, cur_exception, curSeason])
+        name_cache.clearCache()
+        f.close()
 def update_scene_exceptions(tvdb_id, scene_exceptions):
     """
     Given a tvdb_id, and a list of all show scene exceptions, update the db.
@@ -134,4 +133,39 @@ def update_scene_exceptions(tvdb_id, scene_exceptions):
     for cur_exception in scene_exceptions:
         myDB.action("INSERT INTO scene_exceptions (tvdb_id, show_name) VALUES (?,?)", [tvdb_id, cur_exception])
     
-    name_cache.clearCache()
\ No newline at end of file
+    name_cache.clearCache()
+def _xem_excpetions_fetcher():
+    exception_dict = {}
+    opener = urllib2.build_opener()
+
+    url = "http://thexem.de/map/allNames?origin=tvdb&seasonNumbers=1"
+    try:
+        f = opener.open(url)
+    except (EOFError, IOError), e:
+        logger.log(u"Unable to connect to XEM. Is thexem.de down ?" + ex(e), logger.ERROR)
+        return exception_dict
+    except httplib.InvalidURL, e:
+        logger.log(u"Invalid XEM host. Is thexem.de down ?: " + ex(e), logger.ERROR)
+        return exception_dict
+    if not f:
+        logger.log(u"Empty response from " + url + ": " + ex(e), logger.ERROR)
+        return exception_dict
+    try:
+        xemJson = json.loads(f.read())
+    except ValueError, e:
+        pass
+
+    if xemJson['result'] == 'failure':
+        return exception_dict
+
+    for tvdbid, names in xemJson['data'].items():
+        exception_dict[int(tvdbid)] = names
+
+    logger.log(u"xem exception dict: " + str(exception_dict), logger.DEBUG)
+    return exception_dict
+def getSceneSeasons(tvdb_id):
+    """get a list of season numbers that have scene excpetions
+    """
+    myDB = db.DBConnection("cache.db")
+    seasons = myDB.select("SELECT DISTINCT season FROM scene_exceptions WHERE tvdb_id = ?", [tvdb_id])
+    return [cur_exception["season"] for cur_exception in seasons]
diff --git a/sickbeard/show_name_helpers.py b/sickbeard/show_name_helpers.py
index 9bacc303a896f46a83ebd7644bcd39058125d690..a5f6133577a08b785f0a0c6e6034aab338a265af 100644
--- a/sickbeard/show_name_helpers.py
+++ b/sickbeard/show_name_helpers.py
@@ -115,9 +115,9 @@ def sceneToNormalShowNames(name):
 
     return list(set(results))
 
-def makeSceneShowSearchStrings(show):
+def makeSceneShowSearchStrings(show, season=-1):
 
-    showNames = allPossibleShowNames(show)
+    showNames = allPossibleShowNames(show,season=season)
 
     # scenify the names
     return map(sanitizeSceneName, showNames)
@@ -191,15 +191,17 @@ def makeSceneSearchString (episode):
     if episode.show.air_by_date and episode.airdate != datetime.date.fromordinal(1):
         epStrings = [str(episode.airdate)]
     else:
-        epStrings = ["S%02iE%02i" % (int(episode.season), int(episode.episode)),
-                    "%ix%02i" % (int(episode.season), int(episode.episode))]
+        epStrings = ["S%02iE%02i" % (int(episode.scene_season), int(episode.scene_episode)),
+                    "%ix%02i" % (int(episode.scene_season), int(episode.scene_episode))]
+
+ 
 
     # for single-season shows just search for the show name -- if total ep count (exclude s0) is less than 11
     # due to the amount of qualities and releases, it is easy to go over the 50 result limit on rss feeds otherwise
     if numseasons == 1 and numepisodes < 11:
         epStrings = ['']
 
-    showNames = set(makeSceneShowSearchStrings(episode.show))
+    showNames = set(makeSceneShowSearchStrings(episode.show, episode.scene_season))
 
     toReturn = []
 
@@ -209,12 +211,12 @@ def makeSceneSearchString (episode):
 
     return toReturn
 
-def isGoodResult(name, show, log=True):
+def isGoodResult(name, show, log=True, season=-1):
     """
     Use an automatically-created regex to make sure the result actually is the show it claims to be
     """
 
-    all_show_names = allPossibleShowNames(show)
+    all_show_names = allPossibleShowNames(show,season=season)
     showNames = map(sanitizeSceneName, all_show_names) + all_show_names
 
     for curName in set(showNames):
@@ -235,7 +237,7 @@ def isGoodResult(name, show, log=True):
         logger.log(u"Provider gave result "+name+" but that doesn't seem like a valid result for "+show.name+" so I'm ignoring it")
     return False
 
-def allPossibleShowNames(show):
+def allPossibleShowNames(show, season=-1):
     """
     Figures out every possible variation of the name for a particular show. Includes TVDB name, TVRage name,
     country codes on the end, eg. "Show Name (AU)", and any scene exception names.
@@ -245,7 +247,9 @@ def allPossibleShowNames(show):
     Returns: a list of all the possible show names
     """
 
-    showNames = [show.name]
+    showNames = []
+    if season is -1:
+        showNames = [show.name]
     for name in get_scene_exceptions(show.tvdbid):
         if not name in showNames:
             showNames.append( name )
diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py
index eb2056d1c280189b33b5842d4f1c3462e10b357c..c1ef3c4fa4e9a32f1fc53af5dfe2785e0adcaa57 100644
--- a/sickbeard/show_queue.py
+++ b/sickbeard/show_queue.py
@@ -365,6 +365,11 @@ class QueueItemAdd(ShowQueueItem):
             logger.log(u"Setting all episodes to the specified default status: " + str(self.default_status))
             myDB = db.DBConnection()
             myDB.action("UPDATE tv_episodes SET status = ? WHERE status = ? AND showid = ? AND season != 0", [self.default_status, SKIPPED, self.show.tvdbid])
+        logger.log(u"Attempting to load scene numbers", logger.DEBUG)
+        if self.show.loadEpisodeSceneNumbers():
+            logger.log(u"loading scene numbers successfull", logger.DEBUG)
+        else:
+            logger.log(u"loading scene numbers NOT successfull or no scene numbers available", logger.DEBUG)
 
         # if they started with WANTED eps then run the backlog
         if self.default_status == WANTED:
@@ -557,6 +562,12 @@ class QueueItemUpdate(ShowQueueItem):
                         curEp.deleteEpisode()
                     except exceptions.EpisodeDeletedException:
                         pass
+        logger.log(u"Attempting to load scene numbers", logger.DEBUG)
+        if self.show.loadEpisodeSceneNumbers():
+            logger.log(u"loading scene numbers successfull", logger.DEBUG)
+        else:
+            logger.log(u"loading scene numbers NOT successfull or no scene numbers available", logger.DEBUG)
+            
 
         # now that we've updated the DB from TVDB see if there's anything we can add from TVRage
         with self.show.lock:
diff --git a/sickbeard/tv.py b/sickbeard/tv.py
index f3764db86b43d8f4f025b0f3594bb574cdb60802..faf1539001e7968d21914f98bdb16eb29a459313 100644
--- a/sickbeard/tv.py
+++ b/sickbeard/tv.py
@@ -23,6 +23,11 @@ import datetime
 import threading
 import re
 import glob
+try:
+    import json
+except ImportError:
+    from lib import simplejson as json
+import urllib2, httplib
 import traceback
 import hashlib
 from sickbeard import common
@@ -174,27 +179,31 @@ class TVShow(object):
         return ep_list
 
 
-    def getEpisode(self, season, episode, file=None, noCreate=False):
+    def getEpisode(self, season, episode, file=None, noCreate=False, scene=False):
 
         #return TVEpisode(self, season, episode)
-
-        if not season in self.episodes:
-            self.episodes[season] = {}
-
+        def createCurSeasonDict():
+            if not season in self.episodes:
+                self.episodes[season] = {}
+        createCurSeasonDict()
         ep = None
 
-        if not episode in self.episodes[season] or self.episodes[season][episode] == None:
+        if (not episode in self.episodes[season] or self.episodes[season][episode] == None) or scene:
             if noCreate:
                 return None
 
             logger.log(str(self.tvdbid) + ": An object for episode " + str(season) + "x" + str(episode) + " didn't exist in the cache, trying to create it", logger.DEBUG)
 
             if file != None:
-                ep = TVEpisode(self, season, episode, file)
+                ep = TVEpisode(self, season, episode, file, scene)
             else:
-                ep = TVEpisode(self, season, episode)
+                ep = TVEpisode(self, season, episode, scene=scene)
 
             if ep != None:
+                if scene: # if scene mode was active we need to use the new ep season episode numbers
+                    season = ep.season
+                    episode = ep.episode
+                    createCurSeasonDict() # recheck current "real" season dict
                 self.episodes[season][episode] = ep
 
         return self.episodes[season][episode]
@@ -403,6 +412,49 @@ class TVShow(object):
                 scannedEps[season][episode] = True
 
         return scannedEps
+    def loadEpisodeSceneNumbers(self):
+        url = "http://thexem.de/map/all?id=%s&origin=tvdb&destination=scene" % self.tvdbid
+        logger.log("xem url: " + url, logger.DEBUG)
+        opener = urllib2.build_opener()
+        try:
+            f = opener.open(url)
+        except (EOFError, IOError), e:
+            logger.log(u"Unable to connect to XEM. Is thexem.de down ?" + ex(e), logger.ERROR)
+            return False
+        except httplib.InvalidURL, e:
+            logger.log(u"Invalid XEM host. Is thexem.de down ?: " + ex(e), logger.ERROR)
+            return False
+        if not f:
+            logger.log(u"Empty response from " + url + ": " + ex(e), logger.ERROR)
+            return False
+        try:
+            xemJson = json.loads(f.read())
+        except ValueError, e:
+            pass
+        
+        epList = self.loadEpisodesFromDB()
+        for curSeason in epList:
+            for curEp in epList[curSeason]:
+                epObj = self.getEpisode(curSeason, curEp)
+                epObj.scene_season = None
+                epObj.scene_episode = None
+                epObj.saveToDB()
+        
+        if xemJson['result'] == 'failure':
+            return False
+
+        for epNumbers in xemJson['data']:
+            tvdb = epNumbers['tvdb']
+            scene = epNumbers['scene']
+            if not tvdb['season'] in epList or not tvdb['episode'] in epList[tvdb['season']]:
+                logger.log(str(self.tvdbid) + ": NOT adding scene number. tvdb: " + str(tvdb) + "| scene: " + str(scene) + " we dont have a ep with this (tvdb) sxxexx", logger.WARNING)
+
+            logger.log(str(self.tvdbid) + ": adding scene number. tvdb: " + str(tvdb) + "| scene: " + str(scene), logger.DEBUG)
+            curEp = self.getEpisode(tvdb['season'], tvdb['episode'])
+            curEp.scene_season = scene['season']
+            curEp.scene_episode = scene['episode']
+            curEp.saveToDB()
+        return True
 
     def setTVRID(self, force=False):
 
@@ -1106,7 +1158,7 @@ def dirty_setter(attr_name):
 
 class TVEpisode(object):
 
-    def __init__(self, show, season, episode, file=""):
+    def __init__(self, show, season, episode, file="", scene=False):
 
         self._name = ""
         self._season = season
@@ -1123,6 +1175,12 @@ class TVEpisode(object):
         self._file_size = 0
         self._audio_langs = ''
         self._release_name = ''
+        self.scene = scene
+        self._scene_season = None
+        self._scene_episode = None
+        if self.scene:
+            self._scene_season = self._season
+            self._scene_episode = self._episode
 
         # setting any of the above sets the dirty flag
         self.dirty = True
@@ -1132,9 +1190,9 @@ class TVEpisode(object):
 
         self.lock = threading.Lock()
 
-        self.specifyEpisode(self.season, self.episode)
-
         self.relatedEps = []
+        
+        self.specifyEpisode(self.season, self.episode)
 
         self.checkForMetaFiles()
 
@@ -1154,6 +1212,20 @@ class TVEpisode(object):
     file_size = property(lambda self: self._file_size, dirty_setter("_file_size"))
     audio_langs = property(lambda self: self._audio_langs, dirty_setter("_audio_langs"))
     release_name = property(lambda self: self._release_name, dirty_setter("_release_name"))
+    scene_season = property(lambda self: self._getSceneOrTVDBSeason(), dirty_setter("_scene_season"))
+    scene_episode = property(lambda self: self._getSceneOrTVDBEpisode(), dirty_setter("_scene_episode"))
+
+    def _getSceneOrTVDBSeason(self):
+        if self._scene_season is None:
+            return self.season
+        else:
+            return self._scene_season
+
+    def _getSceneOrTVDBEpisode(self):
+        if self._scene_episode is None:
+            return self.episode
+        else:
+            return self._scene_episode
 
     def _set_location(self, new_location):
         logger.log(u"Setter sets location to " + new_location, logger.DEBUG)
@@ -1334,6 +1406,12 @@ class TVEpisode(object):
     def specifyEpisode(self, season, episode):
 
         sqlResult = self.loadFromDB(season, episode)
+        # we need this because if the db loading is done with scene we change the acctuay ep ans season number
+
+        # and these numbers are not valid any more and have been replaced with tvdb numbers
+        if sqlResult:
+            season = self.season
+            episode = self.episode
 
         if not sqlResult:
             # only load from NFO if we didn't load from DB
@@ -1361,22 +1439,43 @@ class TVEpisode(object):
 
     def loadFromDB(self, season, episode):
 
-        logger.log(str(self.show.tvdbid) + ": Loading episode details from DB for episode " + str(season) + "x" + str(episode), logger.DEBUG)
+        msg = ''
+        if self.scene:
+            msg = "(mode: scene numbers)"
+        logger.log(str(self.show.tvdbid) + ": Loading episode details from DB for episode " + msg + " " + str(season) + "x" + str(episode), logger.DEBUG)
 
         myDB = db.DBConnection()
-        sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [self.show.tvdbid, season, episode])
+        if not self.scene:
+            sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [self.show.tvdbid, season, episode])
+        else:
+            sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE showid = ? AND scene_season = ? AND scene_episode = ?", [self.show.tvdbid, season, episode])
+            
+        if len(sqlResults) > 1 and not self.scene:
+            raise exceptions.MultipleDBEpisodesException("Your DB has two records for the same episode somehow."+msg)
+        elif len(sqlResults) > 1 and self.scene:
+            first = True
+            for relatedEP in sqlResults:
+                if first: # first shal be root ep
+                    first = False
+                    continue
+                logger.log(str(self.show.tvdbid) + ": Adding a related episode because of a scene mapping with tvdb numbers " + str(relatedEP["season"]) + "x" + str(relatedEP["episode"]), logger.DEBUG)
 
-        if len(sqlResults) > 1:
-            raise exceptions.MultipleDBEpisodesException("Your DB has two records for the same show somehow.")
+                rel_ep_obj = TVEpisode(self.show, int(relatedEP["season"]), int(relatedEP["episode"]))
+                self.relatedEps.append(rel_ep_obj)
         elif len(sqlResults) == 0:
-            logger.log(str(self.show.tvdbid) + ": Episode " + str(self.season) + "x" + str(self.episode) + " not found in the database", logger.DEBUG)
+            logger.log(str(self.show.tvdbid) + ": Episode " +msg+ str(self.season) + "x" + str(self.episode) + " not found in the database", logger.DEBUG)
             return False
         else:
             #NAMEIT logger.log(u"AAAAA from" + str(self.season)+"x"+str(self.episode) + " -" + self.name + " to " + str(sqlResults[0]["name"]))
             if sqlResults[0]["name"] != None:
                 self.name = sqlResults[0]["name"]
-            self.season = season
-            self.episode = episode
+            
+            if not self.scene:
+                self.season = season
+                self.episode = episode
+            else:
+                self.season = int(sqlResults[0]["season"])
+                self.episode = int(sqlResults[0]["episode"])
             self.description = sqlResults[0]["description"]
             if self.description == None:
                 self.description = ""
@@ -1397,6 +1496,16 @@ class TVEpisode(object):
                 self.file_size = 0
 
             self.tvdbid = int(sqlResults[0]["tvdbid"])
+            # does one now a better way to test for NULL in the db field ?
+            if isinstance(sqlResults[0]["scene_season"], int):
+                self.scene_season = int(sqlResults[0]["scene_season"])
+
+            if isinstance(sqlResults[0]["scene_episode"], int):
+                self.scene_episode = int(sqlResults[0]["scene_episode"])
+
+            logger.log("Episode loading done " + msg + str(self.season) + "x" + str(self.episode), logger.DEBUG)
+            
+            self.scene = False
 
             if sqlResults[0]["audio_langs"] != None:
                 self.audio_langs = sqlResults[0]["audio_langs"]
@@ -1691,6 +1800,8 @@ class TVEpisode(object):
                         "hastbn": self.hastbn,
                         "status": self.status,
                         "location": self.location,
+                        "scene_season": self._scene_season,
+                        "scene_episode": self._scene_episode,
                         "audio_langs": self.audio_langs,
                         "file_size": self.file_size,
                         "release_name": self.release_name}
diff --git a/sickbeard/tvcache.py b/sickbeard/tvcache.py
index 1d6a042d640997e088528291b49b5c62b31db026..1cc6cb3a49c47d038ca895255baffe08d238f27e 100644
--- a/sickbeard/tvcache.py
+++ b/sickbeard/tvcache.py
@@ -26,7 +26,7 @@ from sickbeard import db
 from sickbeard import logger
 from sickbeard.common import Quality
 
-from sickbeard import helpers, exceptions, show_name_helpers
+from sickbeard import helpers, exceptions, show_name_helpers, scene_exceptions
 from sickbeard import name_cache
 from sickbeard.exceptions import ex
 
@@ -248,17 +248,27 @@ class TVCache():
                     if showResult:
                         logger.log(parse_result.series_name+" was found to be show "+showResult[1]+" ("+str(showResult[0])+") in our DB.", logger.DEBUG)
                         tvdb_id = showResult[0]
-
+                def regexSearch(season=-1):
+                    if show_name_helpers.isGoodResult(name, curShow, False, season=season):
+                        logger.log(u"Successfully matched " + name + " to " + curShow.name + " with regex", logger.DEBUG)
+                        tvdb_id = curShow.tvdbid
+                        tvdb_lang = curShow.lang
+                        return True
+                    return False
                 # if the DB lookup fails then do a comprehensive regex search
                 if tvdb_id == None:
                     logger.log(u"Couldn't figure out a show name straight from the DB, trying a regex search instead", logger.DEBUG)
                     for curShow in sickbeard.showList:
-                        if show_name_helpers.isGoodResult(name, curShow, False):
-                            logger.log(u"Successfully matched "+name+" to "+curShow.name+" with regex", logger.DEBUG)
-                            tvdb_id = curShow.tvdbid
-                            tvdb_lang = curShow.lang
+                        if regexSearch():
                             break
-
+                # if the DB lookup fails then do a comprehensive regex search on saason exceptions
+                if tvdb_id == None:
+                    logger.log(u"Couldn't figure out a show name straight from the DB, trying a regex search on season exceptions", logger.DEBUG)
+                    for curShow in sickbeard.showList:
+                        scene_seasons = scene_exceptions.getSceneSeasons(curShow.tvdbid)
+                        for cur_scene_season in scene_seasons:
+                            if regexSearch(cur_scene_season):
+                                break
                 # if tvdb_id was anything but None (0 or a number) then 
                 if not from_cache:
                     name_cache.addNameToCache(parse_result.series_name, tvdb_id)
@@ -340,7 +350,7 @@ class TVCache():
         if not episode:
             sqlResults = myDB.select("SELECT * FROM "+self.providerID)
         else:
-            sqlResults = myDB.select("SELECT * FROM "+self.providerID+" WHERE tvdbid = ? AND season = ? AND episodes LIKE ?", [episode.show.tvdbid, episode.season, "%|"+str(episode.episode)+"|%"])
+            sqlResults = myDB.select("SELECT * FROM "+self.providerID+" WHERE tvdbid = ? AND season = ? AND episodes LIKE ?", [episode.show.tvdbid, episode.scene_season, "%|"+str(episode.scene_episode)+"|%"])
 
         # for each cache entry
         for curResult in sqlResults:
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index 33a00de0467c3f99001cf95bd3f40c6f5d26926a..34465fe5115bc129ee3f1e51f87e1dfb54ed0485 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -2949,13 +2949,14 @@ class Home:
         epCounts[Overview.GOOD] = 0
         epCounts[Overview.UNAIRED] = 0
         epCounts[Overview.SNATCHED] = 0
-
+        showSceneNumberColum = False
         for curResult in sqlResults:
-
+            if not showSceneNumberColum and (isinstance(curResult["scene_season"], int) and isinstance(curResult["scene_episode"], int)):
+                showSceneNumberColum = True
             curEpCat = showObj.getOverview(int(curResult["status"]))
             epCats[str(curResult["season"])+"x"+str(curResult["episode"])] = curEpCat
             epCounts[curEpCat] += 1
-
+        t.showSceneNumberColum = showSceneNumberColum
         def titler(x):
             if not x:
                 return x