diff --git a/gui/slick/images/providers/pretome.png b/gui/slick/images/providers/pretome.png
new file mode 100644
index 0000000000000000000000000000000000000000..86c61681b02a358a516c6e48e01359e84ca767f5
Binary files /dev/null and b/gui/slick/images/providers/pretome.png differ
diff --git a/gui/slick/views/config_providers.mako b/gui/slick/views/config_providers.mako
index dd7be25cf69191ad1a1137027e9766dabec5490d..baf50e9e83ef210524ce90dee493e2af883b3fab 100644
--- a/gui/slick/views/config_providers.mako
+++ b/gui/slick/views/config_providers.mako
@@ -368,6 +368,17 @@ $('#config-components').tabs();
                             </label>
                         </div>
                         % endif
+						
+                        % if hasattr(curTorrentProvider, 'pin'):
+                        <div class="field-pair">
+                            <label for="${curTorrentProvider.getID()}_pin">
+                                <span class="component-title">Pin:</span>
+                                <span class="component-desc">
+                                    <input type="text" name="${curTorrentProvider.getID()}_pin" id="${curTorrentProvider.getID()}_pin" value="${curTorrentProvider.pin}" class="form-control input-sm input100" />
+                                </span>
+                            </label>
+                        </div>
+                        % endif
 
                         % if hasattr(curTorrentProvider, 'ratio'):
                         <div class="field-pair">
diff --git a/gui/slick/views/displayShow.mako b/gui/slick/views/displayShow.mako
index 0e57871c52d29a8fb2968a29608c259e27430425..6e239e5217dbe6de28027c664a576d130dd2b18b 100644
--- a/gui/slick/views/displayShow.mako
+++ b/gui/slick/views/displayShow.mako
@@ -477,9 +477,13 @@
                 % endif
             </td>
             <td class="col-airdate">
-                % if int(epResult['airdate']) > 1 and show.network and show.airs:
+                % if int(epResult['airdate']) != 1:
                     ## Lets do this exactly like ComingEpisodes and History
-                    <% airDate = sbdatetime.sbdatetime.convert_to_setting(network_timezones.parse_date_time(epResult['airdate'], show.airs, show.network)) %>
+                    ## Avoid issues with dateutil's _isdst on Windows but still provide air dates
+                    <% airDate = datetime.datetime.fromordinal(epResult['airdate']) %>
+                    % if airDate.year >= 1970 or show.network:  
+                        <% airDate = sbdatetime.sbdatetime.convert_to_setting(network_timezones.parse_date_time(epResult['airdate'], show.airs, show.network)) %>
+                    % endif
                     <time datetime="${airDate.isoformat('T')}" class="date">${sbdatetime.sbdatetime.sbfdatetime(airDate)}</time>
                 % else:
                     Never
diff --git a/lib/libtrakt/trakt.py b/lib/libtrakt/trakt.py
index 5470eb96840cdd4e1f25e0bd5ead9e4acfba59d1..951f39a824ae329acde417757fd2ecd2097dcb79 100644
--- a/lib/libtrakt/trakt.py
+++ b/lib/libtrakt/trakt.py
@@ -97,10 +97,10 @@ class TraktAPI():
                 # This is pretty much a fatal error if there is no status_code
                 # It means there basically was no response at all                    
                 else:
-                    logger.log(u'Could not connect to Trakt. Error: {0}'.format(e), logger.WARNING)                
+                    logger.log(u'Could not connect to Trakt. Error: {0}'.format(e), logger.DEBUG)                
             elif code == 502:
                 # Retry the request, cloudflare had a proxying issue
-                logger.log(u'Retrying trakt api request: %s' % path, logger.WARNING)
+                logger.log(u'Retrying trakt api request: %s' % path, logger.DEBUG)
                 return self.traktRequest(path, data, headers, url, method)
             elif code == 401:
                 if self.traktToken(refresh=True, count=count):
@@ -109,9 +109,9 @@ class TraktAPI():
                     logger.log(u'Unauthorized. Please check your Trakt settings', logger.WARNING)
             elif code in (500,501,503,504,520,521,522):
                 #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)
+                logger.log(u'Trakt may have some issues and it\'s unavailable. Try again later please', logger.DEBUG)
             elif code == 404:
-                logger.log(u'Trakt error (404) the resource does not exist: %s' % url + path, logger.WARNING)
+                logger.log(u'Trakt error (404) the resource does not exist: %s' % url + path, logger.ERROR)
             else:
                 logger.log(u'Could not connect to Trakt. Code error: {0}'.format(code), logger.ERROR)
             return {}
diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py
index 3ed5cbfbbd88be03395b76fd54558de576d17383..ec389484d6aff09c02586ac9a0b2c26855144daf 100644
--- a/sickbeard/__init__.py
+++ b/sickbeard/__init__.py
@@ -1,4 +1,4 @@
-# Author: Nic Wolfe <nic@wolfeden.ca>
+# Author: Nic Wolfe <nic@wolfeden.ca>
 # URL: http://code.google.com/p/sickbeard/
 #
 # This file is part of SickRage.
@@ -40,7 +40,7 @@ from sickbeard.providers.generic import GenericProvider
 from sickbeard.providers import btn, newznab, womble, thepiratebay, torrentleech, kat, iptorrents, torrentz, \
     omgwtfnzbs, scc, hdtorrents, torrentday, hdbits, hounddawgs, nextgen, speedcd, nyaatorrents, animenzb, bluetigers, cpasbien, fnt, xthor, torrentbytes, \
     frenchtorrentdb, freshontv, titansoftv, libertalia, morethantv, bitsoup, t411, tokyotoshokan, shazbat, rarbg, alpharatio, tntvillage, binsearch, torrentproject, extratorrent, \
-    scenetime, btdigg, strike, transmitthenet, tvchaosuk, bitcannon
+    scenetime, btdigg, strike, transmitthenet, tvchaosuk, bitcannon, pretome
 from sickbeard.config import CheckSection, check_setting_int, check_setting_str, check_setting_float, ConfigMigrator, \
     naming_ep_type
 from sickbeard import searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser, \
@@ -1245,6 +1245,9 @@ def initialize(consoleLogging=True):
             if hasattr(curTorrentProvider, 'passkey'):
                 curTorrentProvider.passkey = check_setting_str(CFG, curTorrentProvider.getID().upper(),
                                                                curTorrentProvider.getID() + '_passkey', '', censor_log=True)
+            if hasattr(curTorrentProvider, 'pin'):
+                curTorrentProvider.pin = check_setting_str(CFG, curTorrentProvider.getID().upper(),
+                                                               curTorrentProvider.getID() + '_pin', '', censor_log=True)
             if hasattr(curTorrentProvider, 'proxy'):
                 curTorrentProvider.proxy.enabled = bool(check_setting_int(CFG, curTorrentProvider.getID().upper(),
                                                                           curTorrentProvider.getID() + '_proxy', 0))
@@ -1811,6 +1814,9 @@ def save_config():
         if hasattr(curTorrentProvider, 'passkey'):
             new_config[curTorrentProvider.getID().upper()][
                 curTorrentProvider.getID() + '_passkey'] = curTorrentProvider.passkey
+        if hasattr(curTorrentProvider, 'pin'):
+            new_config[curTorrentProvider.getID().upper()][
+                curTorrentProvider.getID() + '_pin'] = curTorrentProvider.pin
         if hasattr(curTorrentProvider, 'confirmed'):
             new_config[curTorrentProvider.getID().upper()][curTorrentProvider.getID() + '_confirmed'] = int(
                 curTorrentProvider.confirmed)
diff --git a/sickbeard/clients/rtorrent_client.py b/sickbeard/clients/rtorrent_client.py
index b6d6c1cc9b7afe30a78dd4cba0452af93598ea1b..867599cee2bb49b745b477ed193c5fdbc35a04f0 100644
--- a/sickbeard/clients/rtorrent_client.py
+++ b/sickbeard/clients/rtorrent_client.py
@@ -72,7 +72,7 @@ class rTorrentAPI(GenericClient):
             if result.show.is_anime:
                 label = sickbeard.TORRENT_LABEL_ANIME
             if label:
-                torrent.set_custom(1, label.lower())
+                torrent.set_custom(1, label)
 
             if sickbeard.TORRENT_PATH:
                 torrent.set_directory(sickbeard.TORRENT_PATH)
@@ -112,7 +112,7 @@ class rTorrentAPI(GenericClient):
             if result.show.is_anime:
                 label = sickbeard.TORRENT_LABEL_ANIME
             if label:
-                torrent.set_custom(1, label.lower())
+                torrent.set_custom(1, label)
 
             if sickbeard.TORRENT_PATH:
                 torrent.set_directory(sickbeard.TORRENT_PATH)
diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py
index 399b4999c5971307cd383ec16139da467e542f12..2b0102611ce9e467f11c4f63ea11c95e5290eacb 100644
--- a/sickbeard/postProcessor.py
+++ b/sickbeard/postProcessor.py
@@ -164,12 +164,15 @@ class PostProcessor(object):
         if not file_path:
             return []
 
+        # don't confuse glob with chars we didn't mean to use
+        globbable_file_path = helpers.fixGlob(file_path)
+
         file_path_list = []
 
         if subfolders:
-            base_name = ek(os.path.basename, file_path).rpartition('.')[0]
+            base_name = ek(os.path.basename, globbable_file_path).rpartition('.')[0]
         else:
-            base_name = file_path.rpartition('.')[0]
+            base_name = globbable_file_path.rpartition('.')[0]
 
         if not base_name_only:
             base_name = base_name + '.'
@@ -178,20 +181,17 @@ class PostProcessor(object):
         if not base_name:
             return []
 
-        # don't confuse glob with chars we didn't mean to use
-        base_name = re.sub(r'[\[\]\*\?]', r'[\g<0>]', base_name)
-
         if subfolders: # subfolders are only checked in show folder, so names will always be exactly alike
-            filelist = ek(recursive_glob, ek(os.path.dirname, file_path), base_name + '*') # just create the list of all files starting with the basename
+            filelist = recursive_glob(ek(os.path.dirname, globbable_file_path), base_name + '*') # just create the list of all files starting with the basename
         else: # this is called when PP, so we need to do the filename check case-insensitive
             filelist = []
 
-            checklist = ek(glob.glob, helpers.fixGlob(ek(os.path.join, ek(os.path.dirname, file_path), '*'))) # get a list of all the files in the folder
+            checklist = glob.glob(ek(os.path.join, ek(os.path.dirname, globbable_file_path), '*')) # get a list of all the files in the folder
             for filefound in checklist: # loop through all the files in the folder, and check if they are the same name even when the cases don't match
                 file_name = filefound.rpartition('.')[0]
                 if not base_name_only:
                     file_name = file_name + '.'
-                if file_name.lower() == base_name.lower(): # if there's no difference in the filename add it to the filelist
+                if file_name.lower() == base_name.lower().replace('[[]', '[').replace('[]]', ']'): # if there's no difference in the filename add it to the filelist
                     filelist.append(filefound)
 
         for associated_file_path in filelist:
@@ -910,7 +910,7 @@ class PostProcessor(object):
         if not priority_download:
 
             # Not a priority and the quality is lower than what we already have
-            if (new_ep_quality < old_ep_quality and new_ep_quality != common.Quality.UNKNOWN) and not existing_file_status == PostProcessor.DOESNT_EXIST:
+            if (new_ep_quality < old_ep_quality and old_ep_quality != common.Quality.UNKNOWN) and not existing_file_status == PostProcessor.DOESNT_EXIST:
                 self._log(u"File exists and new file quality is lower than existing, marking it unsafe to replace")
                 return False
 
diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py
index 2880981f61157049b6b477f6a17412787cd9fddf..c7903a69fa4f15bd123fc694fcda6eb4122a125a 100644
--- a/sickbeard/providers/__init__.py
+++ b/sickbeard/providers/__init__.py
@@ -1,4 +1,4 @@
-# Author: Nic Wolfe <nic@wolfeden.ca>
+# Author: Nic Wolfe <nic@wolfeden.ca>
 # URL: http://code.google.com/p/sickbeard/
 #
 # This file is part of SickRage.
@@ -58,7 +58,8 @@ __all__ = ['womble',
            'torrentproject',
            'extratorrent',
            'bitcannon',
-           'torrentz'
+           'torrentz',
+           'pretome'
 ]
 
 import sickbeard
diff --git a/sickbeard/providers/pretome.py b/sickbeard/providers/pretome.py
new file mode 100644
index 0000000000000000000000000000000000000000..4cadb672140ce212c301e37cd7df347479b1b7b9
--- /dev/null
+++ b/sickbeard/providers/pretome.py
@@ -0,0 +1,206 @@
+# Author: Nick Sologoub
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of SickRage.
+#
+# SickRage is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# SickRage is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with SickRage.  If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import urllib
+import traceback
+
+from sickbeard import logger
+from sickbeard import tvcache
+from sickbeard.providers import generic
+from sickbeard.bs4_parser import BS4Parser
+
+
+class PretomeProvider(generic.TorrentProvider):
+
+    def __init__(self):
+
+        generic.TorrentProvider.__init__(self, "Pretome")
+
+        self.supportsBacklog = True
+
+        self.username = None
+        self.password = None
+        self.pin = None
+        self.ratio = None
+        self.minseed = None
+        self.minleech = None
+        self.freeleech = False
+
+        self.urls = {'base_url': 'https://pretome.info',
+                     'login': 'https://pretome.info/takelogin.php',
+                     'detail': 'https://pretome.info/details.php?id=%s',
+                     'search': 'https://pretome.info/browse.php?search=%s%s',
+                     'download': 'https://pretome.info/download.php/%s/%s.torrent'}        
+
+        self.url = self.urls['base_url']
+
+        self.categories = "&st=1&cat%5B%5D=7"
+
+        self.proper_strings = ['PROPER', 'REPACK']
+
+        self.cache = PretomeCache(self)
+
+    def isEnabled(self):
+        return self.enabled
+    
+    def _checkAuth(self):
+
+        if not self.username or not self.password or not self.pin:
+            logger.log(u"Invalid username or password or pin. Check your settings", logger.WARNING)
+
+        return True
+
+    def _doLogin(self):
+
+        login_params = {'username': self.username,
+                        'password': self.password,
+                        'login_pin': self.pin}
+
+        response = self.getURL(self.urls['login'], post_data=login_params, timeout=30)
+        if not response:
+            logger.log(u"Unable to connect to provider", logger.WARNING)
+            return False
+
+        if re.search('Username or password incorrect', response):
+            logger.log(u"Invalid username or password. Check your settings", logger.WARNING)
+            return False
+
+        return True
+
+    def _doSearch(self, search_params, search_mode='eponly', epcount=0, age=0, epObj=None):
+
+        results = []
+        items = {'Season': [], 'Episode': [], 'RSS': []}
+
+        if not self._doLogin():
+            return results
+
+        for mode in search_params.keys():
+            logger.log(u"Search Mode: %s" % mode, logger.DEBUG)
+            for search_string in search_params[mode]:
+
+                if mode != 'RSS':
+                    logger.log(u"Search string: %s " % search_string, logger.DEBUG)
+
+                searchURL = self.urls['search'] % (urllib.quote(search_string.encode('utf-8')), self.categories)
+                logger.log(u"Search URL: %s" %  searchURL, logger.DEBUG)
+
+                data = self.getURL(searchURL)
+                if not data:
+                    continue
+
+                try:
+                    with BS4Parser(data, features=["html5lib", "permissive"]) as html:
+                        #Continue only if one Release is found
+                        empty = html.find('h2', text="No .torrents fit this filter criteria")
+                        if empty:
+                            logger.log(u"Data returned from provider does not contain any torrents", logger.DEBUG)
+                            continue
+
+                        torrent_table = html.find('table', attrs={'style': 'border: none; width: 100%;'})
+                        if not torrent_table:
+                            logger.log(u"Could not find table of torrents", logger.ERROR)
+                            continue
+
+                        torrent_rows = torrent_table.find_all('tr', attrs={'class': 'browse'})
+                        
+                        for result in torrent_rows:
+                            cells = result.find_all('td')
+                            size = None        
+                            link = cells[1].find('a', attrs={'style': 'font-size: 1.25em; font-weight: bold;'})
+
+                            torrent_id = link['href'].replace('details.php?id=', '')
+        
+                            try:
+                                if link.has_key('title'):
+                                    title = link['title']
+                                else:
+                                    title = link.contents[0]
+           
+                                download_url = self.urls['download'] % (torrent_id, link.contents[0])
+                                seeders = int(cells[9].contents[0])
+                                leechers = int(cells[10].contents[0])       
+                                                         
+                                # Need size for failed downloads handling
+                                if size is None:
+                                    if re.match(r'[0-9]+,?\.?[0-9]*[KkMmGg]+[Bb]+', cells[7].text):
+                                        size = self._convertSize(cells[7].text)
+                                        if not size:
+                                            size = -1
+                               
+                            except (AttributeError, TypeError):
+                                continue
+
+                            if not all([title, download_url]):
+                                continue
+
+                            #Filter unseeded torrent
+                            if seeders < self.minseed or leechers < self.minleech:
+                                if mode != 'RSS':
+                                    logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(title, seeders, leechers), logger.DEBUG)
+                                continue
+
+                            item = title, download_url, size, seeders, leechers
+                            if mode != 'RSS':
+                                logger.log(u"Found result: %s " % title, logger.DEBUG)
+
+                            items[mode].append(item)
+
+                except Exception, e:
+                    logger.log(u"Failed parsing provider. Traceback: %s" % traceback.format_exc(), logger.ERROR)
+
+            #For each search mode sort all the items by seeders if available
+            items[mode].sort(key=lambda tup: tup[3], reverse=True)
+
+            results += items[mode]
+
+        return results
+
+    def seedRatio(self):
+        return self.ratio
+    
+    def _convertSize(self, sizeString):
+        size = sizeString[:-2]
+        modifier = sizeString[-2:]
+        size = float(size)
+        if modifier in 'KB':
+            size = size * 1024
+        elif modifier in 'MB':
+            size = size * 1024**2
+        elif modifier in 'GB':
+            size = size * 1024**3
+        elif modifier in 'TB':
+            size = size * 1024**4
+        return int(size)
+
+
+class PretomeCache(tvcache.TVCache):
+    def __init__(self, provider_obj):
+
+        tvcache.TVCache.__init__(self, provider_obj)
+
+        # only poll Pretome every 20 minutes max
+        self.minTime = 20
+
+    def _getRSSData(self):
+        search_params = {'RSS': ['']}
+        return {'entries': self.provider._doSearch(search_params)}
+
+
+provider = PretomeProvider()
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index b275308e5a5859dfffcb34091855bedff501f3a5..ff758b143dd6425fc86be8a00c823b4ae47b031a 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -1,4 +1,4 @@
-# Author: Nic Wolfe <nic@wolfeden.ca>
+# Author: Nic Wolfe <nic@wolfeden.ca>
 # URL: http://code.google.com/p/sickbeard/
 #
 # This file is part of SickRage.
@@ -4418,6 +4418,12 @@ class ConfigProviders(Config):
                     curTorrentProvider.passkey = str(kwargs[curTorrentProvider.getID() + '_passkey']).strip()
                 except:
                     curTorrentProvider.passkey = None
+                    
+            if hasattr(curTorrentProvider, 'pin'):
+                try:
+                    curTorrentProvider.pin = str(kwargs[curTorrentProvider.getID() + '_pin']).strip()
+                except:
+                    curTorrentProvider.pin = None
 
             if hasattr(curTorrentProvider, 'confirmed'):
                 try: