diff --git a/SickBeard.py b/SickBeard.py
index 6e06ba6514a5859c46b3ca97b83a3b95ea52b611..ba46efc0a3ab8e055b797fc723d64c3aa261e280 100755
--- a/SickBeard.py
+++ b/SickBeard.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 # Author: Nic Wolfe <nic@wolfeden.ca>
 # URL: http://code.google.com/p/sickbeard/
 #
@@ -93,6 +93,11 @@ def daemonize():
     dev_null = file('/dev/null', 'r')
     os.dup2(dev_null.fileno(), sys.stdin.fileno())
 
+    if sickbeard.CREATEPID:
+        pid = str(os.getpid())
+        logger.log(u"Writing PID " + pid + " to " + str(sickbeard.PIDFILE))
+        file(sickbeard.PIDFILE, 'w').write("%s\n" % pid)
+
 def main():
 
     # do some preliminary stuff
@@ -100,6 +105,7 @@ def main():
     sickbeard.MY_NAME = os.path.basename(sickbeard.MY_FULLNAME)
     sickbeard.PROG_DIR = os.path.dirname(sickbeard.MY_FULLNAME)
     sickbeard.MY_ARGS = sys.argv[1:]
+    sickbeard.CREATEPID = False
 
     try:
         locale.setlocale(locale.LC_ALL, "")
@@ -120,9 +126,9 @@ def main():
     threading.currentThread().name = "MAIN"
 
     try:
-        opts, args = getopt.getopt(sys.argv[1:], "qfdp:", ['quiet', 'forceupdate', 'daemon', 'port=', 'tvbinz'])
+        opts, args = getopt.getopt(sys.argv[1:], "qfdp::", ['quiet', 'forceupdate', 'daemon', 'port=', 'tvbinz', 'pidfile='])
     except getopt.GetoptError:
-        print "Available options: --quiet, --forceupdate, --port, --daemon"
+        print "Available options: --quiet, --forceupdate, --port, --daemon --pidfile"
         sys.exit()
 
     forceUpdate = False
@@ -130,28 +136,47 @@ def main():
 
     for o, a in opts:
         # for now we'll just silence the logging
-        if (o in ('-q', '--quiet')):
+        if o in ('-q', '--quiet'):
             consoleLogging = False
         # for now we'll just silence the logging
-        if (o in ('--tvbinz')):
+        if o in ('--tvbinz'):
             sickbeard.SHOW_TVBINZ = True
 
         # should we update right away?
-        if (o in ('-f', '--forceupdate')):
+        if o in ('-f', '--forceupdate'):
             forceUpdate = True
 
         # use a different port
-        if (o in ('-p', '--port')):
+        if o in ('-p', '--port'):
             forcedPort = int(a)
 
         # Run as a daemon
-        if (o in ('-d', '--daemon')):
+        if o in ('-d', '--daemon'):
             if sys.platform == 'win32':
                 print "Daemonize not supported under Windows, starting normally"
             else:
                 consoleLogging = False
                 sickbeard.DAEMON = True
 
+        # write a pidfile if requested
+        if o in ('--pidfile'):
+            sickbeard.PIDFILE = str(a)
+
+            # if the pidfile already exists, sickbeard may still be running, so exit
+            if os.path.exists(sickbeard.PIDFILE):
+                sys.exit("PID file " + sickbeard.PIDFILE + " already exists. Exiting.")
+
+            # a pidfile is only useful in daemon mode
+            # also, test to make sure we can write the file properly
+            if sickbeard.DAEMON:
+                sickbeard.CREATEPID = True
+                try:
+                    file(sickbeard.PIDFILE, 'w').write("pid\n")
+                except IOError, e:
+                    raise SystemExit("Unable to write PID file: %s [%d]" % (e.strerror, e.errno))
+            else:
+                logger.log(u"Not running in daemon mode. PID file creation disabled.")
+
     if consoleLogging:
         print "Starting up Sick Beard "+SICKBEARD_VERSION+" from " + sickbeard.CONFIG_FILE
 
diff --git a/autoProcessTV/hellaToSickBeard.py b/autoProcessTV/hellaToSickBeard.py
index 65aadeae7df2d81716d05f0092c109f442be937c..5b73da7eb3a286c3f536177bf6e35f0e8bd65d00 100755
--- a/autoProcessTV/hellaToSickBeard.py
+++ b/autoProcessTV/hellaToSickBeard.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 # Author: Nic Wolfe <nic@wolfeden.ca>
 # URL: http://code.google.com/p/sickbeard/
diff --git a/autoProcessTV/sabToSickBeard.py b/autoProcessTV/sabToSickBeard.py
index c2d5e546b6b8a08f20be48f64796cc07b24b1fc8..8df7b1cc2e5dca4f05f8cdf957fab7be4938fc64 100755
--- a/autoProcessTV/sabToSickBeard.py
+++ b/autoProcessTV/sabToSickBeard.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 # Author: Nic Wolfe <nic@wolfeden.ca>
 # URL: http://code.google.com/p/sickbeard/
@@ -28,4 +28,4 @@ if len(sys.argv) < 2:
 elif len(sys.argv) >= 3:
     autoProcessTV.processEpisode(sys.argv[1], sys.argv[2])
 else:
-    autoProcessTV.processEpisode(sys.argv[1])
\ No newline at end of file
+    autoProcessTV.processEpisode(sys.argv[1])
diff --git a/data/css/config.css b/data/css/config.css
index 20c12187cee024236e90068f2c1fdb22677d6ca3..f52f8a54c70c4ef51e32d64bf9110be7ad261276 100644
--- a/data/css/config.css
+++ b/data/css/config.css
@@ -1,7 +1,8 @@
 #config{text-align:center;padding:0 30px 20px;}
 #config *{font-family:"Trebuchet MS", Verdana, sans-serif;margin:0;padding:0;}
-#config .imgLink img {padding-bottom:1px;}
-#config ul{list-style-type:none;}
+#config h3 a {text-decoration: none;}
+#config h3 img {vertical-align: baseline; padding-right: 5px;}
+#config ul{list-style-type:none;padding-left: 20px;}
 #config h3{font-size:1.5em;color:#000;}
 #config h4{font-size:1em;color:#333;text-transform:uppercase;margin:0 0 .2em;}
 #config h5{font-size:1em;color:#000;margin:0 0 .2em;}
diff --git a/data/css/default.css b/data/css/default.css
index 22034baff171604b6d6448a1cc7418ae88ebdd38..3435ae355a20a9211f623f4876ac3bf507b38c8c 100644
--- a/data/css/default.css
+++ b/data/css/default.css
@@ -85,9 +85,13 @@ font-weight:700;
 }
 
 .h2footer {
-margin-top:-33px;
-margin-right:5px;
+margin: -33px 5px 6px 0px;
 }
+.h2footer select {
+margin-top: -6px;
+margin-bottom: -6px;
+}
+
 .h2footer span {
 padding:2px;
 } 
diff --git a/data/css/smooth-grinder/images/ui-bg_glass_55_fbf9ee_1x400.png b/data/css/smooth-grinder/images/ui-bg_glass_55_fbf9ee_1x400.png
index ad3d6346e00f246102f72f2e026ed0491988b394..b39a6fb27ffbb1f3712e6cfa09e32d8ac084469b 100644
Binary files a/data/css/smooth-grinder/images/ui-bg_glass_55_fbf9ee_1x400.png and b/data/css/smooth-grinder/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/data/css/smooth-grinder/images/ui-bg_highlight-soft_75_dcdcdc_1x100.png b/data/css/smooth-grinder/images/ui-bg_highlight-soft_75_dcdcdc_1x100.png
index 66acd27c22878fbd9c68d3e8b88ba292d595c118..cb6f952f2dc0fff714668e9c79358437078e6fd3 100644
Binary files a/data/css/smooth-grinder/images/ui-bg_highlight-soft_75_dcdcdc_1x100.png and b/data/css/smooth-grinder/images/ui-bg_highlight-soft_75_dcdcdc_1x100.png differ
diff --git a/data/css/smooth-grinder/images/ui-bg_highlight-soft_75_efefef_1x100.png b/data/css/smooth-grinder/images/ui-bg_highlight-soft_75_efefef_1x100.png
index 27fa2fa9fb2c8bb3002e94a81cb04a7a039ec69d..077a5024dbd1dd8e8724f41a10bd8314eb57c9b9 100644
Binary files a/data/css/smooth-grinder/images/ui-bg_highlight-soft_75_efefef_1x100.png and b/data/css/smooth-grinder/images/ui-bg_highlight-soft_75_efefef_1x100.png differ
diff --git a/data/css/smooth-grinder/images/ui-bg_inset-soft_75_dfdfdf_1x100.png b/data/css/smooth-grinder/images/ui-bg_inset-soft_75_dfdfdf_1x100.png
index e6aece058547c64052a118372fded69fa25b1400..c33667aee3d67c6620bdcf7b8a6a7b1c40d4a9ea 100644
Binary files a/data/css/smooth-grinder/images/ui-bg_inset-soft_75_dfdfdf_1x100.png and b/data/css/smooth-grinder/images/ui-bg_inset-soft_75_dfdfdf_1x100.png differ
diff --git a/data/css/smooth-grinder/images/ui-icons_8c291d_256x240.png b/data/css/smooth-grinder/images/ui-icons_8c291d_256x240.png
index 961c8fea3bd431af0918d53a6ff55f8f8bfd014e..a90f0cec755b4a555e4d505ed45a02893c305dd5 100644
Binary files a/data/css/smooth-grinder/images/ui-icons_8c291d_256x240.png and b/data/css/smooth-grinder/images/ui-icons_8c291d_256x240.png differ
diff --git a/data/css/smooth-grinder/jquery-ui-1.8.10.custom.css b/data/css/smooth-grinder/jquery-ui-1.8.11.custom.css
similarity index 94%
rename from data/css/smooth-grinder/jquery-ui-1.8.10.custom.css
rename to data/css/smooth-grinder/jquery-ui-1.8.11.custom.css
index b813dbcc0e465c993a8e88ee0f5627b878d1e554..7399261c996ffcfb55b78315f9174ddfa297cc97 100644
--- a/data/css/smooth-grinder/jquery-ui-1.8.10.custom.css
+++ b/data/css/smooth-grinder/jquery-ui-1.8.11.custom.css
@@ -1,5 +1,5 @@
 /*
- * jQuery UI CSS Framework 1.8.10
+ * jQuery UI CSS Framework 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -42,7 +42,7 @@
 
 
 /*
- * jQuery UI CSS Framework 1.8.10
+ * jQuery UI CSS Framework 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -50,7 +50,7 @@
  *
  * http://docs.jquery.com/UI/Theming/API
  *
- * To view and modify this theme, visit http://jqueryui.com/themeroller/?ctl=themeroller&ffDefault=Verdana,Arial,sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=ffffff&bgTextureHeader=01_flat.png&bgImgOpacityHeader=0&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=dcdcdc&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=efefef&bgTextureDefault=03_highlight_soft.png&bgImgOpacityDefault=75&borderColorDefault=aaaaaa&fcDefault=222222&iconColorDefault=8c291d&bgColorHover=dddddd&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=222222&iconColorHover=222222&bgColorActive=dfdfdf&bgTextureActive=05_inset_soft.png&bgImgOpacityActive=75&borderColorActive=aaaaaa&fcActive=140f06&iconColorActive=8c291d&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=aaaaaa&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=aaaaaa&fcError=8c291d&iconColorError=cd0a0a&bgColorOverlay=6e4f1c&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=35&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=35&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ctl=themeroller&ctl=themeroller&ffDefault=Verdana,Arial,sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=ffffff&bgTextureHeader=01_flat.png&bgImgOpacityHeader=0&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=dcdcdc&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=efefef&bgTextureDefault=03_highlight_soft.png&bgImgOpacityDefault=75&borderColorDefault=aaaaaa&fcDefault=222222&iconColorDefault=8c291d&bgColorHover=dddddd&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=222222&iconColorHover=222222&bgColorActive=dfdfdf&bgTextureActive=05_inset_soft.png&bgImgOpacityActive=75&borderColorActive=aaaaaa&fcActive=140f06&iconColorActive=8c291d&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=aaaaaa&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=aaaaaa&fcError=8c291d&iconColorError=cd0a0a&bgColorOverlay=6e4f1c&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=35&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=35&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
  */
 
 
@@ -298,7 +298,7 @@
 .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #000000 url(images/ui-bg_flat_0_000000_40x100.png) 50% 50% repeat-x; opacity: .35;filter:Alpha(Opacity=35); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
 */
 /*
- * jQuery UI Resizable 1.8.10
+ * jQuery UI Resizable 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -317,7 +317,7 @@
 .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
 .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
 .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
- * jQuery UI Selectable 1.8.10
+ * jQuery UI Selectable 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -327,7 +327,7 @@
  */
 .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
 /*
- * jQuery UI Accordion 1.8.10
+ * jQuery UI Accordion 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -346,7 +346,7 @@
 .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
 .ui-accordion .ui-accordion-content-active { display: block; }
 /*
- * jQuery UI Button 1.8.10
+ * jQuery UI Button 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -384,7 +384,7 @@ input.ui-button { padding: .4em 1em; }
 /* workarounds */
 button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
 /*
- * jQuery UI Dialog 1.8.10
+ * jQuery UI Dialog 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -405,7 +405,7 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
 .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
 .ui-draggable .ui-dialog-titlebar { cursor: move; }
 /*
- * jQuery UI Slider 1.8.10
+ * jQuery UI Slider 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -429,7 +429,7 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
 .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
 .ui-slider-vertical .ui-slider-range-max { top: 0; }
 /*
- * jQuery UI Tabs 1.8.10
+ * jQuery UI Tabs 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -447,7 +447,7 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
 .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
 .ui-tabs .ui-tabs-hide { display: none !important; }
 /*
- * jQuery UI Datepicker 1.8.10
+ * jQuery UI Datepicker 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -514,7 +514,7 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
     width: 200px; /*must have*/
     height: 200px; /*must have*/
 }/*
- * jQuery UI Progressbar 1.8.10
+ * jQuery UI Progressbar 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
diff --git a/data/images/notifiers/growl.gif b/data/images/notifiers/growl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..df0b42bd943d4908e4931cade78369141fb18ccd
Binary files /dev/null and b/data/images/notifiers/growl.gif differ
diff --git a/data/images/notifiers/libnotify.gif b/data/images/notifiers/libnotify.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b6c2e553bde7266530e370b218ced6803d96d7cb
Binary files /dev/null and b/data/images/notifiers/libnotify.gif differ
diff --git a/data/images/notifiers/nmj.gif b/data/images/notifiers/nmj.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1673ab030168b93d0ad6aa57dcf11a0ae12de14c
Binary files /dev/null and b/data/images/notifiers/nmj.gif differ
diff --git a/data/images/notifiers/notifo.gif b/data/images/notifiers/notifo.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ea145d3ccfb1134c69c074d26045178692b7e23b
Binary files /dev/null and b/data/images/notifiers/notifo.gif differ
diff --git a/data/images/notifiers/plex.gif b/data/images/notifiers/plex.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5f3103f07bbad1f16d300a281b1ae48793880950
Binary files /dev/null and b/data/images/notifiers/plex.gif differ
diff --git a/data/images/notifiers/prowl.gif b/data/images/notifiers/prowl.gif
new file mode 100644
index 0000000000000000000000000000000000000000..082bcf479b2e8f84e7c06a68d3a35c0afc289305
Binary files /dev/null and b/data/images/notifiers/prowl.gif differ
diff --git a/data/images/notifiers/twitter.gif b/data/images/notifiers/twitter.gif
new file mode 100644
index 0000000000000000000000000000000000000000..973344d0261f98bdadfca13816d1516783642cbb
Binary files /dev/null and b/data/images/notifiers/twitter.gif differ
diff --git a/data/images/notifiers/xbmc.gif b/data/images/notifiers/xbmc.gif
new file mode 100644
index 0000000000000000000000000000000000000000..cd4b597bfd5393283b0d771e179f264f8856b3f4
Binary files /dev/null and b/data/images/notifiers/xbmc.gif differ
diff --git a/data/images/providers/tvtorrents.gif b/data/images/providers/tvtorrents.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9ce79fe39b05658e570aa485104594d4d895c323
Binary files /dev/null and b/data/images/providers/tvtorrents.gif differ
diff --git a/data/interfaces/default/config_general.tmpl b/data/interfaces/default/config_general.tmpl
index b29734a4d6318dedd74e8be8af374ae2f05b8a0f..2cbcd3975a4e520779b08ab7cc85ec3e688a1ffe 100644
--- a/data/interfaces/default/config_general.tmpl
+++ b/data/interfaces/default/config_general.tmpl
@@ -12,51 +12,6 @@
 #set global $topmenu="config"#
 #include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_top.tmpl")
 
-<script type="text/javascript">
-<!--
-nameTestURL = "$sbRoot/config/general/testNaming";
-//-->
-</script>
-<script type="text/javascript" src="$sbRoot/js/configGeneral.js"></script>
-#set $anyQualities, $bestQualities = $Quality.splitQuality($sickbeard.QUALITY_DEFAULT)
-<script type="text/javascript" charset="utf-8">
-<!--
-\$(document).ready(function(){
-
-  if (#if $sickbeard.QUALITY_DEFAULT in $qualityPresets then "1" else "0"#) {
-      \$('#customQuality').hide();
-  }
-
-  \$.fn.setFromPresets = function(preset) {
-      if (preset == 0) {
-        \$('#customQuality').show();
-        return
-      } else
-        \$('#customQuality').hide();
-  
-      \$('#anyQualities option').each(function(i) {
-          var result = preset & \$(this).val()
-          if (result > 0) \$(this).attr('selected', 'selected');
-          else \$(this).attr('selected', false);
-      });
-
-      \$('#bestQualities option').each(function(i) {
-          var result = preset & (\$(this).val() << 16)
-          if (result > 0) \$(this).attr('selected', 'selected');
-          else \$(this).attr('selected', false);
-      });
-
-      return
-  }
-  
-  \$('#qualityPreset').change(function(){
-        \$(this).setFromPresets(\$('#qualityPreset :selected').val());
-  });
-
-});
-//-->
-</script>
-
 <div id="config">
 <div id="config-content">
 <h5>All non-absolute folder locations are relative to " <span class="path">$sickbeard.PROG_DIR</span> "</h5>
@@ -105,73 +60,6 @@ nameTestURL = "$sbRoot/config/general/testNaming";
                     </fieldset>
                 </div><!-- /component-group1 //-->
 
-                <div id="core-component-group2" class="component-group clearfix">
-
-                    <div class="component-group-desc">
-                        <h3>Metadata</h3>
-                        <p>The data associated to the data. These are files associated to a TV show in the form of images and text that, when supported, will enhance the viewing experience.</p>
-                    </div>
-
-                    <fieldset class="component-group-list">
-                        <div class="field-pair">
-                            <label class="clearfix">
-                                <span class="component-title jumbo">Metadata Type:</span>
-                                <span class="component-desc">
-                                    #set $m_dict = $metadata.get_metadata_generator_dict()
-                                    <select id="metadataType">
-                                    #for ($cur_name, $cur_generator) in $m_dict.items():
-                                    <option value="$GenericMetadata.makeID($cur_name)">$cur_name</option>
-                                    #end for
-                                    </select>
-                                </span>
-                            </label>
-                            <span>Toggle the metadata options that you wish to be created. <b>Multiple targets may be used.</b></span>
-                        </div>
-
-                        <div id="metadataLegend">
-                            <div style="width: 190px; float: left;">Create:</div>
-                            <div style="width: 260px; float: left;">Results:</div>
-                        </div>
-                        <div class="clearfix"></div>
-
-#for ($cur_name, $cur_generator) in $m_dict.items(): 
-#set $cur_metadata_inst = $sickbeard.metadata_provider_dict[$cur_generator.name]
-#set $cur_id = $GenericMetadata.makeID($cur_name)
-<div class="metadataDiv" id="$cur_id">
-    <div class="metadata_options">
-        <label for="${cur_id}_show_metadata"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_show_metadata" #if $cur_metadata_inst.show_metadata then "checked=\"checked\"" else ""#/>&nbsp;Show Metadata</label>
-        <label for="${cur_id}_episode_metadata"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_episode_metadata" #if $cur_metadata_inst.episode_metadata then "checked=\"checked\"" else ""#/>&nbsp;Episode Metadata</label>
-        <label for="${cur_id}_fanart"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_fanart" #if $cur_metadata_inst.fanart then "checked=\"checked\"" else ""#/>&nbsp;Show Fanart Image</label>
-        <label for="${cur_id}_poster"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_poster" #if $cur_metadata_inst.poster then "checked=\"checked\"" else ""#/>&nbsp;Show Folder Image</label>
-        <label for="${cur_id}_episode_thumbnails"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_episode_thumbnails" #if $cur_metadata_inst.episode_thumbnails then "checked=\"checked\"" else ""#/>&nbsp;Episode Thumbnail</label>
-        <label for="${cur_id}_season_thumbnails"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_season_thumbnails" #if $cur_metadata_inst.season_thumbnails then "checked=\"checked\"" else ""#/>&nbsp;Season Thumbnail</label>
-    </div>
-    <div class="metadata_example">
-        <label for="${cur_id}_show_metadata"><span id="${cur_id}_eg_show_metadata">$cur_metadata_inst.eg_show_metadata</span></label>
-        <label for="${cur_id}_episode_metadata"><span id="${cur_id}_eg_episode_metadata">$cur_metadata_inst.eg_episode_metadata</span></label>
-        <label for="${cur_id}_fanart"><span id="${cur_id}_eg_fanart">$cur_metadata_inst.eg_fanart</span></label>
-        <label for="${cur_id}_poster"><span id="${cur_id}_eg_poster">$cur_metadata_inst.eg_poster</span></label>
-        <label for="${cur_id}_episode_thumbnails"><span id="${cur_id}_eg_episode_thumbnails">$cur_metadata_inst.eg_episode_thumbnails</span></label>
-        <label for="${cur_id}_season_thumbnails"><span id="${cur_id}_eg_season_thumbnails">$cur_metadata_inst.eg_season_thumbnails</span></label>
-    </div>
-    <input type="hidden" name="${cur_id}_data" id="${cur_id}_data" value="$cur_metadata_inst.get_config()" />
-</div>
-#end for
-
-                        <div class="clearfix" style="clear:left;"></div>
-
-                        <div class="field-pair clearfix">
-                            <input type="checkbox" name="use_banner" id="use_banner" #if $sickbeard.USE_BANNER then "checked=checked" else ""#/>
-                            <label class="clearfix" for="use_banner">
-                                <span class="component-title">Use Banners</span>
-                                <span class="component-desc">Use banners instead of posters for your Show Folder Images</span>
-                            </label>
-                        </div>
-
-                        <input type="submit" value="Save Changes" /><br/>
-
-                    </fieldset>
-                </div><!-- /component-group2 //-->
 
                 <div id="core-component-group3" class="component-group clearfix">
 
@@ -235,133 +123,6 @@ nameTestURL = "$sbRoot/config/general/testNaming";
                     </fieldset>
                 </div><!-- /component-group3 //-->
 
-                <div id="core-component-group4" class="component-group clearfix">
-
-                    <div class="component-group-desc">
-                        <h3>Episode Naming</h3>
-                        <p>If post-processing 'Rename episodes' is enabled then use these settings.</p>
-                    </div>
-
-                    #set $naming_ep_type_text = ("1x02", "s01e02", "S01E02")
-                    #set $naming_multi_ep_type_text = ("extend", "duplicate", "repeat")
-                    
-                    <fieldset class="component-group-list">
-                        <div class="field-pair">
-                            <input type="checkbox" name="naming_show_name" id="naming_show_name" #if $sickbeard.NAMING_SHOW_NAME then "checked=\"checked\"" else ""#/>
-                            <label class="clearfix" for="naming_show_name">
-                                <span class="component-title">Show Name</span>
-                                <span class="component-desc">Include the TV show's name when renaming the file?</span>
-                            </label>
-                        </div>
-
-                        <div class="field-pair">
-                            <input type="checkbox" name="naming_ep_name" id="naming_ep_name" #if $sickbeard.NAMING_EP_NAME then "checked=\"checked\"" else ""#/>
-                            <label class="clearfix" for="naming_ep_name">
-                                <span class="component-title">Episode Name</span>
-                                <span class="component-desc">Include the TV show's episode title when renaming the file?</span>
-                            </label>
-                        </div>
-
-                        <div class="field-pair">
-                            <input type="checkbox" name="naming_use_periods" id="naming_use_periods" #if $sickbeard.NAMING_USE_PERIODS then "checked=\"checked\"" else ""#/>
-                            <label class="clearfix" for="naming_use_periods">
-                                <span class="component-title">Use Periods</span>
-                                <span class="component-desc">Replace the spaces with periods in the filename instead?</span>
-                            </label>
-                        </div>
-
-                        <div class="field-pair">
-                            <input type="checkbox" name="naming_quality" id="naming_quality" #if $sickbeard.NAMING_QUALITY then "checked=\"checked\"" else ""#/>
-                            <label class="clearfix" for="naming_quality">
-                                <span class="component-title">Quality</span>
-                                <span class="component-desc">Append the show quality to the end of the filename?</span>
-                            </label>
-                        </div>
-
-                        <div class="field-pair">
-                            <input type="checkbox" name="naming_dates" id="naming_dates" #if $sickbeard.NAMING_DATES then "checked=\"checked\"" else ""#/>
-                            <label class="clearfix" for="naming_dates">
-                                <span class="component-title">Air-By-Date Format</span>
-                                <span class="component-desc">Use the date instead of the season/episode format?</span>
-                            </label>
-                            <label class="nocheck clearfix">
-                                <span class="component-title">&nbsp;</span>
-                                <span class="component-desc">Only applies to air-by-date shows. (eg. 2010-02-15 vs S12E23)</span>
-                            </label>
-                        </div>
-
-                        <div class="field-pair">
-                            <label class="nocheck clearfix" for="naming_sep_type">
-                                <span class="component-title">Separator Style</span>
-                                <span class="component-desc">
-                                    <select name="naming_sep_type" id="naming_sep_type">
-                                    #for ($i, $ex) in enumerate($config.naming_sep_type_text):
-                                    <option value="$i" #if $i == int($sickbeard.NAMING_SEP_TYPE) then "selected=\"selected\"" else ""#>$ex</option>
-                                    #end for
-                                    </select>
-                                </span>
-                            </label>
-                        </div>
-
-                        <div class="field-pair">
-                            <label class="nocheck clearfix" for="naming_ep_type">
-                                <span class="component-title">Number Style</span>
-                                <span class="component-desc">
-                                    <select name="naming_ep_type" id="naming_ep_type">
-                                    #for ($i, $ex) in enumerate($config.naming_ep_type_text):
-                                    <option value="$i" #if $i == int($sickbeard.NAMING_EP_TYPE) then "selected=\"selected\"" else ""#>$ex</option>
-                                    #end for
-                                    </select>
-                                </span>
-                            </label>
-                        </div>
-                        
-                        <div class="field-pair" style="padding:10px; background: #efefef;">
-                            <label class="clearfix" for="naming_ep_type">
-                                <span class="component-title jumbo">Single-Ep Example:</span>
-                                <span class="component-desc jumbo" id="normalExampleText"></span>
-                            </label>
-                        </div>
-
-                        <div class="field-pair">
-                            <label class="nocheck clearfix" for="naming_multi_ep_type">
-                                <span class="component-title">Multi-episode Style</span>
-                                <span class="component-desc">
-                                    <select name="naming_multi_ep_type" id="naming_multi_ep_type">
-                                    #for ($i, $ex) in enumerate($config.naming_multi_ep_type_text):
-                                    <option value="$i" #if $i == int($sickbeard.NAMING_MULTI_EP_TYPE) then "selected=\"selected\"" else ""#>$ex</option>
-                                    #end for
-                                    </select>
-                                </span>
-                            </label>
-                        </div>
-
-                        <div class="field-pair" style="padding:10px; background: #efefef;">
-                            <label class="clearfix" for="naming_multi_ep_type">
-                                <span class="component-title jumbo">Multi-Ep Example:</span>
-                                <span class="component-desc jumbo" id="multiExampleText"></span>
-                            </label>
-                        </div>
-                        
-                        <div class="field-pair">
-                            <label class="nocheck clearfix">
-                                <span class="component-title">Season Folder Format</span>
-                                <input type="text" id="season_folders_format" name="season_folders_format" value="$sickbeard.SEASON_FOLDERS_FORMAT" size="15" />
-                            </label>
-                            <label class="nocheck clearfix">
-                                <span class="component-title">&nbsp;</span>
-                                <span class="component-desc">Format to use when creating season folders.</span>
-                            </label>
-                            <label class="nocheck clearfix">
-                                <span class="component-title">&nbsp;</span>
-                                <span class="component-desc">(eg. 'Season %0d' or 'season%02d')</span>
-                            </label>
-                        </div>
-
-                        <input type="submit" value="Save Changes" />
-                    </fieldset>
-                </div><!-- /component-group4 //-->
-
             <br/><input type="submit" value="Save Changes" /><br/>
             </div><!-- /config-components -->
 
diff --git a/data/interfaces/default/config_notifications.tmpl b/data/interfaces/default/config_notifications.tmpl
index b2133838293abf7de2e8086f1c516891260d2d8b..d8a8596606b42b4e51140305456ed02f5ab18ce2 100644
--- a/data/interfaces/default/config_notifications.tmpl
+++ b/data/interfaces/default/config_notifications.tmpl
@@ -8,6 +8,7 @@
 #include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_top.tmpl")
 
 <script type="text/javascript" src="$sbRoot/js/configNotifications.js"></script>
+<script type="text/javascript" src="$sbRoot/js/config.js"></script>
 
 <div id="config">
 <div id="config-content">
@@ -19,7 +20,7 @@
                 <div id="core-component-group1" class="component-group clearfix">
 
                     <div class="component-group-desc">
-                        <h3>XBMC</h3>
+                        <h3><a href="http://xbmc.org/" onclick="window.open(this.href, '_blank'); return false;"><img src="$sbRoot/images/notifiers/xbmc.gif" alt="XBMC" title="XBMC" width="16" height="16" /> XBMC</a></h3>
                         <p>A free and open source cross-platform media center and home entertainment system software with a 10-foot user interface designed for the living-room TV.</p>
                     </div>
 
@@ -114,7 +115,101 @@
                 <div id="core-component-group2" class="component-group clearfix">
 
                     <div class="component-group-desc">
-                        <h3>Growl</h3>
+                        <h3><a href="http://www.plexapp.com/" onclick="window.open(this.href, '_blank'); return false;"><img src="$sbRoot/images/notifiers/plex.gif" alt="Plex Media Server" title="Plex Media Server" width="16" height="16" /> Plex Media Server</a></h3>
+                        <p>Experience your media on a visually stunning, easy to use interface on your Mac connected to your TV. Your media library has never looked this good!</p>
+                    </div>
+
+                    <fieldset class="component-group-list">
+                        <div class="field-pair">
+                            <input type="checkbox" class="enabler" name="use_plex" id="use_plex" #if $sickbeard.USE_PLEX then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="use_plex">
+                                <span class="component-title">Enable</span>
+                                <span class="component-desc">Should Sick Beard send Plex commands?</span>
+                            </label>
+                        </div>
+
+                        <div id="content_use_plex">
+                        <div class="field-pair">
+                            <input type="checkbox" name="plex_notify_onsnatch" id="plex_notify_onsnatch" #if $sickbeard.PLEX_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="plex_notify_onsnatch">
+                                <span class="component-title">Notify on Snatch</span>
+                                <span class="component-desc">Send notification when we start a download?</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="plex_notify_ondownload" id="plex_notify_ondownload" #if $sickbeard.PLEX_NOTIFY_ONDOWNLOAD then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="plex_notify_ondownload">
+                                <span class="component-title">Notify on Download</span>
+                                <span class="component-desc">Send notification when we finish a download?</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="plex_update_library" id="plex_update_library" #if $sickbeard.PLEX_UPDATE_LIBRARY then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="plex_update_library">
+                                <span class="component-title">Update Library</span>
+                                <span class="component-desc">Update Plex Media Server library when we finish a download?</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix">
+                                <span class="component-title">Plex Media Server IP:Port</span>
+                                <input type="text" name="plex_server_host" id="plex_server_host" value="$sickbeard.PLEX_SERVER_HOST" size="35" />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">Host running Plex Media Server (eg. 192.168.1.100:32400)</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix">
+                                <span class="component-title">Plex Client IP:Port</span>
+                                <input type="text" name="plex_host" id="plex_host" value="$sickbeard.PLEX_HOST" size="35" />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">Host running Plex Client (eg. 192.168.1.100:3000)</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix">
+                                <span class="component-title">Plex Client Username</span>
+                                <input type="text" name="plex_username" id="plex_username" value="$sickbeard.PLEX_USERNAME" size="35" />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">Username of your Plex client API (blank for none)</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix">
+                                <span class="component-title">Plex Client Password</span>
+                                <input type="password" name="plex_password" id="plex_password" value="$sickbeard.PLEX_PASSWORD" size="35" />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">Password of your Plex client API (blank for none)</span>
+                            </label>
+                        </div>
+
+                        <div class="testNotification" id="testPLEX-result">Click below to test.</div>
+                        <input type="button" value="Test Plex Media Server" id="testPLEX" />
+                        <input type="submit" value="Save Changes" />
+
+                        </div><!-- /enabler_plex -->
+
+                    </fieldset>
+                </div><!-- /component-group -->
+
+                <div id="core-component-group3" class="component-group clearfix">
+
+                    <div class="component-group-desc">
+                        <h3><a href="http://growl.info/" onclick="window.open(this.href, '_blank'); return false;"><img src="$sbRoot/images/notifiers/growl.gif" alt="Growl" title="Growl" width="16" height="16" /> Growl</a></h3>
                         <p>A cross-platform unobtrusive global notification system.</p>
                     </div>
 
@@ -179,10 +274,10 @@
                     </fieldset>
                 </div><!-- /component-group //-->
 
-                <div id="core-component-group3" class="component-group clearfix">
+                <div id="core-component-group4" class="component-group clearfix">
                 
                     <div class="component-group-desc">
-                        <h3>Twitter</h3>
+                        <h3><a href="http://www.twitter.com/" onclick="window.open(this.href, '_blank'); return false;"><img src="$sbRoot/images/notifiers/twitter.gif" alt="Twitter" title="Twitter" width="16" height="16" /> Twitter</a></h3>
                         <p>A social networking and microblogging service, enabling its users to send and read other users' messages called tweets.</p>
                     </div>
 
@@ -254,10 +349,10 @@
                     </fieldset>
                 </div><!-- /component-group //-->
                 
-            <div id="core-component-group4" class="component-group clearfix">
+            <div id="core-component-group5" class="component-group clearfix">
 
                     <div class="component-group-desc">
-                        <h3>Prowl</h3>
+                        <h3><a href="http://www.prowlapp.com/" onclick="window.open(this.href, '_blank'); return false;"><img src="$sbRoot/images/notifiers/prowl.gif" alt="Prowl" title="Prowl" width="16" height="16" /> Prowl</a></h3>
                         <p>A Growl client for iOS.</p>
                     </div>
 
@@ -324,10 +419,10 @@
                     </fieldset>
                 </div><!-- /component-group //-->
 
-                 <div id="core-component-group5" class="component-group clearfix">
+                 <div id="core-component-group6" class="component-group clearfix">
 
                     <div class="component-group-desc">
-                        <h3>Notifo</h3>
+                        <h3><a href="http://notifo.com/" onclick="window.open(this.href, '_blank'); return false;"><img src="$sbRoot/images/notifiers/notifo.gif" alt="Notifo" title="Notifo" width="16" height="16" /> Notifo</a></h3>
                         <p>A platform for push-notifications to either mobile or desktop clients</p>
                     </div>
 
@@ -390,9 +485,9 @@
                 </div>
 
 
-                <div id="core-component-group6" class="component-group clearfix">
+                <div id="core-component-group7" class="component-group clearfix">
                     <div class="component-group-desc">
-                        <h3>Libnotify</h3>
+                        <h3><a href="http://library.gnome.org/devel/libnotify/" onclick="window.open(this.href, '_blank'); return false;"><img src="$sbRoot/images/notifiers/libnotify.gif" alt="Libnotify" title="Libnotify" width="16" height="16" /> Libnotify</a></h3>
                         <p>The standard desktop notification API for Linux/*nix systems.  This notifier will only function if the pynotify module is installed (Ubuntu/Debian package <a href="apt:python-notify">python-notify</a>).</p>
                     </div>
 
@@ -401,7 +496,7 @@
                             <input type="checkbox" class="enabler" name="use_libnotify" id="use_libnotify" #if $sickbeard.USE_LIBNOTIFY then "checked=\"checked\"" else ""# /> 
                             <label class="clearfix" for="use_libnotify">
                                 <span class="component-title">Enable</span>
-                                <span class="component-desc">Should Sick Beard send libnotify notifications?</span>
+                                <span class="component-desc">Should Sick Beard send Libnotify notifications?</span>
                             </label>
                         </div>
 
@@ -431,6 +526,74 @@
                     </fieldset>
                 </div><!-- /component-group //-->
 
+                <div id="core-component-group8" class="component-group clearfix">
+
+                    <div class="component-group-desc">
+                        <h3><a href="http://www.popcornhour.com/" onclick="window.open(this.href, '_blank'); return false;"><img src="$sbRoot/images/notifiers/nmj.gif" alt="Networked Media Jukebox" title="Networked Media Jukebox" width="16" height="16" /> NMJ</a></h3>
+                        <p>The Networked Media Jukebox, or NMJ, is the official media jukebox interface made available for the Popcorn Hour 200-series.</p>
+                    </div>
+
+                    <fieldset class="component-group-list">
+                        <div class="field-pair">
+                            <input type="checkbox" class="enabler" name="use_nmj" id="use_nmj" #if $sickbeard.USE_NMJ then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="use_nmj">
+                                <span class="component-title">Enable</span>
+                                <span class="component-desc">Should Sick Beard send update commands to NMJ?</span>
+                            </label>
+                        </div>
+
+                        <div id="content_use_nmj">
+                        <div class="field-pair">
+                            <label class="nocheck clearfix">
+                                <span class="component-title">Popcorn IP address</span>
+                                <input type="text" name="nmj_host" id="nmj_host" value="$sickbeard.NMJ_HOST" size="35" />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">IP of Popcorn 200-series (eg. 192.168.1.100)</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix">
+                                <span class="component-title">Get Settings</span>
+                                <input type="button" value="Get Settings" id="settingsNMJ" />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">The Popcorn Hour device must be powered on and NMJ running.</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix">
+                                <span class="component-title">NMJ Database</span>
+                                <input type="text" name="nmj_database" id="nmj_database" value="$sickbeard.NMJ_DATABASE" size="35" #if $sickbeard.NMJ_DATABASE then "readonly=\"readonly\"" else ""# />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">Automatically filled via the 'Get Settings' button.</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix">
+                                <span class="component-title">NMJ Mount URL</span>
+                                <input type="text" name="nmj_mount" id="nmj_mount" value="$sickbeard.NMJ_MOUNT" size="35" #if $sickbeard.NMJ_MOUNT then "readonly=\"readonly\"" else ""# />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">Automatically filled via the 'Get Settings' button.</span>
+                            </label>
+                        </div>
+
+                        <div class="testNotification" id="testNMJ-result">Click below to test.</div>
+                        <input type="button" value="Test NMJ" id="testNMJ" />
+                        <input type="submit" value="Save Changes" />
+                        </div><!-- /content_use_nmj //-->
+                    </fieldset>
+                </div><!-- /component-group //-->
+
             <br/><input type="submit" value="Save Changes" /><br/>
 
             </div><!-- /config-components //-->
diff --git a/data/interfaces/default/config_postProcessing.tmpl b/data/interfaces/default/config_postProcessing.tmpl
new file mode 100644
index 0000000000000000000000000000000000000000..eeb2434ab3ee76570f9021755d3e4c93275f6b4b
--- /dev/null
+++ b/data/interfaces/default/config_postProcessing.tmpl
@@ -0,0 +1,302 @@
+#import os.path
+#import sickbeard
+#from sickbeard.common import *
+#from sickbeard import config
+#from sickbeard import metadata
+#from sickbeard.metadata.generic import GenericMetadata
+#set global $title  = "Config - Post Processing"
+#set global $header = "Post Processing Configuration"
+
+#set global $sbPath="../.."
+
+#set global $topmenu="config"#
+#include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_top.tmpl")
+
+<script type="text/javascript" src="$sbRoot/js/configPostProcessing.js"></script>
+
+<div id="config">
+<div id="config-content">
+<h5>All non-absolute folder locations are relative to " <span class="path">$sickbeard.PROG_DIR</span> "</h5>
+
+<form action="savePostProcessing" method="post">
+
+            <div id="config-components">
+                
+                <div id="core-component-group3" class="component-group clearfix">
+
+                    <div class="component-group-desc">
+                        <h3>Post-Processing</h3>
+                        <p>Settings that dictate how Sick Beard should process completed downloads.</p>
+                    </div>
+
+                    <fieldset class="component-group-list">
+                        <div class="field-pair">
+                            <label class="nocheck clearfix" for="tv_download_dir">
+                                <span class="component-title">TV Download Dir</span>
+                                <input type="text" name="tv_download_dir" id="tv_download_dir" value="$sickbeard.TV_DOWNLOAD_DIR" size="45" />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">The folder where your download client puts your TV downloads.</span>
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc"><b>NOTE:</b> Use only if not using SABnzbd+ post processing.</span>
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">Or if SABnzbd+ and Sick Beard are on different PCs.</span>
+                            </label>
+                        </div>
+
+                        
+                        <div class="field-pair">
+                            <input type="checkbox" name="keep_processed_dir" id="keep_processed_dir" #if $sickbeard.KEEP_PROCESSED_DIR == True then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="keep_processed_dir">
+                                <span class="component-title">Keep Original Files</span>
+                                <span class="component-desc">Keep original files after they've been processed?</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="move_associated_files" id="move_associated_files" #if $sickbeard.MOVE_ASSOCIATED_FILES == True then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="move_associated_files">
+                                <span class="component-title">Move Associated Files</span>
+                                <span class="component-desc">Move srr/srt/sfv/etc files with the episode when processed?</span>
+                            </label>
+                            <label class="nocheck clearfix" for="move_associated_files">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc"><b>NOTE:</b> <i>.nfo</i> will be renamed to <i>.nfo-orig</i> when moved.</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="rename_episodes" id="rename_episodes" #if $sickbeard.RENAME_EPISODES == True then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="rename_episodes">
+                                <span class="component-title">Rename Episodes</span>
+                                <span class="component-desc">Rename episode using the naming settings below?</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="process_automatically" id="process_automatically" #if $sickbeard.PROCESS_AUTOMATICALLY == True then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="process_automatically">
+                                <span class="component-title">Scan and Process</span>
+                                <span class="component-desc">Scan and post-process any files in your <i>TV Download Dir</i>?</span>
+                            </label>
+                            <label class="nocheck clearfix" for="process_automatically">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc"><b>NOTE:</b> Do not use if you use sabToSickbeard w/ SABnzbd+!</span>
+                            </label>
+                        </div>
+
+                        <div class="clearfix"></div>
+                        <input type="submit" value="Save Changes" /><br/>
+
+                    </fieldset>
+                </div><!-- /component-group3 //-->
+
+                <div id="core-component-group2" class="component-group clearfix">
+
+                    <div class="component-group-desc">
+                        <h3>Metadata</h3>
+                        <p>The data associated to the data. These are files associated to a TV show in the form of images and text that, when supported, will enhance the viewing experience.</p>
+                    </div>
+
+                    <fieldset class="component-group-list">
+                        <div class="field-pair">
+                            <label class="clearfix">
+                                <span class="component-title jumbo">Metadata Type:</span>
+                                <span class="component-desc">
+                                    #set $m_dict = $metadata.get_metadata_generator_dict()
+                                    <select id="metadataType">
+                                    #for ($cur_name, $cur_generator) in $m_dict.items():
+                                    <option value="$GenericMetadata.makeID($cur_name)">$cur_name</option>
+                                    #end for
+                                    </select>
+                                </span>
+                            </label>
+                            <span>Toggle the metadata options that you wish to be created. <b>Multiple targets may be used.</b></span>
+                        </div>
+
+                        <div id="metadataLegend">
+                            <div style="width: 190px; float: left;">Create:</div>
+                            <div style="width: 260px; float: left;">Results:</div>
+                        </div>
+                        <div class="clearfix"></div>
+
+#for ($cur_name, $cur_generator) in $m_dict.items(): 
+#set $cur_metadata_inst = $sickbeard.metadata_provider_dict[$cur_generator.name]
+#set $cur_id = $GenericMetadata.makeID($cur_name)
+<div class="metadataDiv" id="$cur_id">
+    <div class="metadata_options">
+        <label for="${cur_id}_show_metadata"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_show_metadata" #if $cur_metadata_inst.show_metadata then "checked=\"checked\"" else ""#/>&nbsp;Show Metadata</label>
+        <label for="${cur_id}_episode_metadata"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_episode_metadata" #if $cur_metadata_inst.episode_metadata then "checked=\"checked\"" else ""#/>&nbsp;Episode Metadata</label>
+        <label for="${cur_id}_fanart"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_fanart" #if $cur_metadata_inst.fanart then "checked=\"checked\"" else ""#/>&nbsp;Show Fanart Image</label>
+        <label for="${cur_id}_poster"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_poster" #if $cur_metadata_inst.poster then "checked=\"checked\"" else ""#/>&nbsp;Show Folder Image</label>
+        <label for="${cur_id}_episode_thumbnails"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_episode_thumbnails" #if $cur_metadata_inst.episode_thumbnails then "checked=\"checked\"" else ""#/>&nbsp;Episode Thumbnail</label>
+        <label for="${cur_id}_season_thumbnails"><input type="checkbox" class="metadata_checkbox" id="${cur_id}_season_thumbnails" #if $cur_metadata_inst.season_thumbnails then "checked=\"checked\"" else ""#/>&nbsp;Season Thumbnail</label>
+    </div>
+    <div class="metadata_example">
+        <label for="${cur_id}_show_metadata"><span id="${cur_id}_eg_show_metadata">$cur_metadata_inst.eg_show_metadata</span></label>
+        <label for="${cur_id}_episode_metadata"><span id="${cur_id}_eg_episode_metadata">$cur_metadata_inst.eg_episode_metadata</span></label>
+        <label for="${cur_id}_fanart"><span id="${cur_id}_eg_fanart">$cur_metadata_inst.eg_fanart</span></label>
+        <label for="${cur_id}_poster"><span id="${cur_id}_eg_poster">$cur_metadata_inst.eg_poster</span></label>
+        <label for="${cur_id}_episode_thumbnails"><span id="${cur_id}_eg_episode_thumbnails">$cur_metadata_inst.eg_episode_thumbnails</span></label>
+        <label for="${cur_id}_season_thumbnails"><span id="${cur_id}_eg_season_thumbnails">$cur_metadata_inst.eg_season_thumbnails</span></label>
+    </div>
+    <input type="hidden" name="${cur_id}_data" id="${cur_id}_data" value="$cur_metadata_inst.get_config()" />
+</div>
+#end for
+
+                        <div class="clearfix" style="clear:left;"></div>
+
+                        <div class="field-pair clearfix">
+                            <input type="checkbox" name="use_banner" id="use_banner" #if $sickbeard.USE_BANNER then "checked=checked" else ""#/>
+                            <label class="clearfix" for="use_banner">
+                                <span class="component-title">Use Banners</span>
+                                <span class="component-desc">Use banners instead of posters for your Show Folder Images</span>
+                            </label>
+                        </div>
+
+                        <input type="submit" value="Save Changes" /><br/>
+
+                    </fieldset>
+                </div><!-- /component-group2 //-->
+
+                <div id="core-component-group4" class="component-group clearfix">
+
+                    <div class="component-group-desc">
+                        <h3>Episode Naming</h3>
+                        <p>If post-processing 'Rename episodes' is enabled then use these settings.</p>
+                    </div>
+
+                    #set $naming_ep_type_text = ("1x02", "s01e02", "S01E02")
+                    #set $naming_multi_ep_type_text = ("extend", "duplicate", "repeat")
+                    
+                    <fieldset class="component-group-list">
+                        <div class="field-pair">
+                            <input type="checkbox" name="naming_show_name" id="naming_show_name" #if $sickbeard.NAMING_SHOW_NAME then "checked=\"checked\"" else ""#/>
+                            <label class="clearfix" for="naming_show_name">
+                                <span class="component-title">Show Name</span>
+                                <span class="component-desc">Include the TV show's name when renaming the file?</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="naming_ep_name" id="naming_ep_name" #if $sickbeard.NAMING_EP_NAME then "checked=\"checked\"" else ""#/>
+                            <label class="clearfix" for="naming_ep_name">
+                                <span class="component-title">Episode Name</span>
+                                <span class="component-desc">Include the TV show's episode title when renaming the file?</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="naming_use_periods" id="naming_use_periods" #if $sickbeard.NAMING_USE_PERIODS then "checked=\"checked\"" else ""#/>
+                            <label class="clearfix" for="naming_use_periods">
+                                <span class="component-title">Use Periods</span>
+                                <span class="component-desc">Replace the spaces with periods in the filename instead?</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="naming_quality" id="naming_quality" #if $sickbeard.NAMING_QUALITY then "checked=\"checked\"" else ""#/>
+                            <label class="clearfix" for="naming_quality">
+                                <span class="component-title">Quality</span>
+                                <span class="component-desc">Append the show quality to the end of the filename?</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="naming_dates" id="naming_dates" #if $sickbeard.NAMING_DATES then "checked=\"checked\"" else ""#/>
+                            <label class="clearfix" for="naming_dates">
+                                <span class="component-title">Air-By-Date Format</span>
+                                <span class="component-desc">Use the date instead of the season/episode format?</span>
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">Only applies to air-by-date shows. (eg. 2010-02-15 vs S12E23)</span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix" for="naming_sep_type">
+                                <span class="component-title">Separator Style</span>
+                                <span class="component-desc">
+                                    <select name="naming_sep_type" id="naming_sep_type">
+                                    #for ($i, $ex) in enumerate($config.naming_sep_type_text):
+                                    <option value="$i" #if $i == int($sickbeard.NAMING_SEP_TYPE) then "selected=\"selected\"" else ""#>$ex</option>
+                                    #end for
+                                    </select>
+                                </span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix" for="naming_ep_type">
+                                <span class="component-title">Number Style</span>
+                                <span class="component-desc">
+                                    <select name="naming_ep_type" id="naming_ep_type">
+                                    #for ($i, $ex) in enumerate($config.naming_ep_type_text):
+                                    <option value="$i" #if $i == int($sickbeard.NAMING_EP_TYPE) then "selected=\"selected\"" else ""#>$ex</option>
+                                    #end for
+                                    </select>
+                                </span>
+                            </label>
+                        </div>
+                        
+                        <div class="field-pair" style="padding:10px; background: #efefef;">
+                            <label class="clearfix" for="naming_ep_type">
+                                <span class="component-title jumbo">Single-Ep Example:</span>
+                                <span class="component-desc jumbo" id="normalExampleText"></span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair">
+                            <label class="nocheck clearfix" for="naming_multi_ep_type">
+                                <span class="component-title">Multi-episode Style</span>
+                                <span class="component-desc">
+                                    <select name="naming_multi_ep_type" id="naming_multi_ep_type">
+                                    #for ($i, $ex) in enumerate($config.naming_multi_ep_type_text):
+                                    <option value="$i" #if $i == int($sickbeard.NAMING_MULTI_EP_TYPE) then "selected=\"selected\"" else ""#>$ex</option>
+                                    #end for
+                                    </select>
+                                </span>
+                            </label>
+                        </div>
+
+                        <div class="field-pair" style="padding:10px; background: #efefef;">
+                            <label class="clearfix" for="naming_multi_ep_type">
+                                <span class="component-title jumbo">Multi-Ep Example:</span>
+                                <span class="component-desc jumbo" id="multiExampleText"></span>
+                            </label>
+                        </div>
+                        
+                        <div class="field-pair">
+                            <label class="nocheck clearfix">
+                                <span class="component-title">Season Folder Format</span>
+                                <input type="text" id="season_folders_format" name="season_folders_format" value="$sickbeard.SEASON_FOLDERS_FORMAT" size="15" />
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">Format to use when creating season folders.</span>
+                            </label>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">&nbsp;</span>
+                                <span class="component-desc">(eg. 'Season %0d' or 'season%02d')</span>
+                            </label>
+                        </div>
+
+                        <input type="submit" value="Save Changes" />
+                    </fieldset>
+                </div><!-- /component-group4 //-->
+
+            <br/><input type="submit" value="Save Changes" /><br/>
+            </div><!-- /config-components -->
+
+</form>
+</div></div>
+<div class="clearfix"></div>
+
+
+#include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_bottom.tmpl")
diff --git a/data/interfaces/default/config_providers.tmpl b/data/interfaces/default/config_providers.tmpl
index d5acb09404e7f493066c566b968ed6858348b74a..ff951fe05ab3e7091c264b67a973cb73d0b6c1ee 100644
--- a/data/interfaces/default/config_providers.tmpl
+++ b/data/interfaces/default/config_providers.tmpl
@@ -1,4 +1,5 @@
 #import sickbeard
+#from sickbeard.providers.generic import GenericProvider
 #set global $title="Config - Providers"
 #set global $header="Search Providers"
 
@@ -11,11 +12,11 @@
 <script type="text/javascript" src="$sbRoot/js/configProviders.js"></script>
 <script type="text/javascript" charset="utf-8">
 <!--
-sbRoot = '$sbRoot'; 
 \$(document).ready(function(){
 
+var show_nzb_providers = #if $sickbeard.USE_NZBS then "true" else "false"#;
 #for $curNewznabProvider in $sickbeard.newznabProviderList:
-    \$(this).addProvider('$curNewznabProvider.getID()', '$curNewznabProvider.name', '$curNewznabProvider.url', '$curNewznabProvider.key', $int($curNewznabProvider.default));
+\$(this).addProvider('$curNewznabProvider.getID()', '$curNewznabProvider.name', '$curNewznabProvider.url', '$curNewznabProvider.key', $int($curNewznabProvider.default), show_nzb_providers);
 #end for
 });
 //-->
@@ -34,7 +35,7 @@ sbRoot = '$sbRoot';
                         <h3>Provider Priorities</h3>
                         <p>Check off and drag the providers into the order you want them to be used.</p>
                         <p class="note">At least one provider is required but two are recommended.</p>
-                        <p>More providers offer redundancy but at the expense of a longer search period.</p>
+                        <p>NZB/Torrent providers can be toggled in <a href="$sbRoot/config/search">Search Settings</a></p>
                         <p class="note"><span style="color: #654B24; font-size: 16px;">*</span> Provider does not support backlog searches at this time.</p>
                         <p class="note"><span style="color: #654B24; font-size: 16px;">**</span> Provider supports <b>limited</b> backlog searches, all episodes/qualities may not be available.</p>
                     </div>
@@ -45,15 +46,15 @@ sbRoot = '$sbRoot';
                             #if $curProvider.getID() == 'tvbinz' and not $sickbeard.SHOW_TVBINZ
                                 #continue
                             #end if
-                            #set $curName = $curProvider.getID()
-                            #if $curProvider in $sickbeard.newznabProviderList:
-                              #set $imgName = 'newznab.gif'
-                            #else:
-                              #set $imgName = $curName + '.gif'
+                            #if $curProvider.providerType == $GenericProvider.NZB and not $sickbeard.USE_NZBS:
+                                #continue
+                            #elif $curProvider.providerType == $GenericProvider.TORRENT and not $sickbeard.USE_TORRENTS:
+                                #continue
                             #end if
+                            #set $curName = $curProvider.getID()
                           <li class="ui-state-default" id="$curName">
-                            <input type="checkbox" id="enable_$curName" class="enabler" #if $curProvider.isEnabled() then "checked=\"checked\"" else ""#/>
-                            <a href="$curProvider.url" class="imgLink" target="_new"><img src="$sbRoot/images/providers/$imgName" alt="$curProvider.name" title="$curProvider.name" width="16" height="16" /></a>
+                            <input type="checkbox" id="enable_$curName" class="provider_enabler" #if $curProvider.isEnabled() then "checked=\"checked\"" else ""#/>
+                            <a href="$curProvider.url" class="imgLink" target="_new"><img src="$sbRoot/images/providers/$curProvider.imageName()" alt="$curProvider.name" title="$curProvider.name" width="16" height="16" /></a>
                             $curProvider.name
                             #if not $curProvider.supportsBacklog then "*" else ""#
                             #if $curProvider.name == "EZRSS" then "**" else ""#
@@ -75,15 +76,31 @@ sbRoot = '$sbRoot';
                     <fieldset class="component-group-list">
                         <div class="field-pair">
                             <label class="clearfix" for="editAProvider">
-                                <span class="component-title jumbo">Select Provider:</span>
+                                <span class="component-title jumbo">Configure Provider:</span>
                                 <span class="component-desc">
+                                    #set $provider_config_list = []
+                                    #for $cur_provider in ("nzbs_org", "nzbs_r_us", "newzbin", "nzbmatrix", "tvbinz", "tvtorrents"):
+                                        #set $cur_provider_obj = $sickbeard.providers.getProviderClass($cur_provider)
+                                        #if $cur_provider_obj.getID() == 'tvbinz' and not $sickbeard.SHOW_TVBINZ
+                                            #continue
+                                        #end if
+                                        #if $cur_provider_obj.providerType == $GenericProvider.NZB and not $sickbeard.USE_NZBS:
+                                            #continue
+                                        #elif $cur_provider_obj.providerType == $GenericProvider.TORRENT and not $sickbeard.USE_TORRENTS:
+                                            #continue
+                                        #end if
+                                        $provider_config_list.append($cur_provider_obj)
+                                    #end for
+
+                                    #if $provider_config_list:                                        
                                     <select id="editAProvider">
-                                        #if $sickbeard.SHOW_TVBINZ then "<option value=\"tvbinz\">TVBinz" else ""#
-                                        <option value="nzbs_org">NZBs.org</option>
-                                        <option value="nzbs_r_us">NZBs'R'US</option>
-                                        <option value="newzbin">Newzbin</option>
-                                        <option value="nzbmatrix">NZBMatrix</option>
+                                        #for $cur_provider in $provider_config_list:
+                                            <option value="$cur_provider.getID()">$cur_provider.name</option>
+                                        #end for
                                     </select>
+                                    #else:
+                                    No providers available to configure.
+                                    #end if
                                 </span>
                             </label>
                         </div>
@@ -172,7 +189,23 @@ sbRoot = '$sbRoot';
                             </label>
                         </div>
 </div>
-<!-- end div for editing providers //-->
+
+<div class="providerDiv" id="tvtorrentsDiv">
+                        <div class="field-pair">
+                            <label class="clearfix">
+                                <span class="component-title">TvTorrents Digest:</span>
+                                <input class="component-desc" type="text" name="tvtorrents_digest" value="$sickbeard.TVTORRENTS_DIGEST" size="40" />
+                            </label>
+                        </div>
+                        <div class="field-pair">
+                            <label class="clearfix">
+                                <span class="component-title">TvTorrents Hash:</span>
+                                <input class="component-desc" type="text" name="tvtorrents_hash" value="$sickbeard.TVTORRENTS_HASH" size="40" />
+                            </label>
+                        </div>
+</div>
+
+<!-- end div for editing providers -->
 
                     <input type="submit" value="Save Changes" /><br/>
             
diff --git a/data/interfaces/default/config_episodedownloads.tmpl b/data/interfaces/default/config_search.tmpl
similarity index 68%
rename from data/interfaces/default/config_episodedownloads.tmpl
rename to data/interfaces/default/config_search.tmpl
index eb54bcd2ec6a94867aa8dec70ed0164487482638..1d7b64f42d4df46bc0189d96dbfa039837b7cb8a 100644
--- a/data/interfaces/default/config_episodedownloads.tmpl
+++ b/data/interfaces/default/config_search.tmpl
@@ -1,6 +1,6 @@
 #import sickbeard
 #set global $title="Config - Episode Search"
-#set global $header="Episode Download Options"
+#set global $header="Search Options"
 
 #set global $sbPath="../.."
 
@@ -8,36 +8,13 @@
 #import os.path
 #include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_top.tmpl")
 
-<script type="text/javascript" charset="utf-8">
-<!--
-\$(document).ready(function(){
-
-    \$.fn.nzb_method_handler = function() {
-        
-        var selectedProvider = \$('#nzb_method :selected').val();
-
-        if (selectedProvider == "blackhole") {
-            \$('#blackhole_settings').show();
-            \$('#sabnzbd_settings').hide();
-        } else {
-            \$('#blackhole_settings').hide();
-            \$('#sabnzbd_settings').show();
-        }
-
-    }
-
-    \$('#nzb_method').change(\$(this).nzb_method_handler);
-
-    \$(this).nzb_method_handler();
-
-});
-//-->
-</script>
+<script type="text/javascript" src="$sbRoot/js/configSearch.js"></script>
+<script type="text/javascript" src="$sbRoot/js/config.js"></script>
 
 <div id="config">
 <div id="config-content">
 <h5>All non-absolute folder locations are relative to " <span class="path">$sickbeard.PROG_DIR</span> "</h5>
-<form action="saveEpisodeDownloads" method="post">
+<form action="saveSearch" method="post">
 
             <div id="config-components">
                 
@@ -88,18 +65,28 @@
                 <div id="core-component-group2" class="component-group clearfix">
 
                     <div class="component-group-desc">
-                        <h3>Episode Results</h3>
-                        <p>Settings that dictate how Sick Beard handles NZB and Torrents search results.</p>
+                        <h3>NZB Search</h3>
+                        <p>Settings that dictate how Sick Beard handles NZB search results.</p>
                     </div>
 
                     <fieldset class="component-group-list">
+
+                        <div class="field-pair">
+                            <input type="checkbox" name="use_nzbs" class="enabler" id="use_nzbs" #if $sickbeard.USE_NZBS then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="use_nzbs">
+                                <span class="component-title">Search NZBs</span>
+                                <span class="component-desc">Should Sick Beard search for NZB files?</span>
+                            </label>
+                        </div>
+
+                        <div id="content_use_nzbs">
                         <div class="field-pair">
                             <label class="clearfix" for="nzb_method">
                                 <span class="component-title jumbo">NZB Method:</span>
                                 <span class="component-desc">
                                     <select name="nzb_method" id="nzb_method">
-                                    #set $nzb_method_text = {'blackhole': "Black hole", 'sabnzbd': "SABnzbd"}
-                                    #for $curAction in ('sabnzbd', 'blackhole'):
+                                    #set $nzb_method_text = {'blackhole': "Black hole", 'sabnzbd': "SABnzbd", 'nzbget': "NZBget"}
+                                    #for $curAction in ('sabnzbd', 'blackhole', 'nzbget'):
                                       #if $sickbeard.NZB_METHOD == $curAction:
                                         #set $nzb_method = "selected=\"selected\""
                                       #else
@@ -112,17 +99,6 @@
                             </label>
                         </div>
 
-                        <div class="field-pair">
-                            <label class="nocheck clearfix">
-                                <span class="component-title">Torrent Black Hole</span>
-                                <input type="text" name="torrent_dir" id="torrent_dir" value="$sickbeard.TORRENT_DIR" size="45" />
-                            </label>
-                            <label class="nocheck clearfix">
-                                <span class="component-title">&nbsp;</span>
-                                <span class="component-desc">The directory where Sick Beard should store your <i>Torrent</i> files.</span>
-                            </label>
-                        </div>
-
                         <div id="blackhole_settings">
                             <div class="field-pair">
                                 <label class="nocheck clearfix">
@@ -196,84 +172,87 @@
                                 </label>
                             </div>
                         </div>
+
+                        <div id="nzbget_settings">
+                            <div class="field-pair">
+                                <label class="nocheck clearfix">
+                                    <span class="component-title">NZBget HOST:PORT</span>
+                                    <input type="text" name="nzbget_host" value="$sickbeard.NZBGET_HOST" size="45" />
+                                </label>
+                                <label class="nocheck clearfix">
+                                    <span class="component-title">&nbsp;</span>
+                                    <span class="component-desc">Hostname and portnumber of the NZBget RPC (not NZBgetweb!)</span>
+                                </label>
+                                <label class="nocheck clearfix">
+                                    <span class="component-title">&nbsp;</span>
+                                    <span class="component-desc">(eg. localhost:6789)</span>
+                                </label>
+                            </div>
+                            
+                            <div class="field-pair">
+                                <label class="nocheck clearfix">
+                                    <span class="component-title">NZBget Password</span>
+                                    <input type="password" name="nzbget_password" value="$sickbeard.NZBGET_PASSWORD" size="20" />
+                                </label>
+                                <label class="nocheck clearfix">
+                                    <span class="component-title">&nbsp;</span>
+                                    <span class="component-desc">Password found in nzbget.conf (by default tegbzn6789)</span>
+                                </label>
+                            </div>
+
+                            <div class="field-pair">
+                                <label class="nocheck clearfix">
+                                    <span class="component-title">NZBget Category</span>
+                                    <input type="text" name="nzbget_category" value="$sickbeard.NZBGET_CATEGORY" size="20" />
+                                </label>
+                                <label class="nocheck clearfix">
+                                    <span class="component-title">&nbsp;</span>
+                                    <span class="component-desc">Category for downloads to go into (eg. TV)</span>
+                                </label>
+                            </div>
+                        </div>
                         
                         <div class="clearfix"></div>
                         <input type="submit" value="Save Changes" /><br/>
                         
+                        </div><!-- /content_use_nzbs //-->
+                        
                     </fieldset>
                 </div><!-- /component-group2 //-->
 
                 <div id="core-component-group3" class="component-group clearfix">
 
                     <div class="component-group-desc">
-                        <h3>Post-Processing</h3>
-                        <p>Settings that dictate how Sick Beard should process completed downloads.</p>
+                        <h3>Torrent Search</h3>
+                        <p>Settings that dictate how Sick Beard handles Torrent search results.</p>
                     </div>
 
                     <fieldset class="component-group-list">
-                        <div class="field-pair">
-                            <label class="nocheck clearfix" for="tv_download_dir">
-                                <span class="component-title">TV Download Dir</span>
-                                <input type="text" name="tv_download_dir" id="tv_download_dir" value="$sickbeard.TV_DOWNLOAD_DIR" size="45" />
-                            </label>
-                            <label class="nocheck clearfix">
-                                <span class="component-title">&nbsp;</span>
-                                <span class="component-desc">The folder where your download client puts your TV downloads.</span>
-                            </label>
-                            <label class="nocheck clearfix">
-                                <span class="component-title">&nbsp;</span>
-                                <span class="component-desc"><b>NOTE:</b> Use only if not using SABnzbd+ post processing.</span>
-                            </label>
-                            <label class="nocheck clearfix">
-                                <span class="component-title">&nbsp;</span>
-                                <span class="component-desc">Or if SABnzbd+ and Sick Beard are on different PCs.</span>
-                            </label>
-                        </div>
-
-                        
-                        <div class="field-pair">
-                            <input type="checkbox" name="keep_processed_dir" id="keep_processed_dir" #if $sickbeard.KEEP_PROCESSED_DIR == True then "checked=\"checked\"" else ""# />
-                            <label class="clearfix" for="keep_processed_dir">
-                                <span class="component-title">Keep Original Files</span>
-                                <span class="component-desc">Keep original files after they've been processed?</span>
-                            </label>
-                        </div>
-
-                        <div class="field-pair">
-                            <input type="checkbox" name="move_associated_files" id="move_associated_files" #if $sickbeard.MOVE_ASSOCIATED_FILES == True then "checked=\"checked\"" else ""# />
-                            <label class="clearfix" for="move_associated_files">
-                                <span class="component-title">Move Associated Files</span>
-                                <span class="component-desc">Move srr/srt/sfv/etc files with the episode when processed?</span>
-                            </label>
-                            <label class="nocheck clearfix" for="move_associated_files">
-                                <span class="component-title">&nbsp;</span>
-                                <span class="component-desc"><b>NOTE:</b> <i>.nfo</i> will be renamed to <i>.nfo-orig</i> when moved.</span>
-                            </label>
-                        </div>
 
                         <div class="field-pair">
-                            <input type="checkbox" name="rename_episodes" id="rename_episodes" #if $sickbeard.RENAME_EPISODES == True then "checked=\"checked\"" else ""# />
-                            <label class="clearfix" for="rename_episodes">
-                                <span class="component-title">Rename Episodes</span>
-                                <span class="component-desc">Rename episode using the naming settings in <a href="$sbRoot/config/general">General</a>?</span>
+                            <input type="checkbox" name="use_torrents" class="enabler" id="use_torrents" #if $sickbeard.USE_TORRENTS == True then "checked=\"checked\"" else ""# />
+                            <label class="clearfix" for="use_torrents">
+                                <span class="component-title">Search Torrents</span>
+                                <span class="component-desc">Should Sick Beard search for torrent files?</span>
                             </label>
                         </div>
 
+                        <div id="content_use_torrents">
                         <div class="field-pair">
-                            <input type="checkbox" name="process_automatically" id="process_automatically" #if $sickbeard.PROCESS_AUTOMATICALLY == True then "checked=\"checked\"" else ""# />
-                            <label class="clearfix" for="process_automatically">
-                                <span class="component-title">Scan and Process</span>
-                                <span class="component-desc">Scan and post-process any files in your <i>TV Download Dir</i>?</span>
+                            <label class="nocheck clearfix">
+                                <span class="component-title">Torrent Black Hole</span>
+                                <input type="text" name="torrent_dir" id="torrent_dir" value="$sickbeard.TORRENT_DIR" size="45" />
                             </label>
-                            <label class="nocheck clearfix" for="process_automatically">
+                            <label class="nocheck clearfix">
                                 <span class="component-title">&nbsp;</span>
-                                <span class="component-desc"><b>NOTE:</b> Do not use if you use sabToSickbeard w/ SABnzbd+!</span>
+                                <span class="component-desc">The directory where Sick Beard should store your <i>Torrent</i> files.</span>
                             </label>
                         </div>
-
+                        
                         <div class="clearfix"></div>
                         <input type="submit" value="Save Changes" /><br/>
-
+                        </div><!-- /content_use_torrents //-->
+                        
                     </fieldset>
                 </div><!-- /component-group3 //-->
 
diff --git a/data/interfaces/default/displayShow.tmpl b/data/interfaces/default/displayShow.tmpl
index 845923888e2e0e51831edfe4f0571d57bc0ed945..d1e0bd3900c351543ee245817d2808e96988509a 100644
--- a/data/interfaces/default/displayShow.tmpl
+++ b/data/interfaces/default/displayShow.tmpl
@@ -11,14 +11,27 @@
 
 <script type="text/javascript" src="$sbRoot/js/jquery.bookmarkscroll.js"></script>
 
-<div class="h2footer align-right" style="margin-left:250px; line-height: 20px;">
+<div class="h2footer align-right">
+#if (len($seasonResults) > 14):
+    <select id="seasonJump">
+        <option value="jump">Jump to Season</option>
+    #for $seasonNum in $seasonResults:
+        <option value="#season-$seasonNum["season"]">#if int($seasonNum["season"]) == 0 then "Specials" else "Season " + str($seasonNum["season"])#</option>
+    #end for
+    </select>
+#else:
     <b>Season:</b>
     #for $seasonNum in $seasonResults:
-        #if int($seasonNum["season"]) == 0 then "<span class=\"separator\">|</span> " else ""#
-        <a href="#season-$seasonNum["season"]">
-        #if int($seasonNum["season"]) == 0 then "Specials</a>" else str($seasonNum["season"])+"</a> "#
-        #if int($seasonNum["season"]) >1 then "<span class=\"separator\">|</span> " else ""#
+        #if int($seasonNum["season"]) == 0:
+            <a href="#season-$seasonNum["season"]">Specials</a>
+        #else:
+            <a href="#season-$seasonNum["season"]">${str($seasonNum["season"])}</a>
+        #end if
+        #if $seasonNum != $seasonResults[-1]:
+            <span class="separator">|</span>
+        #end if
     #end for
+#end if
 </div><br/>
 
 <input type="hidden" id="sbRoot" value="$sbRoot" />
@@ -60,13 +73,8 @@ replace with: <b><%=", ".join([Quality.qualityStrings[x] for x in bestQualities]
     </td></tr>
     <tr><td class="showLegend">Language:</td><td>$show.lang</td></tr>
     <tr><td class="showLegend">Season Folders: </td><td><img src="$sbRoot/images/#if $show.seasonfolders == 1 then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
-#if $show.air_by_date or ($show.genre and "Talk Show" in $show.genre):
-#set $air_by_date = True
-#else
-#set $air_by_date = False
-#end if
     <tr><td class="showLegend">Active: </td><td><img src="$sbRoot/images/#if int($show.paused) == 0 then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
-    <tr><td class="showLegend">Air-by-Date: </td><td><img src="$sbRoot/images/#if int($air_by_date) == 1 then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
+    <tr><td class="showLegend">Air-by-Date: </td><td><img src="$sbRoot/images/#if int($show.air_by_date) == 1 then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
 </table>
 </div>
 
@@ -151,6 +159,6 @@ $epLoc
    </tr>
 
 #end for
-</table><br /><br />
+</table><br />
 
 #include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_bottom.tmpl")
diff --git a/data/interfaces/default/editShow.tmpl b/data/interfaces/default/editShow.tmpl
index afde1c78becbde904d60d0f7259f9b57b68fc52f..f9ccdc245937fa4a75dc1c76f710267df92a184d 100644
--- a/data/interfaces/default/editShow.tmpl
+++ b/data/interfaces/default/editShow.tmpl
@@ -54,19 +54,17 @@ Quality:
 #include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_qualityChooser.tmpl")
 <br />
 <br />
-Language: <select name="tvdbLang" id="tvdbLangSelect"></select>
+Language: <select name="tvdbLang" id="tvdbLangSelect"></select><br />
+Note: This will only affect the language of the retrieved metadata file contents and episode filenames.<br />
+This <b>DOES NOT</b> allow Sick Beard to download non-english TV episodes!<br />
 <br />
 <br />
 Use Season Folders: <input type="checkbox" name="seasonfolders" #if $show.seasonfolders == 1 then "checked=\"checked\"" else ""# /><br /><br />
 Paused: <input type="checkbox" name="paused" #if $show.paused == 1 then "checked=\"checked\"" else ""# /><br /><br />
 
 Air by date:
-#if ($show.genre and "Talk Show" not in $show.genre) or not $show.genre:
 <input type="checkbox" name="air_by_date" #if $show.air_by_date == 1 then "checked=\"checked\"" else ""# /><br />
 (check this if the show is released as Show.03.02.2010 rather than Show.S02E03)
-#else
-<input type="checkbox" disabled=\"disabled\" checked=\"checked\" />
-#end if
 <br /><br />
 <input type="submit" value="Submit" />
 </form>
diff --git a/data/interfaces/default/history.tmpl b/data/interfaces/default/history.tmpl
index afaf97bee1ab64e6c357c094429611dfd10f46f8..63b5ef19e96e8ba51e8234a97927950c337c0259 100644
--- a/data/interfaces/default/history.tmpl
+++ b/data/interfaces/default/history.tmpl
@@ -25,7 +25,6 @@
 //-->
 </script>
 
-
 <table id="historyTable" class="sickbeardTable tablesorter" cellspacing="1" border="0" cellpadding="0">
   <thead><tr><th class="nowrap">Time</th><th>Episode</th><th>Action</th><th>Provider</th><th>Quality</th></tr></thead>
   <tbody>
diff --git a/data/interfaces/default/home_addShows.tmpl b/data/interfaces/default/home_addShows.tmpl
index 5eb7736ac5060018fa588ce400a7bd7056b0b531..4bf428947d0f6c268f925815d4feb91901b8c8de 100644
--- a/data/interfaces/default/home_addShows.tmpl
+++ b/data/interfaces/default/home_addShows.tmpl
@@ -32,7 +32,7 @@
         <div class="button"><img src="$sbRoot/images/add-new32.png" alt="Add New Show"/></div>
         <div class="buttontext">
             <h2>Add New Show</h2>
-            <p>For shows that you haven't downloaded yet, this option finds a show on TVDB.com, creates a directory for its episodes, and adds it to Sick Beard.</p>
+            <p>For shows that you haven't downloaded yet, this option finds a show on theTVDB.com, creates a directory for its episodes, and adds it to Sick Beard.</p>
         </div>
     </button>
 
diff --git a/data/interfaces/default/inc_top.tmpl b/data/interfaces/default/inc_top.tmpl
index 57933ecd78b1ce07f2a49696650b81c6d30daa70..2ebccfb271aa64f25f8f27b70718b842c137c7dd 100644
--- a/data/interfaces/default/inc_top.tmpl
+++ b/data/interfaces/default/inc_top.tmpl
@@ -16,7 +16,7 @@
     <link rel="stylesheet" type="text/css" href="$sbRoot/css/config.css" />
     <link rel="stylesheet" type="text/css" href="$sbRoot/css/jquery.pnotify.default.css" />
     <link rel="stylesheet" type="text/css" href="$sbRoot/css/jquery.autocomplete.css" />
-    <link rel="stylesheet" type="text/css" href="$sbRoot/css/smooth-grinder/jquery-ui-1.8.10.custom.css" />
+    <link rel="stylesheet" type="text/css" href="$sbRoot/css/smooth-grinder/jquery-ui-1.8.11.custom.css" />
     <link rel="stylesheet" type="text/css" href="$sbRoot/css/superfish.css" />
     <link rel="stylesheet" type="text/css" href="$sbRoot/css/tablesorter.css"/>
     <link rel="stylesheet" type="text/css" media="only screen and (max-device-width: 480px)" href="$sbRoot/css/iphone.css" />
@@ -61,7 +61,7 @@ table.tablesorter thead tr .headerSortDown { background-image: url("$sbRoot/imag
 </style>
 
     <script type="text/javascript" src="$sbRoot/js/jquery-1.5.1.min.js"></script>
-    <script type="text/javascript" src="$sbRoot/js/jquery-ui-1.8.10.custom.min.js"></script>
+    <script type="text/javascript" src="$sbRoot/js/jquery-ui-1.8.11.custom.min.js"></script>
     <script type="text/javascript" src="$sbRoot/js/superfish-1.4.8.js"></script>
     <script type="text/javascript" src="$sbRoot/js/supersubs-0.2b.js"></script>
     <script type="text/javascript" src="$sbRoot/js/jquery.autocomplete.min.js"></script>
@@ -200,9 +200,10 @@ table.tablesorter thead tr .headerSortDown { background-image: url("$sbRoot/imag
             <li id="NAVconfig"><a href="$sbRoot/config">Config</a>
                 <ul>
                         <li><a href="$sbRoot/config/general/"><img src="$sbRoot/images/menu/config16.png" alt="" width="16" height="16" />General</a></li>
-                        <li><a href="$sbRoot/config/episodedownloads/"><img src="$sbRoot/images/menu/config16.png" alt="" width="16" height="16" />Episode Downloads</a></li>
-                        <li><a href="$sbRoot/config/notifications/"><img src="$sbRoot/images/menu/config16.png" alt="" width="16" height="16" />Notifications</a></li>
+                        <li><a href="$sbRoot/config/search/"><img src="$sbRoot/images/menu/config16.png" alt="" width="16" height="16" />Search Settings</a></li>
                         <li><a href="$sbRoot/config/providers/"><img src="$sbRoot/images/menu/config16.png" alt="" width="16" height="16" />Search Providers</a></li>
+                        <li><a href="$sbRoot/config/postProcessing/"><img src="$sbRoot/images/menu/config16.png" alt="" width="16" height="16" />Post Processing</a></li>
+                        <li><a href="$sbRoot/config/notifications/"><img src="$sbRoot/images/menu/config16.png" alt="" width="16" height="16" />Notifications</a></li>
                 </ul>
             </li>
             <li id="NAVerrorlogs"><a href="$sbRoot/errorlogs">$logPageTitle</a>
diff --git a/data/interfaces/default/manage_manageSearches.tmpl b/data/interfaces/default/manage_manageSearches.tmpl
index 9a3c157ebd1d87b31fa325ff99a8f11ddb5b4051..ece479634e566abbcd484cd6ddc2cbac14a9dfdd 100644
--- a/data/interfaces/default/manage_manageSearches.tmpl
+++ b/data/interfaces/default/manage_manageSearches.tmpl
@@ -11,6 +11,7 @@
 
 <script type="text/javascript" src="$sbRoot/js/plotTooltip.js"></script>
 
+
 <b>Backlog Search:</b><br />
 
 #if not $backlogRunning:
diff --git a/data/interfaces/default/restart.tmpl b/data/interfaces/default/restart.tmpl
new file mode 100644
index 0000000000000000000000000000000000000000..2a3114254d515afe38166a3e9a6ebc8c4ea57023
--- /dev/null
+++ b/data/interfaces/default/restart.tmpl
@@ -0,0 +1,17 @@
+#import sickbeard
+#import datetime
+#from sickbeard.common import *
+#from sickbeard import db
+
+#set global $title="Home"
+#set global $header="Restarting Sick Beard"
+
+#set global $sbPath = ".."
+
+#set global $topmenu="home"#
+#import os.path
+#include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_top.tmpl")
+
+#include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/restart_bare.tmpl")
+
+#include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_bottom.tmpl")
diff --git a/data/interfaces/default/restart_bare.tmpl b/data/interfaces/default/restart_bare.tmpl
new file mode 100644
index 0000000000000000000000000000000000000000..6add0cd72c20f1ae2e73697670a846559f88282a
--- /dev/null
+++ b/data/interfaces/default/restart_bare.tmpl
@@ -0,0 +1,33 @@
+<script type="text/javascript" src="$sbRoot/js/jquery-1.5.1.min.js"></script>
+<script type="text/javascript" charset="utf-8">
+<!--
+sbRoot = "$sbRoot";
+//-->
+</script>
+
+<script type="text/javascript" src="$sbRoot/js/restart.js"></script>
+
+<h2>Performing Restart</h2>
+<br />
+<div id="shut_down_message">
+Waiting for Sick Beard to shut down:
+<img src="$sbRoot/images/loading16.gif" height="16" width="16" id="shut_down_loading" />
+<img src="$sbRoot/images/yes16.png" height="16" width="16" id="shut_down_success" style="display: none;" />
+</div>
+
+<div id="restart_message" style="display: none;">
+Waiting for Sick Beard to start again:
+<img src="$sbRoot/images/loading16.gif" height="16" width="16" id="restart_loading" />
+<img src="$sbRoot/images/yes16.png" height="16" width="16" id="restart_success" style="display: none;" />
+<img src="$sbRoot/images/no16.png" height="16" width="16" id="restart_failure" style="display: none;" />
+</div>
+
+<div id="refresh_message" style="display: none;">
+Loading the home page:
+<img src="$sbRoot/images/loading16.gif" height="16" width="16" id="refresh_loading" />
+</div>
+
+<div id="restart_fail_message" style="display: none;">
+Error: The restart has timed out, perhaps something prevented Sick Beard from starting again?
+</div>
+
diff --git a/data/interfaces/default/viewlogs.tmpl b/data/interfaces/default/viewlogs.tmpl
index 6f596523a65e0662d4e6050b38e87561ba7798cc..eab5e1d2d5a12e33fcc1b9b53d2951b2f2a6e2a2 100644
--- a/data/interfaces/default/viewlogs.tmpl
+++ b/data/interfaces/default/viewlogs.tmpl
@@ -21,7 +21,7 @@
 //-->
 </script>
 
-<div class="h2footer align-right"><b>Minimum logging level to display:</b> <select name="minLevel" id="minLevel" style="margin-top: -5px;">
+<div class="h2footer align-right"><b>Minimum logging level to display:</b> <select name="minLevel" id="minLevel">
 #set $levels = $reverseNames.keys()
 $levels.sort(lambda x,y: cmp($reverseNames[$x], $reverseNames[$y]))
 #for $level in $levels:
diff --git a/data/js/config.js b/data/js/config.js
new file mode 100644
index 0000000000000000000000000000000000000000..37d3a24c1344320e075ae0ad44238afdaf363d32
--- /dev/null
+++ b/data/js/config.js
@@ -0,0 +1,13 @@
+$(document).ready(function(){
+    $(".enabler").each(function(){
+        if (!$(this).attr('checked'))
+            $('#content_'+$(this).attr('id')).hide();
+    });
+
+    $(".enabler").click(function() {
+        if ($(this).attr('checked'))
+            $('#content_'+$(this).attr('id')).show();
+        else
+            $('#content_'+$(this).attr('id')).hide();
+  });
+});
\ No newline at end of file
diff --git a/data/js/configNotifications.js b/data/js/configNotifications.js
index da95ee87a3674a97e391b2a42ac27d48448ca8e5..cacfdd02ee001c7d7c3e46bbe16be09cfa3ae8d0 100644
--- a/data/js/configNotifications.js
+++ b/data/js/configNotifications.js
@@ -2,72 +2,112 @@ $(document).ready(function(){
     var loading = '<img src="'+sbRoot+'/images/loading16.gif" height="16" width="16" />';
 
     $('#testGrowl').click(function(){
-        document.getElementById('testGrowl-result').innerHTML = loading;
+        $('#testGrowl-result').html(loading);
         var growl_host = $("#growl_host").val();
         var growl_password = $("#growl_password").val();
         var growl_result = $.get(sbRoot+"/home/testGrowl", {'host': growl_host, 'password': growl_password}, 
-        function (data){ document.getElementById('testGrowl-result').innerHTML = data;});
+        function (data){ $('#testGrowl-result').html(data); });
     });
 
     $('#testProwl').click(function(){
-        document.getElementById('testProwl-result').innerHTML = loading;
+        $('#testProwl-result').html(loading);
         var prowl_api = $("#prowl_api").val();
         var prowl_priority = $("#prowl_priority").val();
         var prowl_result = $.get(sbRoot+"/home/testProwl", {'prowl_api': prowl_api, 'prowl_priority': prowl_priority}, 
-        function (data){ document.getElementById('testProwl-result').innerHTML = data;});
+        function (data){ $('#testProwl-result').html(data); });
     });
 
     $('#testXBMC').click(function(){
-        document.getElementById('testXBMC-result').innerHTML = loading;
+        $('#testXBMC-result').html(loading);
         var xbmc_host = $("#xbmc_host").val();
         var xbmc_username = $("#xbmc_username").val();
         var xbmc_password = $("#xbmc_password").val();
         
         $.get(sbRoot+"/home/testXBMC", {'host': xbmc_host, 'username': xbmc_username, 'password': xbmc_password}, 
-        function (data){ document.getElementById('testXBMC-result').innerHTML = data;});
+        function (data){ $('#testXBMC-result').html(data); });
+    });
+
+    $('#testPLEX').click(function(){
+        $('#testPLEX-result').html(loading);
+        var plex_host = $("#plex_host").val();
+        var plex_username = $("#plex_username").val();
+        var plex_password = $("#plex_password").val();
+        
+        $.get(sbRoot+"/home/testPLEX", {'host': plex_host, 'username': plex_username, 'password': plex_password}, 
+        function (data){ $('#testPLEX-result').html(data);});
     });
 
     $('#testNotifo').click(function(){
-        document.getElementById('testNotifo-result').innerHTML = loading;
+        $('#testNotifo-result').html(loading);
         var notifo_username = $("#notifo_username").val();
         var notifo_apisecret = $("#notifo_apisecret").val();
         $.get(sbRoot+"/home/testNotifo", {'username': notifo_username, 'apisecret': notifo_apisecret},
-        function (data){ document.getElementById('testNotifo-result').innerHTML = data; });
+        function (data){ $('#testNotifo-result').html(data); });
     });
 
     $('#testLibnotify').click(function(){
         $('#testLibnotify-result').html(loading);
-        $.get("$sbRoot/home/testLibnotify",
-        function(message){ document.getElementById('testLibnotify-result').innerHTML = message; });
+        $.get(sbRoot+"/home/testLibnotify",
+        function(message){ $('#testLibnotify-result').html(message); });
     });
   
     $('#twitterStep1').click(function(){
-        document.getElementById('testTwitter-result').innerHTML = loading;
+        $('#testTwitter-result').html(loading);
         var twitter1_result = $.get(sbRoot+"/home/twitterStep1", function (data){window.open(data)})
-        .complete(function() { document.getElementById('testTwitter-result').innerHTML = '<b>Step1:</b> Confirm Authorization'; });
+        .complete(function() { $('#testTwitter-result').html('<b>Step1:</b> Confirm Authorization'); });
     });
 
     $('#twitterStep2').click(function(){
-        document.getElementById('testTwitter-result').innerHTML = loading;
+        $('#testTwitter-result').html(loading);
         var twitter_key = $("#twitter_key").val();
         $.get(sbRoot+"/home/twitterStep2", {'key': twitter_key}, 
-        function (data){ document.getElementById('testTwitter-result').innerHTML = data; });
+        function (data){ $('#testTwitter-result').html(data); });
     });
 
     $('#testTwitter').click(function(){
         $.get(sbRoot+"/home/testTwitter", 
-        function (data){ document.getElementById('testTwitter-result').innerHTML = data;});
+        function (data){ $('#testTwitter-result').html(data); });
     });
 
-    $(".enabler").each(function(){
-        if (!$(this).attr('checked'))
-            $('#content_'+$(this).attr('id')).hide();
+    $('#settingsNMJ').click(function(){
+        if (!$('#nmj_host').val()) {
+            alert('Please fill in the Popcorn IP address');
+            $('#nmj_host').focus();
+            return;
+        }
+        $('#testNMJ-result').html(loading);
+        var nmj_host = $('#nmj_host').val();
+        
+        $.get(sbRoot+"/home/settingsNMJ", {'host': nmj_host}, 
+        function (data){
+            if (data == null) {
+                $('#nmj_database').removeAttr('readonly');
+                $('#nmj_mount').removeAttr('readonly');
+            }
+            var JSONData = $.parseJSON(data);
+            $('#testNMJ-result').html(JSONData.message);
+            $('#nmj_database').val(JSONData.database);
+            $('#nmj_mount').val(JSONData.mount);
+            
+            if (JSONData.database)
+                $('#nmj_database').attr('readonly', true);
+            else
+                $('#nmj_database').removeAttr('readonly');
+            
+            if (JSONData.mount)
+                $('#nmj_mount').attr('readonly', true);
+            else
+                $('#nmj_mount').removeAttr('readonly');
+        });
     });
 
-    $(".enabler").click(function() {
-        if ($(this).attr('checked'))
-            $('#content_'+$(this).attr('id')).show();
-        else
-            $('#content_'+$(this).attr('id')).hide();
-  });
-});
\ No newline at end of file
+    $('#testNMJ').click(function(){
+        $('#testNMJ-result').html(loading);
+        var nmj_host = $("#nmj_host").val();
+        var nmj_database = $("#nmj_database").val();
+        var nmj_mount = $("#nmj_mount").val();
+        
+        $.get(sbRoot+"/home/testNMJ", {'host': nmj_host, 'database': nmj_database, 'mount': nmj_mount}, 
+        function (data){ $('#testNMJ-result').html(data); });
+    });
+});
diff --git a/data/js/configGeneral.js b/data/js/configPostProcessing.js
similarity index 94%
rename from data/js/configGeneral.js
rename to data/js/configPostProcessing.js
index 1787d6dafd44867c98de52c2a0fe243f9f870376..82f3376906358aa0c2d90763f3108ccaca82b824 100644
--- a/data/js/configGeneral.js
+++ b/data/js/configPostProcessing.js
@@ -12,13 +12,13 @@ $(document).ready(function(){
                   'whichTest': 'single'
                   }
         
-        $.get(nameTestURL, params,
+        $.get(sbRoot+"/config/postProcessing/testNaming", params,
               function(data){
                   $('#normalExampleText').text(data);
         });
 
         params['whichTest'] = 'multi'
-        $.get(nameTestURL, params,
+        $.get(sbRoot+"/config/postProcessing/testNaming", params,
               function(data){
                   $('#multiExampleText').text(data);
         });
diff --git a/data/js/configProviders.js b/data/js/configProviders.js
index d54bac82148eb4d41f148fe49a846418f294cc8e..137b8ce0b402b424856196f2071b349f977a9d8b 100644
--- a/data/js/configProviders.js
+++ b/data/js/configProviders.js
@@ -13,7 +13,7 @@ $(document).ready(function(){
         });
     } 
 
-    $.fn.addProvider = function (id, name, url, key, isDefault) {
+    $.fn.addProvider = function (id, name, url, key, isDefault, showProvider) {
 
         if (url.match('/$') == null)
             url = url + '/'
@@ -24,8 +24,8 @@ $(document).ready(function(){
         $('#editANewznabProvider').addOption(id, name);
         $(this).populateNewznabSection();
 
-        if ($('#provider_order_list > #'+id).length == 0) {
-            var toAdd = '<li class="ui-state-default" id="'+id+'"> <input type="checkbox" id="enable_'+id+'" class="enabler" CHECKED> <a href="'+url+'" class="imgLink" target="_new"><img src="'+sbRoot+'/images/providers/newznab.gif" alt="'+name+'" width="16" height="16"></a> '+name+'</li>'
+        if ($('#provider_order_list > #'+id).length == 0 && showProvider != false) {
+            var toAdd = '<li class="ui-state-default" id="'+id+'"> <input type="checkbox" id="enable_'+id+'" class="provider_enabler" CHECKED> <a href="'+url+'" class="imgLink" target="_new"><img src="'+sbRoot+'/images/providers/newznab.gif" alt="'+name+'" width="16" height="16"></a> '+name+'</li>'
 
             $('#provider_order_list').append(toAdd);
             $('#provider_order_list').sortable("refresh");
@@ -140,7 +140,7 @@ $(document).ready(function(){
         $(this).populateNewznabSection();
     });
     
-    $('.enabler').live('click', function(){
+    $('.provider_enabler').live('click', function(){
         $(this).refreshProviderList();
     }); 
     
diff --git a/data/js/configSearch.js b/data/js/configSearch.js
new file mode 100644
index 0000000000000000000000000000000000000000..01d8f89bc8beb40a835b97a29c4f1278998deb26
--- /dev/null
+++ b/data/js/configSearch.js
@@ -0,0 +1,27 @@
+$(document).ready(function(){
+
+    $.fn.nzb_method_handler = function() {
+        
+        var selectedProvider = $('#nzb_method :selected').val();
+
+        if (selectedProvider == "blackhole") {
+            $('#blackhole_settings').show();
+            $('#sabnzbd_settings').hide();
+            $('#nzbget_settings').hide();
+        } else if (selectedProvider == "nzbget") {
+            $('#blackhole_settings').hide();
+            $('#sabnzbd_settings').hide();
+            $('#nzbget_settings').show();
+        } else {
+            $('#blackhole_settings').hide();
+            $('#sabnzbd_settings').show();
+            $('#nzbget_settings').hide();
+        }
+
+    }
+
+    $('#nzb_method').change($(this).nzb_method_handler);
+
+    $(this).nzb_method_handler();
+
+});
diff --git a/data/js/displayShow.js b/data/js/displayShow.js
index bfcecdfadaa19314224dcde5d827b5c6b58dbb55..d5e0ab23670afd7d3b7dce40df9cd52b400dbcbf 100644
--- a/data/js/displayShow.js
+++ b/data/js/displayShow.js
@@ -1,12 +1,13 @@
 $(document).ready(function(){
 
-   $("table.sickbeardTable tr").click( function(event) {
-               if (event.target.type !== "checkbox") {
-                  $(this).find("input:checkbox.epCheck").each(function(){
-                     $(this).attr("checked", !$(this).attr("checked"));
-                  });
-               }
-   });
+    $('#seasonJump').change(function() {
+    var id = $(this).val();
+    if (id && id != 'jump') {
+        $('html,body').animate({scrollTop: $(id).offset().top},'slow');
+        location.hash = id;
+    }
+    $(this).val('jump');
+    });
 
     $("#prevShow").click(function(){
         $('#pickShow option:selected').prev('option').attr('selected', 'selected');
diff --git a/data/js/jquery-ui-1.8.10.custom.min.js b/data/js/jquery-ui-1.8.11.custom.min.js
similarity index 76%
rename from data/js/jquery-ui-1.8.10.custom.min.js
rename to data/js/jquery-ui-1.8.11.custom.min.js
index dec36337246f9bf6f2eb7ea1ccad21c81401a755..e32859f38bd221b0a0e0d161b1f8ea06220ea409 100644
--- a/data/js/jquery-ui-1.8.10.custom.min.js
+++ b/data/js/jquery-ui-1.8.11.custom.min.js
@@ -1,5 +1,5 @@
 /*!
- * jQuery UI 1.8.10
+ * jQuery UI 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -7,7 +7,7 @@
  *
  * http://docs.jquery.com/UI
  */
-(function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.10",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,
+(function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.11",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,
 NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,
 "position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");
 if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,l,m){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(l)g-=parseFloat(c.curCSS(f,
@@ -16,7 +16,7 @@ d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c
 c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&
 b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&c.ui.isOverAxis(b,e,i)}})}})(jQuery);
 ;/*!
- * jQuery UI Widget 1.8.10
+ * jQuery UI Widget 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -31,7 +31,7 @@ this._getCreateOptions(),a);var d=this;this.element.bind("remove."+this.widgetNa
 widget:function(){return this.element},option:function(a,c){var d=a;if(arguments.length===0)return b.extend({},this.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}this._setOptions(d);return this},_setOptions:function(a){var c=this;b.each(a,function(d,e){c._setOption(d,e)});return this},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},
 enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
 ;/*!
- * jQuery UI Mouse 1.8.10
+ * jQuery UI Mouse 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -42,13 +42,13 @@ enable:function(){return this._setOption("disabled",false)},disable:function(){r
  * Depends:
  *	jquery.ui.widget.js
  */
-(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(true===c.data(b.target,a.widgetName+".preventClickEvent")){c.removeData(b.target,a.widgetName+".preventClickEvent");b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=
-a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=
-this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);
-return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;a.target==this._mouseDownEvent.target&&c.data(a.target,this.widgetName+".preventClickEvent",
-true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
+(function(b){b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(c){return a._mouseDown(c)}).bind("click."+this.widgetName,function(c){if(true===b.data(c.target,a.widgetName+".preventClickEvent")){b.removeData(c.target,a.widgetName+".preventClickEvent");c.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=
+a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&this._mouseUp(a);this._mouseDownEvent=a;var c=this,e=a.which==1,f=typeof this.options.cancel=="string"?b(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){c.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=
+this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();return true}}true===b.data(a.target,this.widgetName+".preventClickEvent")&&b.removeData(a.target,this.widgetName+".preventClickEvent");this._mouseMoveDelegate=function(d){return c._mouseMove(d)};this._mouseUpDelegate=function(d){return c._mouseUp(d)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);a.preventDefault();return a.originalEvent.mouseHandled=
+true}},_mouseMove:function(a){if(b.browser.msie&&!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);
+if(this._mouseStarted){this._mouseStarted=false;a.target==this._mouseDownEvent.target&&b.data(a.target,this.widgetName+".preventClickEvent",true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
 ;/*
- * jQuery UI Position 1.8.10
+ * jQuery UI Position 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -64,7 +64,7 @@ d>0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a)
 a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b),
 g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery);
 ;/*
- * jQuery UI Draggable 1.8.10
+ * jQuery UI Draggable 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -87,34 +87,34 @@ this.options.revert.call(this.element,b)){var c=this;d(this.helper).animate(this
 a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
 0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
 this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-
-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment==
-"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[(a.containment=="document"?0:d(window).scrollLeft())-this.offset.relative.left-this.offset.parent.left,(a.containment=="document"?0:d(window).scrollTop())-this.offset.relative.top-this.offset.parent.top,(a.containment=="document"?0:d(window).scrollLeft())+d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a.containment=="document"?
-0:d(window).scrollTop())+(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),
-10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==
-Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():
-f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;
-if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])e=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/
-b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;e=this.originalPageX+Math.round((e-this.originalPageX)/b.grid[0])*b.grid[0];e=this.containment?!(e-this.offset.click.left<this.containment[0]||e-this.offset.click.left>this.containment[2])?e:!(e-this.offset.click.left<this.containment[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:g-this.offset.click.top-
-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=
-this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.10"});
-d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");if(g&&!g.options.disabled){c.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=
-0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=
-c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=d(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,
-true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=
-0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=
-a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","iframeFix",{start:function(){var a=d(this).data("draggable").options;d(a.iframeFix===true?"iframe":a.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},
-stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=
-document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-
-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-b.overflowOffset.left<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-
-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable",
-"snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,g=b.offset.left,n=g+c.helperProportions.width,m=b.offset.top,o=m+c.helperProportions.height,h=
-c.snapElements.length-1;h>=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e<g&&g<k+e&&j-e<m&&m<l+e||i-e<g&&g<k+e&&j-e<o&&o<l+e||i-e<n&&n<k+e&&j-e<m&&m<l+e||i-e<n&&n<k+e&&j-e<o&&o<l+e){if(f.snapMode!="inner"){var p=Math.abs(j-o)<=e,q=Math.abs(l-m)<=e,r=Math.abs(i-n)<=e,s=Math.abs(k-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",
-{top:l,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k}).left-c.margins.left}var t=p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.abs(i-g)<=e;s=Math.abs(k-n)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l-c.helperProportions.height,
-left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[h].snapping&&(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=p||q||r||s||t}else{c.snapElements[h].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,
-a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,
-b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
+(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),
+height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[(a.containment=="document"?0:d(window).scrollLeft())-this.offset.relative.left-this.offset.parent.left,(a.containment=="document"?0:d(window).scrollTop())-this.offset.relative.top-this.offset.parent.top,(a.containment=="document"?0:d(window).scrollLeft())+d(a.containment=="document"?
+document:window).width()-this.helperProportions.width-this.margins.left,(a.containment=="document"?0:d(window).scrollTop())+(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),
+10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0),a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0),a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),
+10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&
+d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
+this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])e=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=
+this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;e=this.originalPageX+Math.round((e-this.originalPageX)/b.grid[0])*b.grid[0];e=this.containment?!(e-this.offset.click.left<this.containment[0]||e-this.offset.click.left>this.containment[2])?
+e:!(e-this.offset.click.left<this.containment[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():
+f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,
+offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.11"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");if(g&&!g.options.disabled){c.sortables.push({instance:g,shouldRevert:g.options.revert});g.refreshPositions();g._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},
+b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=
+d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=d(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};
+a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&
+this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",
+{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","iframeFix",{start:function(){var a=d(this).data("draggable").options;d(a.iframeFix===true?"iframe":a.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+
+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",
+a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+
+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-b.overflowOffset.left<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<
+c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+
+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),
+f=c.options,e=f.snapTolerance,g=b.offset.left,n=g+c.helperProportions.width,m=b.offset.top,o=m+c.helperProportions.height,h=c.snapElements.length-1;h>=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e<g&&g<k+e&&j-e<m&&m<l+e||i-e<g&&g<k+e&&j-e<o&&o<l+e||i-e<n&&n<k+e&&j-e<m&&m<l+e||i-e<n&&n<k+e&&j-e<o&&o<l+e){if(f.snapMode!="inner"){var p=Math.abs(j-o)<=e,q=Math.abs(l-m)<=e,r=Math.abs(i-n)<=e,s=Math.abs(k-g)<=e;if(p)b.position.top=
+c._convertPositionTo("relative",{top:j-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k}).left-c.margins.left}var t=p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.abs(i-g)<=e;s=Math.abs(k-n)<=e;if(p)b.position.top=
+c._convertPositionTo("relative",{top:j,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[h].snapping&&(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),
+{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=p||q||r||s||t}else{c.snapElements[h].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=
+parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
 ;/*
- * jQuery UI Droppable 1.8.10
+ * jQuery UI Droppable 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -133,14 +133,14 @@ a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var
 this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);
 this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g=
 d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",
-a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.10"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
+a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.11"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
 switch(c){case "fit":return i<=e&&g<=k&&j<=f&&h<=l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>=
 i&&e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!=
-"none";if(c[f].visible){c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight};e=="mousedown"&&c[f]._activate.call(c[f],b)}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
+"none";if(c[f].visible){e=="mousedown"&&c[f]._activate.call(c[f],b);c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight}}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
 a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c=!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=
 d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})}}})(jQuery);
 ;/*
- * jQuery UI Resizable 1.8.10
+ * jQuery UI Resizable 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -173,7 +173,7 @@ this.size.height,k=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&k)b.left=i-a.minW
 this.options;this.elementOffset=this.element.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,
 a){return{width:this.originalSize.width+a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,
 c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,
-originalPosition:this.originalPosition}}});e.extend(e.ui.resizable,{version:"1.8.10"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(),10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=
+originalPosition:this.originalPosition}}});e.extend(e.ui.resizable,{version:"1.8.11"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(),10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=
 b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize,function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top-f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var k=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:k.parents(a.originalElement[0]).length?["width","height"]:["width",
 "height","top","left"];e.each(r,function(n,o){if((n=(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(k.css("position"))){c._revertToRelativePosition=true;k.css({position:"absolute",top:"auto",left:"auto"})}k.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType?e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};
 if(b._revertToRelativePosition){b._revertToRelativePosition=false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a=e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-
@@ -187,7 +187,7 @@ a.size.width/a.aspectRatio}if(d+a.size.height>=a.parentData.height){a.size.heigh
 b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b=e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/
 (a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},l=function(b){return!isNaN(parseInt(b,10))}})(jQuery);
 ;/*
- * jQuery UI Selectable 1.8.10
+ * jQuery UI Selectable 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -207,9 +207,9 @@ c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){va
 this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.right<b||a.top>i||a.bottom<g);else if(d.tolerance=="fit")k=a.left>b&&a.right<h&&a.top>g&&a.bottom<i;if(k){if(a.selected){a.$element.removeClass("ui-selected");a.selected=false}if(a.unselecting){a.$element.removeClass("ui-unselecting");
 a.unselecting=false}if(!a.selecting){a.$element.addClass("ui-selecting");a.selecting=true;f._trigger("selecting",c,{selecting:a.element})}}else{if(a.selecting)if(c.metaKey&&a.startselected){a.$element.removeClass("ui-selecting");a.selecting=false;a.$element.addClass("ui-selected");a.selected=true}else{a.$element.removeClass("ui-selecting");a.selecting=false;if(a.startselected){a.$element.addClass("ui-unselecting");a.unselecting=true}f._trigger("unselecting",c,{unselecting:a.element})}if(a.selected)if(!c.metaKey&&
 !a.startselected){a.$element.removeClass("ui-selected");a.selected=false;a.$element.addClass("ui-unselecting");a.unselecting=true;f._trigger("unselecting",c,{unselecting:a.element})}}}});return false}},_mouseStop:function(c){var f=this;this.dragged=false;e(".ui-unselecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-unselecting");d.unselecting=false;d.startselected=false;f._trigger("unselected",c,{unselected:d.element})});e(".ui-selecting",this.element[0]).each(function(){var d=
-e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected");d.selecting=false;d.selected=true;d.startselected=true;f._trigger("selected",c,{selected:d.element})});this._trigger("stop",c);this.helper.remove();return false}});e.extend(e.ui.selectable,{version:"1.8.10"})})(jQuery);
+e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected");d.selecting=false;d.selected=true;d.startselected=true;f._trigger("selected",c,{selected:d.element})});this._trigger("stop",c);this.helper.remove();return false}});e.extend(e.ui.selectable,{version:"1.8.11"})})(jQuery);
 ;/*
- * jQuery UI Sortable 1.8.10
+ * jQuery UI Sortable 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -223,29 +223,29 @@ e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("
  *	jquery.ui.widget.js
  */
 (function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
-this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,
-arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
-c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
-{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
-if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
-a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
-if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
-this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
-b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
-"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
-c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
-document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-
-1;b>=0;b--){this.containers[b]._trigger("deactivate",null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});
-this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):d(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&
-a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?
-"width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?
-c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;
-return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=
-d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});
-return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=
-d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=
-this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=
-e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];
+this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=
+b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;
+d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-
+this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};
+this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=
+document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);
+return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<
+b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-
+b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,
+a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],
+e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();
+c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):
+this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,
+dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):d(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")},
+toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||
+this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();
+var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},
+_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();
+if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),
+this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),
+this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&
+this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=
+e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];
 if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);
 c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===
 1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=
@@ -267,9 +267,9 @@ this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",f,this._uiHash(
 this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",
 g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||
 this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,
-originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.10"})})(jQuery);
+originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.11"})})(jQuery);
 ;/*
- * jQuery UI Accordion 1.8.10
+ * jQuery UI Accordion 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -284,8 +284,8 @@ originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,send
 (function(c){c.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix");
 a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
 if(b.navigation){var d=a.element.find("a").filter(b.navigationFilter).eq(0);if(d.length){var h=d.closest(".ui-accordion-header");a.active=h.length?h:d.closest(".ui-accordion-content").prev()}}a.active=a._findActive(a.active||b.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");a.active.next().addClass("ui-accordion-content-active");a._createIcons();a.resize();a.element.attr("role","tablist");a.headers.attr("role","tab").bind("keydown.accordion",
-function(f){return a._keydown(f)}).next().attr("role","tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(f){a._clickHandler.call(a,f,this);f.preventDefault()})},_createIcons:function(){var a=this.options;if(a.icons){c("<span></span>").addClass("ui-icon "+
-a.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");
+function(f){return a._keydown(f)}).next().attr("role","tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(f){a._clickHandler.call(a,f,this);f.preventDefault()})},_createIcons:function(){var a=
+this.options;if(a.icons){c("<span></span>").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex");
 this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(a.autoHeight||a.fillHeight)b.css("height","");return c.Widget.prototype.destroy.call(this)},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons();
 b&&this._createIcons()}if(a=="disabled")this.headers.add(this.headers.next())[b?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(a){if(!(this.options.disabled||a.altKey||a.ctrlKey)){var b=c.ui.keyCode,d=this.headers.length,h=this.headers.index(a.target),f=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:f=this.headers[(h+1)%d];break;case b.LEFT:case b.UP:f=this.headers[(h-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},a.target);
 a.preventDefault()}if(f){c(a.target).attr("tabIndex",-1);c(f).attr("tabIndex",0);f.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,b-c(this).innerHeight()+
@@ -294,12 +294,12 @@ if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]===this.active[0];d.ac
 if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);a.next().addClass("ui-accordion-content-active")}}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var g=this.active.next(),
 e={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:g},j=this.active=c([]);this._toggle(j,g,e)}},_toggle:function(a,b,d,h,f){var g=this,e=g.options;g.toShow=a;g.toHide=b;g.data=d;var j=function(){if(g)return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data);g.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&h?{toShow:c([]),toHide:b,complete:j,down:f,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:j,down:f,autoHeight:e.autoHeight||
 e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;h=c.ui.accordion.animations;var i=e.duration,k=e.animated;if(k&&!h[k]&&!c.easing[k])k="slide";h[k]||(h[k]=function(l){this.slide(l,{easing:k,duration:i||700})});h[k](d)}else{if(e.collapsible&&h)a.toggle();else{b.hide();a.show()}j(true)}b.prev().attr({"aria-expanded":"false",
-tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");if(this.toHide.length)this.toHide.parent()[0].className=this.toHide.parent()[0].className;this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.10",animations:{slide:function(a,b){a=
-c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),h=0,f={},g={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){g[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/);f[i]={value:j[1],
-unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(g,{step:function(j,i){if(i.prop=="height")h=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=h*f[i.prop].value+f[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide",paddingTop:"hide",
-paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery);
+"aria-selected":"false",tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");if(this.toHide.length)this.toHide.parent()[0].className=this.toHide.parent()[0].className;this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.11",
+animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),h=0,f={},g={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){g[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/);
+f[i]={value:j[1],unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(g,{step:function(j,i){if(i.prop=="height")h=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=h*f[i.prop].value+f[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide",
+paddingTop:"hide",paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery);
 ;/*
- * jQuery UI Button 1.8.10
+ * jQuery UI Button 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -316,16 +316,15 @@ i);if(typeof this.options.disabled!=="boolean")this.options.disabled=this.elemen
 function(){if(!c.disabled){a(this).addClass("ui-state-hover");this===g&&a(this).addClass("ui-state-active")}}).bind("mouseleave.button",function(){c.disabled||a(this).removeClass(f)}).bind("focus.button",function(){a(this).addClass("ui-state-focus")}).bind("blur.button",function(){a(this).removeClass("ui-state-focus")});d&&this.element.bind("change.button",function(){b.refresh()});if(this.type==="checkbox")this.buttonElement.bind("click.button",function(){if(c.disabled)return false;a(this).toggleClass("ui-state-active");
 b.buttonElement.attr("aria-pressed",b.element[0].checked)});else if(this.type==="radio")this.buttonElement.bind("click.button",function(){if(c.disabled)return false;a(this).addClass("ui-state-active");b.buttonElement.attr("aria-pressed",true);var e=b.element[0];h(e).not(e).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed",false)});else{this.buttonElement.bind("mousedown.button",function(){if(c.disabled)return false;a(this).addClass("ui-state-active");
 g=this;a(document).one("mouseup",function(){g=null})}).bind("mouseup.button",function(){if(c.disabled)return false;a(this).removeClass("ui-state-active")}).bind("keydown.button",function(e){if(c.disabled)return false;if(e.keyCode==a.ui.keyCode.SPACE||e.keyCode==a.ui.keyCode.ENTER)a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")});this.buttonElement.is("a")&&this.buttonElement.keyup(function(e){e.keyCode===a.ui.keyCode.SPACE&&a(this).click()})}this._setOption("disabled",
-c.disabled)},_determineButtonType:function(){this.type=this.element.is(":checkbox")?"checkbox":this.element.is(":radio")?"radio":this.element.is("input")?"input":"button";if(this.type==="checkbox"||this.type==="radio"){this.buttonElement=this.element.parents().last().find("label[for="+this.element.attr("id")+"]");this.element.addClass("ui-helper-hidden-accessible");var b=this.element.is(":checked");b&&this.buttonElement.addClass("ui-state-active");this.buttonElement.attr("aria-pressed",b)}else this.buttonElement=
-this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible");this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active  ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html());this.hasTitle||
-this.buttonElement.removeAttr("title");a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);if(b==="disabled")c?this.element.attr("disabled",true):this.element.removeAttr("disabled");this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b);if(this.type==="radio")h(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed",
+c.disabled)},_determineButtonType:function(){this.type=this.element.is(":checkbox")?"checkbox":this.element.is(":radio")?"radio":this.element.is("input")?"input":"button";if(this.type==="checkbox"||this.type==="radio"){var b=this.element.parents().filter(":last"),c="label[for="+this.element.attr("id")+"]";this.buttonElement=b.find(c);if(!this.buttonElement.length){b=b.length?b.siblings():this.element.siblings();this.buttonElement=b.filter(c);if(!this.buttonElement.length)this.buttonElement=b.find(c)}this.element.addClass("ui-helper-hidden-accessible");
+(b=this.element.is(":checked"))&&this.buttonElement.addClass("ui-state-active");this.buttonElement.attr("aria-pressed",b)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible");this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active  ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html());
+this.hasTitle||this.buttonElement.removeAttr("title");a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);if(b==="disabled")c?this.element.attr("disabled",true):this.element.removeAttr("disabled");this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b);if(this.type==="radio")h(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed",
 true):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed",false)});else if(this.type==="checkbox")this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed",true):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed",false)},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var b=this.buttonElement.removeClass("ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only"),
-c=a("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,f=d.primary&&d.secondary,e=[];if(d.primary||d.secondary){e.push("ui-button-text-icon"+(f?"s":d.primary?"-primary":"-secondary"));d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>");d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>");if(!this.options.text){e.push(f?"ui-button-icons-only":"ui-button-icon-only");
-b.removeClass("ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary");this.hasTitle||b.attr("title",c)}}else e.push("ui-button-text-only");b.addClass(e.join(" "))}}});a.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,
-arguments)},refresh:function(){this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()},destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");
-a.Widget.prototype.destroy.call(this)}})})(jQuery);
+c=a("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,f=d.primary&&d.secondary,e=[];if(d.primary||d.secondary){if(this.options.text)e.push("ui-button-text-icon"+(f?"s":d.primary?"-primary":"-secondary"));d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>");d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>");if(!this.options.text){e.push(f?"ui-button-icons-only":
+"ui-button-icon-only");this.hasTitle||b.attr("title",c)}}else e.push("ui-button-text-only");b.addClass(e.join(" "))}}});a.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()},
+destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery);
 ;/*
- * jQuery UI Dialog 1.8.10
+ * jQuery UI Dialog 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -359,13 +358,13 @@ h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c
 l)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"):e.removeClass("ui-dialog-disabled");
 break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||"&#160;"));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a=this.options,b,d,e=
 this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();e||this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height-b,0));this.uiDialog.is(":data(resizable)")&&
-this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.10",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===
+this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.11",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===
 0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()<c.ui.dialog.overlay.maxZ)return false})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),
 height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){var b=c.inArray(a,this.instances);b!=-1&&this.oldInstances.push(this.instances.splice(b,1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var d=0;c.each(this.instances,function(){d=Math.max(d,this.css("z-index"))});this.maxZ=d},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);
 b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a<b?c(window).height()+"px":a+"px"}else return c(document).height()+"px"},width:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);b=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return a<b?c(window).width()+"px":a+"px"}else return c(document).width()+"px"},resize:function(){var a=c([]);c.each(c.ui.dialog.overlay.instances,
 function(){a=a.add(this)});a.css({width:0,height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);
 ;/*
- * jQuery UI Slider 1.8.10
+ * jQuery UI Slider 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -396,9 +395,9 @@ this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui
 return a=this._trimAlignValue(a)}else{a=this.options.values.slice();for(c=0;c<a.length;c+=1)a[c]=this._trimAlignValue(a[c]);return a}},_trimAlignValue:function(b){if(b<=this._valueMin())return this._valueMin();if(b>=this._valueMax())return this._valueMax();var a=this.options.step>0?this.options.step:1,c=(b-this._valueMin())%a;alignValue=b-c;if(Math.abs(c)*2>=a)alignValue+=c>0?a:-a;return parseFloat(alignValue.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},
 _refreshValue:function(){var b=this.options.range,a=this.options,c=this,e=!this._animateOff?a.animate:false,f,h={},g,i,j,l;if(this.options.values&&this.options.values.length)this.handles.each(function(k){f=(c.values(k)-c._valueMin())/(c._valueMax()-c._valueMin())*100;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](h,a.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(k===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},a.animate);
 if(k===1)c.range[e?"animate":"css"]({width:f-g+"%"},{queue:false,duration:a.animate})}else{if(k===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},a.animate);if(k===1)c.range[e?"animate":"css"]({height:f-g+"%"},{queue:false,duration:a.animate})}g=f});else{i=this.value();j=this._valueMin();l=this._valueMax();f=l!==j?(i-j)/(l-j)*100:0;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](h,a.animate);if(b==="min"&&this.orientation==="horizontal")this.range.stop(1,
-1)[e?"animate":"css"]({width:f+"%"},a.animate);if(b==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:a.animate});if(b==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},a.animate);if(b==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:a.animate})}}});d.extend(d.ui.slider,{version:"1.8.10"})})(jQuery);
+1)[e?"animate":"css"]({width:f+"%"},a.animate);if(b==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:a.animate});if(b==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},a.animate);if(b==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:a.animate})}}});d.extend(d.ui.slider,{version:"1.8.11"})})(jQuery);
 ;/*
- * jQuery UI Tabs 1.8.10
+ * jQuery UI Tabs 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -430,10 +429,10 @@ if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(b+(b+1<this
 this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(b){b=this._getIndex(b);var e=this.options;if(b!=e.selected){this.lis.eq(b).addClass("ui-state-disabled");e.disabled.push(b);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[b],this.panels[b]))}return this},select:function(b){b=this._getIndex(b);if(b==-1)if(this.options.collapsible&&this.options.selected!=-1)b=this.options.selected;else return this;this.anchors.eq(b).trigger(this.options.event+".tabs");return this},
 load:function(b){b=this._getIndex(b);var e=this,a=this.options,c=this.anchors.eq(b)[0],h=d.data(c,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(c,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(a.spinner){var j=d("span",c);j.data("label.tabs",j.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){e.element.find(e._sanitizeSelector(c.hash)).html(k);e._cleanup();a.cache&&d.data(c,
 "cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.error(k,n,b,c)}catch(m){}}}));e.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},
-url:function(b,e){this.anchors.eq(b).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.10"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(b,e){var a=this,c=this.options,h=a._rotate||(a._rotate=function(j){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=c.selected;a.select(++k<a.anchors.length?k:0)},b);j&&j.stopPropagation()});e=a._unrotate||(a._unrotate=!e?function(j){j.clientX&&
+url:function(b,e){this.anchors.eq(b).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.11"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(b,e){var a=this,c=this.options,h=a._rotate||(a._rotate=function(j){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=c.selected;a.select(++k<a.anchors.length?k:0)},b);j&&j.stopPropagation()});e=a._unrotate||(a._unrotate=!e?function(j){j.clientX&&
 a.rotate(null)}:function(){t=c.selected;h()});if(b){this.element.bind("tabsshow",h);this.anchors.bind(c.event+".tabs",e);h()}else{clearTimeout(a.rotation);this.element.unbind("tabsshow",h);this.anchors.unbind(c.event+".tabs",e);delete this._rotate;delete this._unrotate}return this}})})(jQuery);
 ;/*
- * jQuery UI Datepicker 1.8.10
+ * jQuery UI Datepicker 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -444,51 +443,52 @@ a.rotate(null)}:function(){t=c.selected;h()});if(b){this.element.bind("tabsshow"
  * Depends:
  *	jquery.ui.core.js
  */
-(function(d,G){function K(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass=
+(function(d,A){function K(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass=
 "ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su",
 "Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",
-minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false};d.extend(this._defaults,this.regional[""]);this.dpDiv=d('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}function E(a,b){d.extend(a,b);for(var c in b)if(b[c]==
-null||b[c]==G)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.10"}});var y=(new Date).getTime();d.extend(K.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=f}}}e=a.nodeName.toLowerCase();
+minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false};d.extend(this._defaults,this.regional[""]);this.dpDiv=d('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}function F(a,b){d.extend(a,b);for(var c in b)if(b[c]==
+null||b[c]==A)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.11"}});var y=(new Date).getTime();d.extend(K.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){F(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=f}}}e=a.nodeName.toLowerCase();
 f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}},
 _connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&
 b.append.remove();if(c){b.append=d('<span class="'+this._appendClass+'">'+c+"</span>");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("<img/>").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('<button type="button"></button>').addClass(this._triggerClass).html(f==
 ""?c:d("<img/>").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;g<f.length;g++)if(f[g].length>h){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,
 c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),
-true);this._updateDatepicker(b);this._updateAlternate(b);b.dpDiv.show()}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('<input type="text" id="'+("dp"+this.uuid)+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});
+true);this._updateDatepicker(b);this._updateAlternate(b);b.dpDiv.show()}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('<input type="text" id="'+("dp"+this.uuid)+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}F(a.settings,e||{});
 b=b&&b.constructor==Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);
 this._showDatepicker(this._dialogInput[0]);d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",
 this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,
 function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:
 f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return true;return false},_getInst:function(a){try{return d.data(a,"datepicker")}catch(b){throw"Missing instance data for this datepicker";}},_optionDatepicker:function(a,b,c){var e=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?d.extend({},d.datepicker._defaults):e?b=="all"?d.extend({},
-e.settings):this._get(e,b):null;var f=b||{};if(typeof b=="string"){f={};f[b]=c}if(e){this._curInst==e&&this._hideDatepicker();var h=this._getDateDatepicker(a,true);E(e.settings,f);this._attachments(d(a),e);this._autoSize(e);this._setDateDatepicker(a,h);this._updateDatepicker(e)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,b){if(a=this._getInst(a)){this._setDate(a,b);
-this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,b){(a=this._getInst(a))&&!a.inline&&this._setDateFromField(a,b);return a?this._getDate(a):null},_doKeyDown:function(a){var b=d.datepicker._getInst(a.target),c=true,e=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=true;if(d.datepicker._datepickerShowing)switch(a.keyCode){case 9:d.datepicker._hideDatepicker();c=false;break;case 13:c=d("td."+d.datepicker._dayOverClass+":not(."+d.datepicker._currentClass+")",b.dpDiv);c[0]?
-d.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,c[0]):d.datepicker._hideDatepicker();return false;case 27:d.datepicker._hideDatepicker();break;case 33:d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 34:d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)d.datepicker._clearDate(a.target);c=a.ctrlKey||
-a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)d.datepicker._gotoToday(a.target);c=a.ctrlKey||a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?+1:-1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,-7,"D");c=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,
-e?-1:+1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,+7,"D");c=a.ctrlKey||a.metaKey;break;default:c=false}else if(a.keyCode==36&&a.ctrlKey)d.datepicker._showDatepicker(this);else c=false;if(c){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var b=d.datepicker._getInst(a.target);if(d.datepicker._get(b,
-"constrainInput")){b=d.datepicker._possibleChars(d.datepicker._get(b,"dateFormat"));var c=String.fromCharCode(a.charCode==G?a.keyCode:a.charCode);return a.ctrlKey||a.metaKey||c<" "||!b||b.indexOf(c)>-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},
-_showDatepicker:function(a){a=a.target||a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=
-d.datepicker._findPos(a);d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.empty();b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,
-c,e);b.dpDiv.css({position:d.datepicker._inDialog&&d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=b.dpDiv.find("iframe.ui-datepicker-cover");if(i.length){var g=d.datepicker._getBorders(b.dpDiv);i.css({left:-g[0],top:-g[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&
-d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a));var e=a.dpDiv.find("iframe.ui-datepicker-cover");e.length&&e.css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()});a.dpDiv.find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",
-function(){d(this).removeClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=
--1&&d(this).addClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,
-"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var f=a.yearshtml;setTimeout(function(){f===a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml);f=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),
-parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),j=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,
-b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>j&&j>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1||d.expr.filters.hidden(a));)a=a[b?"previousSibling":"nextSibling"];a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);
-this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val():"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},
-_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):
-0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=
-false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){var b=this._getInst(d(a)[0]);b.input&&b._selectingMonthYear&&setTimeout(function(){b.input.focus()},0);b._selectingMonthYear=!b._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=
-d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a);this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);
-else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=
-a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;e=typeof e!="string"?e:(new Date).getFullYear()%100+parseInt(e,10);for(var f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,
-g=(c?c.monthNames:null)||this._defaults.monthNames,j=c=-1,l=-1,u=-1,k=false,o=function(p){(p=z+1<a.length&&a.charAt(z+1)==p)&&z++;return p},m=function(p){var v=o(p);p=new RegExp("^\\d{1,"+(p=="@"?14:p=="!"?20:p=="y"&&v?4:p=="o"?3:2)+"}");p=b.substring(s).match(p);if(!p)throw"Missing number at position "+s;s+=p[0].length;return parseInt(p[0],10)},n=function(p,v,H){p=o(p)?H:v;for(v=0;v<p.length;v++)if(b.substr(s,p[v].length).toLowerCase()==p[v].toLowerCase()){s+=p[v].length;return v+1}throw"Unknown name at position "+
+e.settings):this._get(e,b):null;var f=b||{};if(typeof b=="string"){f={};f[b]=c}if(e){this._curInst==e&&this._hideDatepicker();var h=this._getDateDatepicker(a,true),i=this._getMinMaxDate(e,"min"),g=this._getMinMaxDate(e,"max");F(e.settings,f);if(i!==null&&f.dateFormat!==A&&f.minDate===A)e.settings.minDate=this._formatDate(e,i);if(g!==null&&f.dateFormat!==A&&f.maxDate===A)e.settings.maxDate=this._formatDate(e,g);this._attachments(d(a),e);this._autoSize(e);this._setDateDatepicker(a,h);this._updateDatepicker(e)}},
+_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,b){if(a=this._getInst(a)){this._setDate(a,b);this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,b){(a=this._getInst(a))&&!a.inline&&this._setDateFromField(a,b);return a?this._getDate(a):null},_doKeyDown:function(a){var b=d.datepicker._getInst(a.target),c=true,e=b.dpDiv.is(".ui-datepicker-rtl");
+b._keyEvent=true;if(d.datepicker._datepickerShowing)switch(a.keyCode){case 9:d.datepicker._hideDatepicker();c=false;break;case 13:c=d("td."+d.datepicker._dayOverClass+":not(."+d.datepicker._currentClass+")",b.dpDiv);c[0]?d.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,c[0]):d.datepicker._hideDatepicker();return false;case 27:d.datepicker._hideDatepicker();break;case 33:d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),
+"M");break;case 34:d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)d.datepicker._clearDate(a.target);c=a.ctrlKey||a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)d.datepicker._gotoToday(a.target);c=a.ctrlKey||a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?+1:-1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?
+-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,-7,"D");c=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?-1:+1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,
++7,"D");c=a.ctrlKey||a.metaKey;break;default:c=false}else if(a.keyCode==36&&a.ctrlKey)d.datepicker._showDatepicker(this);else c=false;if(c){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var b=d.datepicker._getInst(a.target);if(d.datepicker._get(b,"constrainInput")){b=d.datepicker._possibleChars(d.datepicker._get(b,"dateFormat"));var c=String.fromCharCode(a.charCode==A?a.keyCode:a.charCode);return a.ctrlKey||a.metaKey||c<" "||!b||b.indexOf(c)>-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);
+if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);
+d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");F(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=
+document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.empty();b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");
+var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=b.dpDiv.find("iframe.ui-datepicker-cover");if(i.length){var g=d.datepicker._getBorders(b.dpDiv);i.css({left:-g[0],top:-g[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=
+b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a));var e=a.dpDiv.find("iframe.ui-datepicker-cover");e.length&&e.css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()});a.dpDiv.find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");
+this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+
+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&
+a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var f=a.yearshtml;setTimeout(function(){f===a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml);f=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():
+0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),j=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>j&&j>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),
+"isRTL");a&&(a.type=="hidden"||a.nodeType!=1||d.expr.filters.hidden(a));)a=a[b?"previousSibling":"nextSibling"];a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?
+"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val():"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=
+d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=
+d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c==
+"M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){var b=this._getInst(d(a)[0]);b.input&&b._selectingMonthYear&&setTimeout(function(){b.input.focus()},0);b._selectingMonthYear=!b._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=
+b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a);this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();
+this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);
+a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;e=typeof e!="string"?e:(new Date).getFullYear()%100+parseInt(e,10);for(var f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?
+c.monthNames:null)||this._defaults.monthNames,j=c=-1,l=-1,u=-1,k=false,o=function(p){(p=z+1<a.length&&a.charAt(z+1)==p)&&z++;return p},m=function(p){var v=o(p);p=new RegExp("^\\d{1,"+(p=="@"?14:p=="!"?20:p=="y"&&v?4:p=="o"?3:2)+"}");p=b.substring(s).match(p);if(!p)throw"Missing number at position "+s;s+=p[0].length;return parseInt(p[0],10)},n=function(p,v,H){p=o(p)?H:v;for(v=0;v<p.length;v++)if(b.substr(s,p[v].length).toLowerCase()==p[v].toLowerCase()){s+=p[v].length;return v+1}throw"Unknown name at position "+
 s;},r=function(){if(b.charAt(s)!=a.charAt(z))throw"Unexpected literal at position "+s;s++},s=0,z=0;z<a.length;z++)if(k)if(a.charAt(z)=="'"&&!o("'"))k=false;else r();else switch(a.charAt(z)){case "d":l=m("d");break;case "D":n("D",f,h);break;case "o":u=m("o");break;case "m":j=m("m");break;case "M":j=n("M",i,g);break;case "y":c=m("y");break;case "@":var w=new Date(m("@"));c=w.getFullYear();j=w.getMonth()+1;l=w.getDate();break;case "!":w=new Date((m("!")-this._ticksTo1970)/1E4);c=w.getFullYear();j=w.getMonth()+
 1;l=w.getDate();break;case "'":if(o("'"))r();else k=true;break;default:r()}if(c==-1)c=(new Date).getFullYear();else if(c<100)c+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c<=e?0:-100);if(u>-1){j=1;l=u;do{e=this._getDaysInMonth(c,j-1);if(l<=e)break;j++;l-=e}while(1)}w=this._daylightSavingAdjust(new Date(c,j-1,l));if(w.getFullYear()!=c||w.getMonth()+1!=j||w.getDate()!=l)throw"Invalid date";return w},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",
 RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=k+1<a.length&&
 a.charAt(k+1)==o)&&k++;return o},g=function(o,m,n){m=""+m;if(i(o))for(;m.length<n;)m="0"+m;return m},j=function(o,m,n,r){return i(o)?r[m]:n[m]},l="",u=false;if(b)for(var k=0;k<a.length;k++)if(u)if(a.charAt(k)=="'"&&!i("'"))u=false;else l+=a.charAt(k);else switch(a.charAt(k)){case "d":l+=g("d",b.getDate(),2);break;case "D":l+=j("D",b.getDay(),e,f);break;case "o":l+=g("o",(b.getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864E5,3);break;case "m":l+=g("m",b.getMonth()+1,2);break;case "M":l+=j("M",
 b.getMonth(),h,c);break;case "y":l+=i("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case "@":l+=b.getTime();break;case "!":l+=b.getTime()*1E4+this._ticksTo1970;break;case "'":if(i("'"))l+="'";else u=true;break;default:l+=a.charAt(k)}return l},_possibleChars:function(a){for(var b="",c=false,e=function(h){(h=f+1<a.length&&a.charAt(f+1)==h)&&f++;return h},f=0;f<a.length;f++)if(c)if(a.charAt(f)=="'"&&!e("'"))c=false;else b+=a.charAt(f);else switch(a.charAt(f)){case "d":case "m":case "y":case "@":b+=
-"0123456789";break;case "D":case "M":return null;case "'":if(e("'"))b+="'";else c=true;break;default:b+=a.charAt(f)}return b},_get:function(a,b){return a.settings[b]!==G?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),e=a.lastVal=a.input?a.input.val():null,f,h;f=h=this._getDefaultDate(a);var i=this._getFormatConfig(a);try{f=this.parseDate(c,e,i)||h}catch(g){this.log(g);e=b?"":e}a.selectedDay=f.getDate();a.drawMonth=a.selectedMonth=
+"0123456789";break;case "D":case "M":return null;case "'":if(e("'"))b+="'";else c=true;break;default:b+=a.charAt(f)}return b},_get:function(a,b){return a.settings[b]!==A?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),e=a.lastVal=a.input?a.input.val():null,f,h;f=h=this._getDefaultDate(a);var i=this._getFormatConfig(a);try{f=this.parseDate(c,e,i)||h}catch(g){this.log(g);e=b?"":e}a.selectedDay=f.getDate();a.drawMonth=a.selectedMonth=
 f.getMonth();a.drawYear=a.selectedYear=f.getFullYear();a.currentDay=e?f.getDate():0;a.currentMonth=e?f.getMonth():0;a.currentYear=e?f.getFullYear():0;this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},_determineDate:function(a,b,c){var e=function(h){var i=new Date;i.setDate(i.getDate()+h);return i},f=function(h){try{return d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),h,d.datepicker._getFormatConfig(a))}catch(i){}var g=
 (h.toLowerCase().match(/^c/)?d.datepicker._getDate(a):null)||new Date,j=g.getFullYear(),l=g.getMonth();g=g.getDate();for(var u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,k=u.exec(h);k;){switch(k[2]||"d"){case "d":case "D":g+=parseInt(k[1],10);break;case "w":case "W":g+=parseInt(k[1],10)*7;break;case "m":case "M":l+=parseInt(k[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(j,l));break;case "y":case "Y":j+=parseInt(k[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(j,l));break}k=u.exec(h)}return new Date(j,
 l,g)};if(b=(b=b==null||b===""?c:typeof b=="string"?f(b):typeof b=="number"?isNaN(b)?c:e(b):new Date(b.getTime()))&&b.toString()=="Invalid Date"?c:b){b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0)}return this._daylightSavingAdjust(b)},_daylightSavingAdjust:function(a){if(!a)return null;a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=
@@ -498,12 +498,12 @@ this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.g
 (c?"e":"w")+'">'+n+"</span></a>":f?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m,g+j,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', +"+j+", 'M');\" title=\""+r+'"><span class="ui-icon ui-icon-circle-triangle-'+
 (c?"w":"e")+'">'+r+"</span></a>":f?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>";j=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&&a.currentDay?u:b;j=!h?j:this.formatDate(j,r,this._getFormatConfig(a));h=!a.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+y+'.datepicker._hideDatepicker();">'+this._get(a,
 "closeText")+"</button>":"";e=e?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?h:"")+(this._isInRange(a,r)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._gotoToday('#"+a.id+"');\">"+j+"</button>":"")+(c?"":h)+"</div>":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;j=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=
-this._get(a,"monthNames"),w=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),v=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var L=this._getDefaultDate(a),I="",C=0;C<i[0];C++){for(var M="",D=0;D<i[1];D++){var N=this._daylightSavingAdjust(new Date(m,g,a.selectedDay)),t=" ui-corner-all",x="";if(l){x+='<div class="ui-datepicker-group';if(i[1]>1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-
-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+t+'">'+(/all|left/.test(t)&&C==0?c?f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,k,o,C>0||D>0,z,w)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var A=j?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(t=0;t<7;t++){var q=
-(t+h)%7;A+="<th"+((t+h+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+r[q]+'">'+s[q]+"</span></th>"}x+=A+"</tr></thead><tbody>";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay,A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var O=0;O<A;O++){x+="<tr>";var P=!j?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(q)+"</td>";for(t=0;t<7;t++){var F=
-p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,J=B&&!H||!F[0]||k&&q<k||o&&q>o;P+='<td class="'+((t+h+6)%7>=5?" ui-datepicker-week-end":"")+(B?" ui-datepicker-other-month":"")+(q.getTime()==N.getTime()&&g==a.selectedMonth&&a._keyEvent||L.getTime()==q.getTime()&&L.getTime()==N.getTime()?" "+this._dayOverClass:"")+(J?" "+this._unselectableClass+" ui-state-disabled":"")+(B&&!v?"":" "+F[1]+(q.getTime()==u.getTime()?" "+this._currentClass:"")+(q.getTime()==b.getTime()?" ui-datepicker-today":
-""))+'"'+((!B||v)&&F[2]?' title="'+F[2]+'"':"")+(J?"":' onclick="DP_jQuery_'+y+".datepicker._selectDay('#"+a.id+"',"+q.getMonth()+","+q.getFullYear()+', this);return false;"')+">"+(B&&!v?"&#xa0;":J?'<span class="ui-state-default">'+q.getDate()+"</span>":'<a class="ui-state-default'+(q.getTime()==b.getTime()?" ui-state-highlight":"")+(q.getTime()==u.getTime()?" ui-state-active":"")+(B?" ui-priority-secondary":"")+'" href="#">'+q.getDate()+"</a>")+"</td>";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=
-P+"</tr>"}g++;if(g>11){g=0;m++}x+="</tbody></table>"+(l?"</div>"+(i[0]>0&&D==i[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");M+=x}I+=M}I+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':"");a._keyEvent=false;return I},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var j=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),k='<div class="ui-datepicker-title">',
+this._get(a,"monthNames"),w=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),v=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var L=this._getDefaultDate(a),I="",D=0;D<i[0];D++){for(var M="",E=0;E<i[1];E++){var N=this._daylightSavingAdjust(new Date(m,g,a.selectedDay)),t=" ui-corner-all",x="";if(l){x+='<div class="ui-datepicker-group';if(i[1]>1)switch(E){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-
+1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+t+'">'+(/all|left/.test(t)&&D==0?c?f:n:"")+(/all|right/.test(t)&&D==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,k,o,D>0||E>0,z,w)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var B=j?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(t=0;t<7;t++){var q=
+(t+h)%7;B+="<th"+((t+h+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+r[q]+'">'+s[q]+"</span></th>"}x+=B+"</tr></thead><tbody>";B=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay,B);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;B=l?6:Math.ceil((t+B)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var O=0;O<B;O++){x+="<tr>";var P=!j?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(q)+"</td>";for(t=0;t<7;t++){var G=
+p?p.apply(a.input?a.input[0]:null,[q]):[true,""],C=q.getMonth()!=g,J=C&&!H||!G[0]||k&&q<k||o&&q>o;P+='<td class="'+((t+h+6)%7>=5?" ui-datepicker-week-end":"")+(C?" ui-datepicker-other-month":"")+(q.getTime()==N.getTime()&&g==a.selectedMonth&&a._keyEvent||L.getTime()==q.getTime()&&L.getTime()==N.getTime()?" "+this._dayOverClass:"")+(J?" "+this._unselectableClass+" ui-state-disabled":"")+(C&&!v?"":" "+G[1]+(q.getTime()==u.getTime()?" "+this._currentClass:"")+(q.getTime()==b.getTime()?" ui-datepicker-today":
+""))+'"'+((!C||v)&&G[2]?' title="'+G[2]+'"':"")+(J?"":' onclick="DP_jQuery_'+y+".datepicker._selectDay('#"+a.id+"',"+q.getMonth()+","+q.getFullYear()+', this);return false;"')+">"+(C&&!v?"&#xa0;":J?'<span class="ui-state-default">'+q.getDate()+"</span>":'<a class="ui-state-default'+(q.getTime()==b.getTime()?" ui-state-highlight":"")+(q.getTime()==u.getTime()?" ui-state-active":"")+(C?" ui-priority-secondary":"")+'" href="#">'+q.getDate()+"</a>")+"</td>";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=
+P+"</tr>"}g++;if(g>11){g=0;m++}x+="</tbody></table>"+(l?"</div>"+(i[0]>0&&E==i[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");M+=x}I+=M}I+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':"");a._keyEvent=false;return I},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var j=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),k='<div class="ui-datepicker-title">',
 o="";if(h||!j)o+='<span class="ui-datepicker-month">'+i[b]+"</span>";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+a.id+"');\">";for(var n=0;n<12;n++)if((!i||n>=e.getMonth())&&(!m||n<=f.getMonth()))o+='<option value="'+n+'"'+(n==b?' selected="selected"':"")+">"+g[n]+"</option>";o+="</select>"}u||(k+=o+(h||!(j&&
 l)?"&#xa0;":""));a.yearshtml="";if(h||!l)k+='<span class="ui-datepicker-year">'+c+"</span>";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b,i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(a.yearshtml+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+
 a.id+"', this, 'Y');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+a.id+"');\">";b<=g;b++)a.yearshtml+='<option value="'+b+'"'+(b==c?' selected="selected"':"")+">"+b+"</option>";a.yearshtml+="</select>";if(d.browser.mozilla)k+='<select class="ui-datepicker-year"><option value="'+c+'" selected="selected">'+c+"</option></select>";else{k+=a.yearshtml;a.yearshtml=null}}k+=this._get(a,"yearSuffix");if(u)k+=(h||!(j&&l)?"&#xa0;":"")+o;k+="</div>";return k},_adjustInstDate:function(a,b,c){var e=
@@ -512,9 +512,9 @@ a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this
 c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,
 "dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=
 function(a){if(!this.length)return this;if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,
-[this[0]].concat(b));return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new K;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.10";window["DP_jQuery_"+y]=d})(jQuery);
+[this[0]].concat(b));return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new K;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.11";window["DP_jQuery_"+y]=d})(jQuery);
 ;/*
- * jQuery UI Progressbar 1.8.10
+ * jQuery UI Progressbar 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -528,9 +528,9 @@ function(a){if(!this.length)return this;if(!d.datepicker.initialized){d(document
  */
 (function(b,d){b.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()});this.valueDiv=b("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element);this.oldValue=this._value();this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow");
 this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===d)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){if(a==="value"){this.options.value=c;this._refreshValue();this._value()===this.options.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*
-this._value()/this.options.max},_refreshValue:function(){var a=this.value(),c=this._percentage();if(this.oldValue!==a){this.oldValue=a;this._trigger("change")}this.valueDiv.toggleClass("ui-corner-right",a===this.options.max).width(c.toFixed(0)+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.10"})})(jQuery);
+this._value()/this.options.max},_refreshValue:function(){var a=this.value(),c=this._percentage();if(this.oldValue!==a){this.oldValue=a;this._trigger("change")}this.valueDiv.toggleClass("ui-corner-right",a===this.options.max).width(c.toFixed(0)+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.11"})})(jQuery);
 ;/*
- * jQuery UI Effects 1.8.10
+ * jQuery UI Effects 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -547,7 +547,7 @@ a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number
 211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},r=["add","remove","toggle"],t={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,
 d){if(f.isFunction(b)){d=b;b=null}return this.queue("fx",function(){var e=f(this),g=e.attr("style")||" ",h=q(p.call(this)),l,v=e.attr("className");f.each(r,function(w,i){c[i]&&e[i+"Class"](c[i])});l=q(p.call(this));e.attr("className",v);e.animate(u(h,l),a,b,function(){f.each(r,function(w,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)});h=f.queue(this);l=h.splice(h.length-1,1)[0];
 h.splice(1,0,l);f.dequeue(this)})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,
-a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.10",save:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.data("ec.storage."+a[b],c[0].style[a[b]])},restore:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.css(a[b],c.data("ec.storage."+a[b]))},setMode:function(c,a){if(a=="toggle")a=c.is(":hidden")?"show":"hide";return a},getBaseline:function(c,
+a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.11",save:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.data("ec.storage."+a[b],c[0].style[a[b]])},restore:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.css(a[b],c.data("ec.storage."+a[b]))},setMode:function(c,a){if(a=="toggle")a=c.is(":hidden")?"show":"hide";return a},getBaseline:function(c,
 a){var b;switch(c[0]){case "top":b=0;break;case "middle":b=0.5;break;case "bottom":b=1;break;default:b=c[0]/a.height}switch(c[1]){case "left":c=0;break;case "center":c=0.5;break;case "right":c=1;break;default:c=c[1]/a.width}return{x:c,y:b}},createWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent();var a={width:c.outerWidth(true),height:c.outerHeight(true),"float":c.css("float")},b=f("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",
 border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"});c.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);
 return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments),b={options:a[1],duration:a[2],callback:a[3]};a=b.options.mode;var d=f.effects[c];if(f.fx.off||!d)return a?this[a](b.duration,b.callback):this.each(function(){b.callback&&b.callback.call(this)});return d.call(this,b)},_show:f.fn.show,show:function(c){if(m(c))return this._show.apply(this,arguments);
@@ -560,7 +560,7 @@ g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*
 h);if(a<1)return-0.5*h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)+b;return h*Math.pow(2,-10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)*0.5+d+b},easeInBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;return d*(a/=e)*a*((g+1)*a-g)+b},easeOutBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;return d*((a=a/e-1)*a*((g+1)*a+g)+1)+b},easeInOutBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;if((a/=e/2)<1)return d/2*a*a*(((g*=1.525)+1)*a-g)+b;return d/2*((a-=2)*a*(((g*=1.525)+1)*a+g)+2)+b},easeInBounce:function(c,
 a,b,d,e){return d-f.easing.easeOutBounce(c,e-a,0,d,e)+b},easeOutBounce:function(c,a,b,d,e){return(a/=e)<1/2.75?d*7.5625*a*a+b:a<2/2.75?d*(7.5625*(a-=1.5/2.75)*a+0.75)+b:a<2.5/2.75?d*(7.5625*(a-=2.25/2.75)*a+0.9375)+b:d*(7.5625*(a-=2.625/2.75)*a+0.984375)+b},easeInOutBounce:function(c,a,b,d,e){if(a<e/2)return f.easing.easeInBounce(c,a*2,0,d,e)*0.5+b;return f.easing.easeOutBounce(c,a*2-e,0,d,e)*0.5+d*0.5+b}})}(jQuery);
 ;/*
- * jQuery UI Effects Blind 1.8.10
+ * jQuery UI Effects Blind 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -574,7 +574,7 @@ a,b,d,e){return d-f.easing.easeOutBounce(c,e-a,0,d,e)+b},easeOutBounce:function(
 (function(b){b.effects.blind=function(c){return this.queue(function(){var a=b(this),g=["position","top","bottom","left","right"],f=b.effects.setMode(a,c.options.mode||"hide"),d=c.options.direction||"vertical";b.effects.save(a,g);a.show();var e=b.effects.createWrapper(a).css({overflow:"hidden"}),h=d=="vertical"?"height":"width";d=d=="vertical"?e.height():e.width();f=="show"&&e.css(h,0);var i={};i[h]=f=="show"?d:0;e.animate(i,c.duration,c.options.easing,function(){f=="hide"&&a.hide();b.effects.restore(a,
 g);b.effects.removeWrapper(a);c.callback&&c.callback.apply(a[0],arguments);a.dequeue()})})}})(jQuery);
 ;/*
- * jQuery UI Effects Bounce 1.8.10
+ * jQuery UI Effects Bounce 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -589,7 +589,7 @@ g);b.effects.removeWrapper(a);c.callback&&c.callback.apply(a[0],arguments);a.deq
 3);if(h=="show")a.css("opacity",0).css(f,d=="pos"?-c:c);if(h=="hide")c/=m*2;h!="hide"&&m--;if(h=="show"){var g={opacity:1};g[f]=(d=="pos"?"+=":"-=")+c;a.animate(g,i/2,b.options.easing);c/=2;m--}for(g=0;g<m;g++){var j={},k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing);c=h=="hide"?c*2:c/2}if(h=="hide"){g={opacity:0};g[f]=(d=="pos"?"-=":"+=")+c;a.animate(g,i/2,b.options.easing,function(){a.hide();e.effects.restore(a,l);e.effects.removeWrapper(a);
 b.callback&&b.callback.apply(this,arguments)})}else{j={};k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing,function(){e.effects.restore(a,l);e.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments)})}a.queue("fx",function(){a.dequeue()});a.dequeue()})}})(jQuery);
 ;/*
- * jQuery UI Effects Clip 1.8.10
+ * jQuery UI Effects Clip 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -603,7 +603,7 @@ b.callback&&b.callback.apply(this,arguments)})}else{j={};k={};j[f]=(d=="pos"?"-=
 (function(b){b.effects.clip=function(e){return this.queue(function(){var a=b(this),i=["position","top","bottom","left","right","height","width"],f=b.effects.setMode(a,e.options.mode||"hide"),c=e.options.direction||"vertical";b.effects.save(a,i);a.show();var d=b.effects.createWrapper(a).css({overflow:"hidden"});d=a[0].tagName=="IMG"?d:a;var g={size:c=="vertical"?"height":"width",position:c=="vertical"?"top":"left"};c=c=="vertical"?d.height():d.width();if(f=="show"){d.css(g.size,0);d.css(g.position,
 c/2)}var h={};h[g.size]=f=="show"?c:0;h[g.position]=f=="show"?0:c/2;d.animate(h,{queue:false,duration:e.duration,easing:e.options.easing,complete:function(){f=="hide"&&a.hide();b.effects.restore(a,i);b.effects.removeWrapper(a);e.callback&&e.callback.apply(a[0],arguments);a.dequeue()}})})}})(jQuery);
 ;/*
- * jQuery UI Effects Drop 1.8.10
+ * jQuery UI Effects Drop 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -617,7 +617,7 @@ c/2)}var h={};h[g.size]=f=="show"?c:0;h[g.position]=f=="show"?0:c/2;d.animate(h,
 (function(c){c.effects.drop=function(d){return this.queue(function(){var a=c(this),h=["position","top","bottom","left","right","opacity"],e=c.effects.setMode(a,d.options.mode||"hide"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a);var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true})/2:a.outerWidth({margin:true})/2);if(e=="show")a.css("opacity",0).css(f,b=="pos"?-g:g);var i={opacity:e==
 "show"?1:0};i[f]=(e=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
 ;/*
- * jQuery UI Effects Explode 1.8.10
+ * jQuery UI Effects Explode 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -632,7 +632,7 @@ c/2)}var h={};h[g.size]=f=="show"?c:0;h[g.position]=f=="show"?0:c/2;d.animate(h,
 0;f<d;f++)b.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+
 e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery);
 ;/*
- * jQuery UI Effects Fade 1.8.10
+ * jQuery UI Effects Fade 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -645,7 +645,7 @@ e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.m
  */
 (function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery);
 ;/*
- * jQuery UI Effects Fold 1.8.10
+ * jQuery UI Effects Fold 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -659,7 +659,7 @@ e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.m
 (function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","bottom","left","right"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],
 10)/100*f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery);
 ;/*
- * jQuery UI Effects Highlight 1.8.10
+ * jQuery UI Effects Highlight 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -673,7 +673,7 @@ e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.m
 (function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&&
 this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
 ;/*
- * jQuery UI Effects Pulsate 1.8.10
+ * jQuery UI Effects Pulsate 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -687,7 +687,7 @@ this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments
 (function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c<times;c++){b.animate({opacity:animateTo},duration,a.options.easing);animateTo=(animateTo+1)%2}b.animate({opacity:animateTo},duration,
 a.options.easing,function(){animateTo==0&&b.hide();a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()}).dequeue()})}})(jQuery);
 ;/*
- * jQuery UI Effects Scale 1.8.10
+ * jQuery UI Effects Scale 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -707,7 +707,7 @@ a.css("overflow","hidden").css(a.from);if(m=="content"||m=="both"){f=f.concat(["
 child.to=c.effects.setTransition(child,f,d.to.y,child.to)}if(d.from.x!=d.to.x){child.from=c.effects.setTransition(child,k,d.from.x,child.from);child.to=c.effects.setTransition(child,k,d.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){n&&c.effects.restore(child,h)})})}a.animate(a.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){a.to.opacity===0&&a.css("opacity",a.from.opacity);p=="hide"&&a.hide();c.effects.restore(a,
 n?e:g);c.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
 ;/*
- * jQuery UI Effects Shake 1.8.10
+ * jQuery UI Effects Shake 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -721,7 +721,7 @@ n?e:g);c.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments);a
 (function(d){d.effects.shake=function(a){return this.queue(function(){var b=d(this),j=["position","top","bottom","left","right"];d.effects.setMode(b,a.options.mode||"effect");var c=a.options.direction||"left",e=a.options.distance||20,l=a.options.times||3,f=a.duration||a.options.duration||140;d.effects.save(b,j);b.show();d.effects.createWrapper(b);var g=c=="up"||c=="down"?"top":"left",h=c=="up"||c=="left"?"pos":"neg";c={};var i={},k={};c[g]=(h=="pos"?"-=":"+=")+e;i[g]=(h=="pos"?"+=":"-=")+e*2;k[g]=
 (h=="pos"?"-=":"+=")+e*2;b.animate(c,f,a.options.easing);for(e=1;e<l;e++)b.animate(i,f,a.options.easing).animate(k,f,a.options.easing);b.animate(i,f,a.options.easing).animate(c,f/2,a.options.easing,function(){d.effects.restore(b,j);d.effects.removeWrapper(b);a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()});b.dequeue()})}})(jQuery);
 ;/*
- * jQuery UI Effects Slide 1.8.10
+ * jQuery UI Effects Slide 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
@@ -735,7 +735,7 @@ n?e:g);c.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments);a
 (function(c){c.effects.slide=function(d){return this.queue(function(){var a=c(this),h=["position","top","bottom","left","right"],f=c.effects.setMode(a,d.options.mode||"show"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a).css({overflow:"hidden"});var g=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var e=d.options.distance||(g=="top"?a.outerHeight({margin:true}):a.outerWidth({margin:true}));if(f=="show")a.css(g,b=="pos"?isNaN(e)?"-"+e:-e:e);
 var i={};i[g]=(f=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+e;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){f=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
 ;/*
- * jQuery UI Effects Transfer 1.8.10
+ * jQuery UI Effects Transfer 1.8.11
  *
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
  * Dual licensed under the MIT or GPL Version 2 licenses.
diff --git a/data/js/restart.js b/data/js/restart.js
new file mode 100644
index 0000000000000000000000000000000000000000..86160c9482b6fdc6bfa61ba2e0bc0895323f0130
--- /dev/null
+++ b/data/js/restart.js
@@ -0,0 +1,59 @@
+var is_alive_url = sbRoot+'/home/is_alive';
+var timeout_id;
+var current_pid = '';
+var num_restart_waits = 0;
+
+function is_alive() {
+    timeout_id = 0;
+    $.get(is_alive_url, function(data) {
+                                        
+        // if it's still initalizing then just wait and try again
+        if (data == 'nope') {
+            $('#shut_down_loading').hide();
+            $('#shut_down_success').show();
+            $('#restart_message').show();
+            setTimeout('is_alive()', 1000);
+        } else {
+            // if this is before we've even shut down then just try again later
+            if (current_pid == '' || data == current_pid) {
+                current_pid = data;
+                setTimeout(is_alive, 1000);
+
+            // if we're ready to go then refresh the page which'll forward to /home
+            } else {
+                $('#restart_loading').hide();
+                $('#restart_success').show();
+                $('#refresh_message').show();
+                location.reload();
+            }
+        }
+    });
+}
+
+$(document).ready(function() 
+{ 
+
+    is_alive();
+    
+    $('#shut_down_message').ajaxError(function(e, jqxhr, settings, exception) {
+        if (settings.url != is_alive_url)
+            return;
+        num_restart_waits += 1;
+
+        $('#shut_down_loading').hide();
+        $('#shut_down_success').show();
+        $('#restart_message').show();
+
+        // if it is taking forever just give up
+        if (num_restart_waits > 90) {
+            $('#restart_loading').hide();
+            $('#restart_failure').show();
+            $('#restart_fail_message').show();
+            return;
+        }
+
+        if (timeout_id == 0)
+            timeout_id = setTimeout('is_alive()', 1000);
+    });
+
+});
diff --git a/data/js/rootDirs.js b/data/js/rootDirs.js
index 2ab7cd37a8a0c4da447b883ad8bec2971e855c5c..1947646b404d96f947aef43c8048f8531ca3cff6 100644
--- a/data/js/rootDirs.js
+++ b/data/js/rootDirs.js
@@ -20,7 +20,7 @@ $(document).ready(function(){
 
         refreshRootDirs();
     
-        $.get('/config/general/saveRootDirs', { rootDirString: $('#rootDirText').val() });
+        $.get(sbRoot+'/config/general/saveRootDirs', { rootDirString: $('#rootDirText').val() });
     
     }
 
@@ -37,7 +37,7 @@ $(document).ready(function(){
         }
 
         refreshRootDirs();
-        $.get('/config/general/saveRootDirs', {rootDirString: $('#rootDirText').val()});
+        $.get(sbRoot+'/config/general/saveRootDirs', {rootDirString: $('#rootDirText').val()});
     }
     
     $('#addRootDir').click(function(){$(this).nFileBrowser(addRootDir)});
@@ -73,14 +73,14 @@ $(document).ready(function(){
 
         }
         refreshRootDirs();
-        $.get('/config/general/saveRootDirs', {rootDirString: $('#rootDirText').val()});
+        $.get(sbRoot+'/config/general/saveRootDirs', {rootDirString: $('#rootDirText').val()});
     });
 
     $('#defaultRootDir').click(function(){
         if ($("#rootDirs option:selected").length)
             setDefault($("#rootDirs option:selected").attr('id'));
         refreshRootDirs();
-        $.get('/config/general/saveRootDirs', 'rootDirString='+$('#rootDirText').val());
+        $.get(sbRoot+'/config/general/saveRootDirs', 'rootDirString='+$('#rootDirText').val());
     });
 
     function setDefault(which, force){
diff --git a/init.fedora b/init.fedora
new file mode 100755
index 0000000000000000000000000000000000000000..d763c373f58c58f7e2f37612d49448e60c6f170b
--- /dev/null
+++ b/init.fedora
@@ -0,0 +1,86 @@
+### BEGIN INIT INFO
+# Provides:          Sick Beard application instance
+# Required-Start:    $all
+# Required-Stop:     $all
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: starts Sick Beard
+# Description:       starts Sick Beard
+### END INIT INFO
+
+# Source function library.
+. /etc/init.d/functions
+
+# Source SickBeard configuration
+if [ -f /etc/sysconfig/sickbeard ]; then
+        . /etc/sysconfig/sickbeard
+fi
+
+prog=sickbeard
+lockfile=/var/lock/subsys/$prog
+
+## Edit user configuation in /etc/sysconfig/sickbeard to change
+## the defaults
+username=${SB_USER-sickbeard}
+homedir=${SB_HOME-/opt/sickbeard}
+pidfile=${SB_PIDFILE-/var/run/sickbeard/sickbeard.pid}
+nice=${SB_NICE-}
+##
+
+pidpath=`dirname ${pidfile}`
+options=" --daemon --pidfile=${pidfile}"
+
+# create PID directory if not exist and ensure the SickBeard user can write to it
+if [ ! -d $pidpath ]; then
+	mkdir -p $pidpath
+	chown $username $pidpath
+fi
+
+start() {
+        # Start daemon.
+        echo -n $"Starting $prog: "
+        daemon --user=${username} --pidfile=${pidfile} ${nice} python ${homedir}/SickBeard.py ${options}
+        RETVAL=$?
+        echo
+        [ $RETVAL -eq 0 ] && touch $lockfile
+        return $RETVAL
+}
+
+stop() {
+        echo -n $"Shutting down $prog: "
+        killproc -p ${pidfile} python
+        RETVAL=$?
+        echo
+        [ $RETVAL -eq 0 ] && rm -f $lockfile
+        return $RETVAL
+}
+
+# See how we were called.
+case "$1" in
+  start)
+        start
+        ;;
+  stop)
+        stop
+        ;;
+  status)
+        status $prog
+        ;;
+  restart|force-reload)
+        stop
+        start
+        ;;
+  try-restart|condrestart)
+        if status $prog > /dev/null; then
+            stop
+            start
+        fi
+        ;;
+  reload)
+        exit 3
+        ;;
+  *)
+        echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}"
+        exit 2
+esac
+
diff --git a/initscript b/init.ubuntu
similarity index 70%
rename from initscript
rename to init.ubuntu
index 85619f86133799593c312f14528a6e8c28f9df7e..6509898c04075f82b3f45777978ece232ec26398 100755
--- a/initscript
+++ b/init.ubuntu
@@ -17,8 +17,12 @@ APP_PATH=PATH_TO_SICKBEARD_DIRECTORY
 # path to python bin
 DAEMON=/usr/bin/python
 
+# Path to store PID file
+PID_FILE=/var/run/sickbeard/sickbeard.pid
+PID_PATH=`dirname $PID_FILE`
+
 # startup args
-DAEMON_OPTS=" SickBeard.py -q"
+DAEMON_OPTS=" SickBeard.py -q --daemon --pidfile=${PID_FILE}"
 
 # script name
 NAME=sickbeard
@@ -29,18 +33,21 @@ DESC=SickBeard
 # user
 RUN_AS=SICKBEARD_USER
 
-PID_FILE=/var/run/sickbeard.pid
-
 ############### END EDIT ME ##################
 
 test -x $DAEMON || exit 0
 
 set -e
 
+if [ ! -d $PID_PATH ]; then
+        mkdir -p $PID_PATH
+        chown $RUN_AS $PID_PATH
+fi
+
 case "$1" in
   start)
         echo "Starting $DESC"
-        start-stop-daemon -d $APP_PATH -c $RUN_AS --start --background --pidfile $PID_FILE  --make-pidfile --exec $DAEMON -- $DAEMON_OPTS
+        start-stop-daemon -d $APP_PATH -c $RUN_AS --start --pidfile $PID_FILE --exec $DAEMON -- $DAEMON_OPTS
         ;;
   stop)
         echo "Stopping $DESC"
@@ -51,7 +58,7 @@ case "$1" in
         echo "Restarting $DESC"
         start-stop-daemon --stop --pidfile $PID_FILE
         sleep 15
-        start-stop-daemon -d $APP_PATH -c $RUN_AS --start --background --pidfile $PID_FILE  --make-pidfile --exec $DAEMON -- $DAEMON_OPTS
+        start-stop-daemon -d $APP_PATH -c $RUN_AS --start --pidfile $PID_FILE --exec $DAEMON -- $DAEMON_OPTS
         ;;
   *)
         N=/etc/init.d/$NAME
diff --git a/lib/httplib2/__init__.py b/lib/httplib2/__init__.py
index 4285b1c2ed4a26b187c5b0f46cd9733b8639b1de..39b78f4d1eeae608d99602ac2c33583990eefa21 100644
--- a/lib/httplib2/__init__.py
+++ b/lib/httplib2/__init__.py
@@ -869,7 +869,9 @@ the same interface as FileCache."""
                 conn.close()
                 raise ServerNotFoundError("Unable to find the server at %s" % conn.host)
             except socket.error, e:
-                if e.errno == errno.ECONNREFUSED: # Connection refused
+                if not hasattr(e, 'errno'): # I don't know what this is so lets raise it if it happens
+                    raise
+                elif e.errno == errno.ECONNREFUSED: # Connection refused
                     raise
                 # Just because the server closed the connection doesn't apparently mean
                 # that the server didn't send a response.
diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py
index 8e4e17ba0d6079821f1c7fab0ca51dddcf26aa0c..00902c91dca3a130fab529c467c2856cd204595a 100644
--- a/lib/tvdb_api/tvdb_api.py
+++ b/lib/tvdb_api/tvdb_api.py
@@ -28,6 +28,7 @@ import warnings
 import logging
 import datetime
 import time
+import traceback
 
 try:
     import xml.etree.cElementTree as ElementTree
@@ -71,9 +72,9 @@ def clean_cache(cachedir):
 
     # Does our cachedir exists
     if not os.path.isdir(cachedir):
-	log().debug("Told to clean cache dir %s but it does not exist" %
-		cachedir)
-	return
+        log().debug("Told to clean cache dir %s but it does not exist" %
+                cachedir)
+        return
     now = time.time()
     day = 86400
 
@@ -81,14 +82,14 @@ def clean_cache(cachedir):
     files = os.listdir(cachedir)
 
     for file in files:
-	ffile = os.path.join(cachedir,file)
-	# If modified time is > 24 hrs ago, die!
-	# log().debug("Comparing %s mtime" % ffile)
-	if now - os.stat(ffile).st_mtime > day:
-	    try:
-		os.remove(ffile)
-	    except:
-		raise tvdb_error("Couldn't remove %s" % ffile)
+        ffile = os.path.join(cachedir,file)
+        # If modified time is > 24 hrs ago, die!
+        # log().debug("Comparing %s mtime" % ffile)
+        if now - os.stat(ffile).st_mtime > day:
+            try:
+                os.remove(ffile)
+            except:
+                raise tvdb_error("Couldn't remove %s" % ffile)
 
 class ShowContainer(dict):
     """Simple dict that holds a series of Show instances
@@ -309,7 +310,7 @@ class Tvdb:
                 select_first = False,
                 debug = False,
                 cache = True,
-		cache_dir = False,
+                cache_dir = False,
                 banners = False,
                 actors = False,
                 custom_ui = None,
@@ -336,11 +337,11 @@ class Tvdb:
         cache (True/False/Recache):
             Retrieved XML are persisted to to disc. If true, stores in tvdb_api
             folder under directory specified by cache_dir.  If False, disables
-	    caching entirely.  If Refresh, requests a fresh copy and caches it
-	    for further use.
+            caching entirely.  If Refresh, requests a fresh copy and caches it
+            for further use.
 
-	cache_dir (str/unicode):
-	    Location for the cache directory, defaults to systems TEMP_DIR.
+        cache_dir (str/unicode):
+            Location for the cache directory, defaults to systems TEMP_DIR.
 
         banners (True/False):
             Retrieves the banners for a show. These are accessed
@@ -416,20 +417,20 @@ class Tvdb:
 
         self.config['search_all_languages'] = search_all_languages
 
-	if cache_dir:
-	    self.config['cache_location'] = cache_dir
-	else:
+        if cache_dir:
+            self.config['cache_location'] = cache_dir
+        else:
             self.config['cache_location'] = self._getTempDir()
 
-	if cache:
-	    self.config['cache_enabled'] = cache
-	else:
+        if cache:
+            self.config['cache_enabled'] = cache
+        else:
             self.config['cache_enabled'] = False
 
-	# Clean cache, this might need to be moved elsewhere
-	if self.config['cache_enabled'] and self.config['cache_location']:
-	    # log().debug("Cleaning cache %s " % self.config['cache_location'])
-	    clean_cache(self.config['cache_location'])
+        # Clean cache, this might need to be moved elsewhere
+        if self.config['cache_enabled'] and self.config['cache_location']:
+            # log().debug("Cleaning cache %s " % self.config['cache_location'])
+            clean_cache(self.config['cache_location'])
 
         self.config['banners_enabled'] = banners
         self.config['actors_enabled'] = actors
@@ -496,11 +497,11 @@ class Tvdb:
 
     def _loadUrl(self, url, recache = False):
         global lastTimeout
-	# Do we want caching?
-	if self.config['cache_enabled'] and self.config['cache_location']:
-	    h_cache = self.config['cache_location']
-	else:
-	    h_cache = False
+        # Do we want caching?
+        if self.config['cache_enabled'] and self.config['cache_location']:
+            h_cache = self.config['cache_location']
+        else:
+            h_cache = False
 
         if self.config['http_proxy'] != '' and self.config['http_proxy'] != None and socks != None:
             parsedURI = socks.parseproxyuri(self.config['http_proxy'])
@@ -508,12 +509,12 @@ class Tvdb:
         else:
             h = httplib2.Http(cache=h_cache)
 
-	# Handle a recache request, this will get fresh content and cache again
-	# if enabled
-	if str(self.config['cache_enabled']).lower() == 'recache' or recache:
-	    h_header = {'cache-control':'no-cache'}
-	else:
-	    h_header = {}
+        # Handle a recache request, this will get fresh content and cache again
+        # if enabled
+        if str(self.config['cache_enabled']).lower() == 'recache' or recache:
+            h_header = {'cache-control':'no-cache'}
+        else:
+            h_header = {}
 
         try:
             log().debug("Retrieving URL %s" % url)
@@ -522,10 +523,10 @@ class Tvdb:
             if not str(errormsg).startswith('HTTP Error'):
                 lastTimeout = datetime.datetime.now()
             raise tvdb_error("Could not connect to server %s: %s" % (url, errormsg))
-	except (AttributeError), errormsg:
-	    raise tvdb_error("Silly upstream module timed out and didn't give a \
-	    good error.  Failed hitting %s, error message: %s" % (url,
-		str(errormsg)))
+        except (AttributeError), errormsg:
+            raise tvdb_error("Silly upstream module timed out and didn't give a \
+            good error.  Failed hitting %s, error message: %s" % (url,
+                str(errormsg)))
         #end try
         
         return str(resp)
diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py
index 3266451cb4a5ecc14443f5ff331359c9761215e5..930c36b0f6928a3e06df6ec7867638803b235f3d 100644
--- a/sickbeard/__init__.py
+++ b/sickbeard/__init__.py
@@ -30,7 +30,7 @@ from threading import Lock
 
 # apparently py2exe won't build these unless they're imported somewhere
 from sickbeard import providers, metadata
-from providers import ezrss, nzbs_org, nzbmatrix, tvbinz, nzbsrus, newznab, womble, newzbin
+from providers import ezrss, tvtorrents, nzbs_org, nzbmatrix, tvbinz, nzbsrus, newznab, womble, newzbin
 
 from sickbeard import searchCurrent, searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser
 from sickbeard import helpers, db, exceptions, show_queue, search_queue, scheduler
@@ -38,7 +38,7 @@ from sickbeard import logger
 
 from sickbeard.common import *
 
-from sickbeard.databases import mainDB
+from sickbeard.databases import mainDB, cache_db
 
 from lib.configobj import ConfigObj
 
@@ -51,7 +51,7 @@ PID = None
 CFG = None
 CONFIG_FILE = None
 
-PROG_DIR = None
+PROG_DIR = '.'
 MY_FULLNAME = None
 MY_NAME = None
 MY_ARGS = []
@@ -81,6 +81,7 @@ VERSION_NOTIFY = None
 
 INIT_LOCK = Lock()
 __INITIALIZED__ = False
+started = False
 
 LOG_DIR = None
 
@@ -122,6 +123,9 @@ TVDB_API_KEY = '9DAF49C96CBF8DAC'
 TVDB_BASE_URL = None
 TVDB_API_PARMS = {}
 
+USE_NZBS = None
+USE_TORRENTS = None
+
 NZB_METHOD = None
 NZB_DIR = None
 USENET_RETENTION = None
@@ -135,6 +139,11 @@ MIN_SEARCH_FREQUENCY = 10
 DEFAULT_SEARCH_FREQUENCY = 60
 
 EZRSS = False
+TVTORRENTS = False
+TVTORRENTS_DIGEST = None
+TVTORRENTS_HASH = None
+
+
 TORRENT_DIR = None
 
 RENAME_EPISODES = False
@@ -173,6 +182,10 @@ SAB_APIKEY = None
 SAB_CATEGORY = None
 SAB_HOST = None
 
+NZBGET_PASSWORD = None
+NZBGET_CATEGORY = None
+NZBGET_HOST = None
+
 USE_XBMC = False
 XBMC_NOTIFY_ONSNATCH = False
 XBMC_NOTIFY_ONDOWNLOAD = False
@@ -182,6 +195,15 @@ XBMC_HOST = None
 XBMC_USERNAME = None
 XBMC_PASSWORD = None
 
+USE_PLEX = False
+PLEX_NOTIFY_ONSNATCH = False
+PLEX_NOTIFY_ONDOWNLOAD = False
+PLEX_UPDATE_LIBRARY = False
+PLEX_SERVER_HOST = None
+PLEX_HOST = None
+PLEX_USERNAME = None
+PLEX_PASSWORD = None
+
 USE_GROWL = False
 GROWL_NOTIFY_ONSNATCH = False
 GROWL_NOTIFY_ONDOWNLOAD = False
@@ -212,6 +234,11 @@ USE_LIBNOTIFY = False
 LIBNOTIFY_NOTIFY_ONSNATCH = False
 LIBNOTIFY_NOTIFY_ONDOWNLOAD = False
 
+USE_NMJ = False
+NMJ_HOST = None
+NMJ_DATABASE = None
+NMJ_MOUNT = None
+
 
 COMING_EPS_LAYOUT = None
 COMING_EPS_DISPLAY_PAUSED = None
@@ -311,15 +338,18 @@ def initialize(consoleLogging=True):
     with INIT_LOCK:
 
         global LOG_DIR, WEB_PORT, WEB_LOG, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, \
-                NZB_METHOD, NZB_DIR, TVBINZ, TVBINZ_UID, TVBINZ_HASH, DOWNLOAD_PROPERS, \
+                USE_NZBS, USE_TORRENTS, NZB_METHOD, NZB_DIR, TVBINZ, TVBINZ_UID, TVBINZ_HASH, DOWNLOAD_PROPERS, \
                 SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_HOST, \
-                XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, XBMC_UPDATE_FULL, \
-                XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, currentSearchScheduler, backlogSearchScheduler, \
+                NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_HOST, currentSearchScheduler, backlogSearchScheduler, \
+                USE_XBMC, XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, XBMC_UPDATE_FULL, \
+                XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, \
+                USE_PLEX, PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_UPDATE_LIBRARY, \
+                PLEX_SERVER_HOST, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, \
                 showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, showList, loadingShowList, \
-                NZBS, NZBS_UID, NZBS_HASH, EZRSS, TORRENT_DIR, USENET_RETENTION, SOCKET_TIMEOUT, \
+                NZBS, NZBS_UID, NZBS_HASH, EZRSS, TVTORRENTS, TVTORRENTS_DIGEST, TVTORRENTS_HASH, TORRENT_DIR, USENET_RETENTION, SOCKET_TIMEOUT, \
                 SEARCH_FREQUENCY, DEFAULT_SEARCH_FREQUENCY, BACKLOG_SEARCH_FREQUENCY, \
                 QUALITY_DEFAULT, SEASON_FOLDERS_FORMAT, SEASON_FOLDERS_DEFAULT, STATUS_DEFAULT, \
-                USE_XBMC, GROWL_NOTIFY_ONSNATCH, GROWL_NOTIFY_ONDOWNLOAD, TWITTER_NOTIFY_ONSNATCH, TWITTER_NOTIFY_ONDOWNLOAD, \
+                GROWL_NOTIFY_ONSNATCH, GROWL_NOTIFY_ONDOWNLOAD, TWITTER_NOTIFY_ONSNATCH, TWITTER_NOTIFY_ONDOWNLOAD, \
                 USE_GROWL, GROWL_HOST, GROWL_PASSWORD, USE_PROWL, PROWL_NOTIFY_ONSNATCH, PROWL_NOTIFY_ONDOWNLOAD, PROWL_API, PROWL_PRIORITY, PROG_DIR, NZBMATRIX, NZBMATRIX_USERNAME, \
                 NZBMATRIX_APIKEY, versionCheckScheduler, VERSION_NOTIFY, PROCESS_AUTOMATICALLY, \
                 KEEP_PROCESSED_DIR, TV_DOWNLOAD_DIR, TVDB_BASE_URL, MIN_SEARCH_FREQUENCY, \
@@ -330,7 +360,7 @@ def initialize(consoleLogging=True):
                 NZBSRUS, NZBSRUS_UID, NZBSRUS_HASH, NAMING_QUALITY, providerList, newznabProviderList, \
                 NAMING_DATES, EXTRA_SCRIPTS, USE_TWITTER, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, \
                 USE_NOTIFO, NOTIFO_USERNAME, NOTIFO_APISECRET, NOTIFO_NOTIFY_ONDOWNLOAD, NOTIFO_NOTIFY_ONSNATCH, \
-                USE_LIBNOTIFY, LIBNOTIFY_NOTIFY_ONSNATCH, LIBNOTIFY_NOTIFY_ONDOWNLOAD, \
+                USE_LIBNOTIFY, LIBNOTIFY_NOTIFY_ONSNATCH, LIBNOTIFY_NOTIFY_ONDOWNLOAD, USE_NMJ, NMJ_HOST, NMJ_DATABASE, NMJ_MOUNT, \
                 USE_BANNER, USE_LISTVIEW, METADATA_XBMC, METADATA_MEDIABROWSER, METADATA_PS3, metadata_provider_dict, \
                 NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, GIT_PATH, MOVE_ASSOCIATED_FILES, \
                 COMING_EPS_LAYOUT, COMING_EPS_SORT, COMING_EPS_DISPLAY_PAUSED, METADATA_WDTV
@@ -345,10 +375,13 @@ def initialize(consoleLogging=True):
         CheckSection('Newzbin')
         CheckSection('TVBinz')
         CheckSection('SABnzbd')
+        CheckSection('NZBget')
         CheckSection('XBMC')
+        CheckSection('PLEX')
         CheckSection('Growl')
         CheckSection('Prowl')
         CheckSection('Twitter')
+        CheckSection('NMJ')
 
         LOG_DIR = check_setting_str(CFG, 'General', 'log_dir', 'Logs')
         if not helpers.makeDir(LOG_DIR):
@@ -418,8 +451,11 @@ def initialize(consoleLogging=True):
 
         TVDB_BASE_URL = 'http://www.thetvdb.com/api/' + TVDB_API_KEY
 
+        USE_NZBS = bool(check_setting_int(CFG, 'General', 'use_nzbs', 1))
+        USE_TORRENTS = bool(check_setting_int(CFG, 'General', 'use_torrents', 0))
+
         NZB_METHOD = check_setting_str(CFG, 'General', 'nzb_method', 'blackhole')
-        if NZB_METHOD not in ('blackhole', 'sabnzbd'):
+        if NZB_METHOD not in ('blackhole', 'sabnzbd', 'nzbget'):
             NZB_METHOD = 'blackhole'
 
         DOWNLOAD_PROPERS = bool(check_setting_int(CFG, 'General', 'download_propers', 1))
@@ -442,6 +478,10 @@ def initialize(consoleLogging=True):
         EZRSS = bool(check_setting_int(CFG, 'General', 'use_torrent', 0))
         if not EZRSS:
             EZRSS = bool(check_setting_int(CFG, 'EZRSS', 'ezrss', 0))
+            
+        TVTORRENTS = bool(check_setting_int(CFG, 'TVTORRENTS', 'tvtorrents', 0))    
+        TVTORRENTS_DIGEST = check_setting_str(CFG, 'TVTORRENTS', 'tvtorrents_digest', '')
+        TVTORRENTS_HASH = check_setting_str(CFG, 'TVTORRENTS', 'tvtorrents_hash', '')
 
         TVBINZ = bool(check_setting_int(CFG, 'TVBinz', 'tvbinz', 0))
         TVBINZ_UID = check_setting_str(CFG, 'TVBinz', 'tvbinz_uid', '')
@@ -472,6 +512,10 @@ def initialize(consoleLogging=True):
         SAB_CATEGORY = check_setting_str(CFG, 'SABnzbd', 'sab_category', 'tv')
         SAB_HOST = check_setting_str(CFG, 'SABnzbd', 'sab_host', '')
 
+        NZBGET_PASSWORD = check_setting_str(CFG, 'NZBget', 'nzbget_password', 'tegbzn6789')
+        NZBGET_CATEGORY = check_setting_str(CFG, 'NZBget', 'nzbget_category', 'tv')
+        NZBGET_HOST = check_setting_str(CFG, 'NZBget', 'nzbget_host', '')
+
         USE_XBMC = bool(check_setting_int(CFG, 'XBMC', 'use_xbmc', 0)) 
         XBMC_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify_onsnatch', 0))
         XBMC_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify_ondownload', 0))
@@ -481,6 +525,15 @@ def initialize(consoleLogging=True):
         XBMC_USERNAME = check_setting_str(CFG, 'XBMC', 'xbmc_username', '')
         XBMC_PASSWORD = check_setting_str(CFG, 'XBMC', 'xbmc_password', '')
 
+        USE_PLEX = bool(check_setting_int(CFG, 'Plex', 'use_plex', 0))
+        PLEX_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Plex', 'plex_notify_onsnatch', 0))
+        PLEX_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Plex', 'plex_notify_ondownload', 0))
+        PLEX_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'Plex', 'plex_update_library', 0))
+        PLEX_SERVER_HOST = check_setting_str(CFG, 'Plex', 'plex_server_host', '')
+        PLEX_HOST = check_setting_str(CFG, 'Plex', 'plex_host', '')
+        PLEX_USERNAME = check_setting_str(CFG, 'Plex', 'plex_username', '')
+        PLEX_PASSWORD = check_setting_str(CFG, 'Plex', 'plex_password', '')
+
         USE_GROWL = bool(check_setting_int(CFG, 'Growl', 'use_growl', 0))
         GROWL_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Growl', 'growl_notify_onsnatch', 0))
         GROWL_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Growl', 'growl_notify_ondownload', 0))
@@ -510,6 +563,12 @@ def initialize(consoleLogging=True):
         LIBNOTIFY_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Libnotify', 'libnotify_notify_onsnatch', 0))
         LIBNOTIFY_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Libnotify', 'libnotify_notify_ondownload', 0))
 
+        USE_NMJ = bool(check_setting_int(CFG, 'NMJ', 'use_nmj', 0))
+        NMJ_HOST = check_setting_str(CFG, 'NMJ', 'nmj_host', '')
+        NMJ_DATABASE = check_setting_str(CFG, 'NMJ', 'nmj_database', '')
+        NMJ_MOUNT = check_setting_str(CFG, 'NMJ', 'nmj_mount', '')
+
+
         GIT_PATH = check_setting_str(CFG, 'General', 'git_path', '')
 
         EXTRA_SCRIPTS = [x for x in check_setting_str(CFG, 'General', 'extra_scripts', '').split('|') if x]
@@ -583,6 +642,9 @@ def initialize(consoleLogging=True):
         # initialize the main SB database
         db.upgradeDatabase(db.DBConnection(), mainDB.InitialSchema)
         
+        # initialize the cache database
+        db.upgradeDatabase(db.DBConnection("cache.db"), cache_db.InitialSchema)
+        
         # fix up any db problems
         db.sanityCheckDatabase(db.DBConnection(), mainDB.MainSanityCheck)
 
@@ -641,7 +703,8 @@ def start():
 
     global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, \
             showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
-            properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler
+            properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
+            started
 
     with INIT_LOCK:
 
@@ -670,11 +733,14 @@ def start():
 
             # start the proper finder
             autoPostProcesserScheduler.thread.start()
+            
+            started = True
 
 def halt ():
 
     global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, showUpdateScheduler, \
-            showQueueScheduler, properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler
+            showQueueScheduler, properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
+            started
 
     with INIT_LOCK:
 
@@ -766,13 +832,17 @@ def saveAll():
 
 def saveAndShutdown(restart=False):
 
-    logger.log(u"Killing cherrypy")
-    cherrypy.engine.exit()
-
     halt()
 
     saveAll()
 
+    logger.log(u"Killing cherrypy")
+    cherrypy.engine.exit()
+
+    if sickbeard.CREATEPID:
+        logger.log(u"Removing pidfile " + str(sickbeard.PIDFILE))
+        os.remove(sickbeard.PIDFILE)
+
     if restart:
         install_type = sickbeard.versionCheckScheduler.action.install_type
 
@@ -838,6 +908,8 @@ def save_config():
     new_config['General']['web_root'] = WEB_ROOT
     new_config['General']['web_username'] = WEB_USERNAME
     new_config['General']['web_password'] = WEB_PASSWORD
+    new_config['General']['use_nzbs'] = int(USE_NZBS)
+    new_config['General']['use_torrents'] = int(USE_TORRENTS)
     new_config['General']['nzb_method'] = NZB_METHOD
     new_config['General']['usenet_retention'] = int(USENET_RETENTION)
     new_config['General']['search_frequency'] = int(SEARCH_FREQUENCY)
@@ -882,6 +954,11 @@ def save_config():
 
     new_config['EZRSS'] = {}
     new_config['EZRSS']['ezrss'] = int(EZRSS)
+    
+    new_config['TVTORRENTS'] = {}
+    new_config['TVTORRENTS']['tvtorrents'] = int(TVTORRENTS)
+    new_config['TVTORRENTS']['tvtorrents_digest'] = TVTORRENTS_DIGEST
+    new_config['TVTORRENTS']['tvtorrents_hash'] = TVTORRENTS_HASH
 
     new_config['TVBinz'] = {}
     new_config['TVBinz']['tvbinz'] = int(TVBINZ)
@@ -919,8 +996,13 @@ def save_config():
     new_config['SABnzbd']['sab_category'] = SAB_CATEGORY
     new_config['SABnzbd']['sab_host'] = SAB_HOST
 
+    new_config['NZBget'] = {}
+    new_config['NZBget']['nzbget_password'] = NZBGET_PASSWORD
+    new_config['NZBget']['nzbget_category'] = NZBGET_CATEGORY
+    new_config['NZBget']['nzbget_host'] = NZBGET_HOST
+
     new_config['XBMC'] = {}
-    new_config['XBMC']['use_xbmc'] = int(USE_XBMC)    
+    new_config['XBMC']['use_xbmc'] = int(USE_XBMC)
     new_config['XBMC']['xbmc_notify_onsnatch'] = int(XBMC_NOTIFY_ONSNATCH)
     new_config['XBMC']['xbmc_notify_ondownload'] = int(XBMC_NOTIFY_ONDOWNLOAD)
     new_config['XBMC']['xbmc_update_library'] = int(XBMC_UPDATE_LIBRARY)
@@ -928,6 +1010,16 @@ def save_config():
     new_config['XBMC']['xbmc_host'] = XBMC_HOST
     new_config['XBMC']['xbmc_username'] = XBMC_USERNAME
     new_config['XBMC']['xbmc_password'] = XBMC_PASSWORD
+
+    new_config['Plex'] = {}
+    new_config['Plex']['use_plex'] = int(USE_PLEX)
+    new_config['Plex']['plex_notify_onsnatch'] = int(PLEX_NOTIFY_ONSNATCH)
+    new_config['Plex']['plex_notify_ondownload'] = int(PLEX_NOTIFY_ONDOWNLOAD)
+    new_config['Plex']['plex_update_library'] = int(PLEX_UPDATE_LIBRARY)
+    new_config['Plex']['plex_server_host'] = PLEX_SERVER_HOST
+    new_config['Plex']['plex_host'] = PLEX_HOST
+    new_config['Plex']['plex_username'] = PLEX_USERNAME
+    new_config['Plex']['plex_password'] = PLEX_PASSWORD
 
     new_config['Growl'] = {}
     new_config['Growl']['use_growl'] = int(USE_GROWL)
@@ -963,6 +1055,12 @@ def save_config():
     new_config['Libnotify']['libnotify_notify_onsnatch'] = int(LIBNOTIFY_NOTIFY_ONSNATCH)
     new_config['Libnotify']['libnotify_notify_ondownload'] = int(LIBNOTIFY_NOTIFY_ONDOWNLOAD)
 
+    new_config['NMJ'] = {}
+    new_config['NMJ']['use_nmj'] = int(USE_NMJ)
+    new_config['NMJ']['nmj_host'] = NMJ_HOST
+    new_config['NMJ']['nmj_database'] = NMJ_DATABASE
+    new_config['NMJ']['nmj_mount'] = NMJ_MOUNT
+
     new_config['Newznab'] = {}
     new_config['Newznab']['newznab_data'] = '!!!'.join([x.configStr() for x in newznabProviderList])
 
diff --git a/sickbeard/browser.py b/sickbeard/browser.py
index 783afa13c74fe3da2895357f96516a952efc0a45..69f89e4e13383ea9a27b3eb20b8095ce6955ab8b 100644
--- a/sickbeard/browser.py
+++ b/sickbeard/browser.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import os
 import glob
 import string
diff --git a/sickbeard/classes.py b/sickbeard/classes.py
index a97b2dd7ca1b779d2dd9a0fd32b0e84f88844dc6..3c2cf32acf699003d3896463e287c333727ba2ae 100644
--- a/sickbeard/classes.py
+++ b/sickbeard/classes.py
@@ -31,32 +31,64 @@ class SickBeardURLopener(urllib.FancyURLopener):
     version = USER_AGENT
 
 class AuthURLOpener(SickBeardURLopener):
+    """
+    URLOpener class that supports http auth without needing interactive password entry.
+    If the provided username/password don't work it simply fails.
+    
+    user: username to use for HTTP auth
+    pw: password to use for HTTP auth
+    """
     def __init__(self, user, pw):
         self.username = user
         self.password = pw
+
+        # remember if we've tried the username/password before
         self.numTries = 0
+        
+        # call the base class
         urllib.FancyURLopener.__init__(self)
 
     def prompt_user_passwd(self, host, realm):
+        """
+        Override this function and instead of prompting just give the
+        username/password that were provided when the class was instantiated.
+        """
+
+        # if this is the first try then provide a username/password
         if self.numTries == 0:
             self.numTries = 1
             return (self.username, self.password)
+        
+        # if we've tried before then return blank which cancels the request
         else:
             return ('', '')
 
+    # this is pretty much just a hack for convenience
     def openit(self, url):
         self.numTries = 0
         return SickBeardURLopener.open(self, url)
 
 class SearchResult:
+    """
+    Represents a search result from an indexer.
+    """
 
     def __init__(self, episodes):
         self.provider = -1
+
+        # URL to the NZB/torrent file
         self.url = ""
+
+        # used by some providers to store extra info associated with the result
         self.extraInfo = []
+
+        # list of TVEpisode objects that this result is associated with
         self.episodes = episodes
-        self.predownloaded = False
+
+        # quality of the release
         self.quality = -1
+
+        # release name
         self.name = ""
 
     def __str__(self):
@@ -74,16 +106,30 @@ class SearchResult:
         return self.episodes[0].prettyName(True) + "." + self.resultType
 
 class NZBSearchResult(SearchResult):
+    """
+    Regular NZB result with an URL to the NZB
+    """
     resultType = "nzb"
 
 class NZBDataSearchResult(SearchResult):
+    """
+    NZB result where the actual NZB XML data is stored in the extraInfo
+    """
     resultType = "nzbdata"
 
 class TorrentSearchResult(SearchResult):
+    """
+    Torrent result with an URL to the torrent
+    """
     resultType = "torrent"
 
 
 class ShowListUI:
+    """
+    This class is for tvdb-api. Instead of prompting with a UI to pick the
+    desired result out of a list of shows it tries to be smart about it
+    based on what shows are in SB. 
+    """
     def __init__(self, config, log=None):
         self.config = config
         self.log = log
@@ -116,6 +162,10 @@ class Proper:
 
 
 class ErrorViewer():
+    """
+    Keeps a static list of UIErrors to be displayed on the UI and allows
+    the list to be cleared.
+    """
 
     errors = []
 
@@ -131,6 +181,9 @@ class ErrorViewer():
         ErrorViewer.errors = []
 
 class UIError():
+    """
+    Represents an error to be displayed in the web UI.
+    """
     def __init__(self, message):
         self.message = message
         self.time = datetime.datetime.now()
diff --git a/sickbeard/common.py b/sickbeard/common.py
index 57beeaaedd0492101a697c1ec816e9fd4e9b2a59..9692dadd78cbaeae361505294a77352807d32660 100644
--- a/sickbeard/common.py
+++ b/sickbeard/common.py
@@ -28,7 +28,8 @@ USER_AGENT = 'Sick Beard/alpha2-'+version.SICKBEARD_VERSION.replace(' ','-')+' (
 mediaExtensions = ['avi', 'mkv', 'mpg', 'mpeg', 'wmv',
                    'ogm', 'mp4', 'iso', 'img', 'divx',
                    'm2ts', 'm4v', 'ts', 'flv', 'f4v',
-                   'mov', 'rmvb', 'vob']
+                   'mov', 'rmvb', 'vob', 'dvr-ms', 'wtv',
+                   ]
 
 ### Other constants
 MULTI_EP_RESULT = -1
@@ -236,64 +237,8 @@ XML_NSMAP = {'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
              'xsd': 'http://www.w3.org/2001/XMLSchema'}
 
 
-
-#####################################################################
-###
-###  DO NOT EDIT THIS MANUALLY! If you find a show that isn't
-###  being found please submit a ticket on google code so that
-###  I can fix the problem for everybody:
-###  http://code.google.com/p/sickbeard/issues/entry
-###
-#####################################################################
-
-sceneExceptions = {72546: ['CSI'],
-                   73696: ['CSI: New York'],
-                   110381: ['Archer'],
-                   83897: ['Life After People: The Series'],
-                   80552: ['Kitchen Nightmares (US)'],
-                   71256: ['The Daily Show'],
-                   75692: ['Law & Order: SVU'],
-                   71489: ['Law & Order: Criminal Intent', 'Law & Order: CI'],
-                   79590: ['Dancing With The Stars (US)'],
-                   73387: ['Craig Ferguson'],
-                   85355: ['Jimmy Fallon'],
-                   75088: ['David Letterman'],
-                   76706: ['Big Brother (US)'],
-                   105521: ['The Colony', 'The Colony (US)'],
-                   76235: ['America\'s Funniest Home Videos', 'AFHV'],
-                   139941: ['Childrens Hospital (US)', 'Childrens Hospital'],
-                   83123: ['Merlin', 'Merlin (2008)'],
-                   76779: ['WWE Monday Night RAW'],
-                   164951: ['Shit My Dad Says'],
-                   83714: ['Genius with Dave Gorman'],
-                   168161: ['Law & Order: Los Angeles', 'Law & Order: LA'],
-                   77526: ['Star Trek: TOS'],
-                   72194: ['The Ellen Degeneres Show', 'Ellen Degeneres'],
-                   72073: ['Star Trek DS9'],
-                   195831: ['Zane Lamprey\'s Drinking Made Easy'],
-                   76133: ['Poirot', 'Agatha Christie\'s Poirot'],
-                   70870: ['The Real World Road Rules Challenge', 'The Challenge Cutthroat'],
-                   77444: ['This Old House Program'],
-                   73290: ['60 Minutes (US)'],
-                   194751: ['Conan', 'Conan (2010)'],
-                   164451: ['Carlos (2010)'],
-                   70726: ['Babylon 5', 'Babylon5'],
-                   83714: ['Genius', 'Genius With Dave Gormand'],
-                   212571: ['Come Fly With Me (2010)'],
-                   81563: ['Border Security', 'Border Security Australia\'s Frontline'],
-                   172381: ['Silent Library (US)'],
-                   131791: ['Sci-Fi Science'],
-                   80646: ['Frontline (US)', 'Frontline'],
-                   189931: ['RBT (AU)'],
-                   73255: ['House', 'House M D'],
-                   73244: ['The Office (US)', 'The Office'],
-                   81386: ['Being Human', 'Being Human (UK)'],
-                   89991: ['Out of the Wild: The Alaskan Experiment', 'Out of the Wild: Venezuela'],
-                   222551: ['Only in America With Larry the Cable Guy', 'Only in America'],
-                   77733: ['Degrassi: The Next Generation', 'Degrassi TNG'],
-                   }
-
 countryList = {'Australia': 'AU',
                'Canada': 'CA',
                'USA': 'US'
                }
+
diff --git a/sickbeard/databases/__init__.py b/sickbeard/databases/__init__.py
index 9666180624c2329afa8d4c80f0be996004f25ccb..3c75828d8f1dcedcef7055bde578f8afb29a5ea2 100644
--- a/sickbeard/databases/__init__.py
+++ b/sickbeard/databases/__init__.py
@@ -1 +1,19 @@
-__all__ = ["mainDB"]
\ No newline at end of file
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
+__all__ = ["mainDB", "cache"]
\ No newline at end of file
diff --git a/sickbeard/databases/cache_db.py b/sickbeard/databases/cache_db.py
new file mode 100644
index 0000000000000000000000000000000000000000..997b09bf2e8996bed71daa3a2e6871c140f56149
--- /dev/null
+++ b/sickbeard/databases/cache_db.py
@@ -0,0 +1,51 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
+from sickbeard import db
+
+# Add new migrations at the bottom of the list; subclass the previous migration.
+class InitialSchema (db.SchemaUpgrade):
+    def test(self):
+        return self.hasTable("lastUpdate")
+
+    def execute(self):
+
+        queries = [
+            ("CREATE TABLE lastUpdate (provider TEXT, time NUMERIC);",),
+            ("CREATE TABLE db_version (db_version INTEGER);",),
+            ("INSERT INTO db_version (db_version) VALUES (?)", 1),
+        ]
+        for query in queries:
+            if len(query) == 1:
+                self.connection.action(query[0])
+            else:
+                self.connection.action(query[0], query[1:])
+
+class AddSceneExceptions(InitialSchema):
+    def test(self):
+        return self.hasTable("scene_exceptions")
+
+    def execute(self):
+        self.connection.action("CREATE TABLE scene_exceptions (exception_id INTEGER PRIMARY KEY, tvdb_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 (tvdb_id INTEGER, name TEXT)")
\ No newline at end of file
diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py
index ca4d154e01e27f9ac67279cabc290edd631b1fbc..2acb6fe20b36a67115ed9627f56baf8430219166 100644
--- a/sickbeard/databases/mainDB.py
+++ b/sickbeard/databases/mainDB.py
@@ -1,10 +1,32 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import sickbeard
+import shutil, time, os.path, sys
+
 from sickbeard import db
 from sickbeard import common
 from sickbeard import logger
+from sickbeard.providers.generic import GenericProvider
 
 from sickbeard import encodingKludge as ek
-import shutil, time, os.path, sys
+
+
 
 class MainSanityCheck(db.DBSanityCheck):
 
@@ -156,8 +178,12 @@ class NewQualitySettings (NumericProviders):
 
         ### Update episode statuses
         toUpdate = self.connection.select("SELECT episode_id, location, status FROM tv_episodes WHERE status IN (?, ?, ?, ?, ?, ?, ?)", [common.DOWNLOADED, common.SNATCHED, PREDOWNLOADED, MISSED, BACKLOG, DISCBACKLOG, SNATCHED_BACKLOG])
+        didUpdate = False
         for curUpdate in toUpdate:
 
+            # remember that we changed something
+            didUpdate = True
+
             newStatus = None
             oldStatus = int(curUpdate["status"])
             if oldStatus == common.SNATCHED:
@@ -184,6 +210,10 @@ class NewQualitySettings (NumericProviders):
 
             self.connection.action("UPDATE tv_episodes SET status = ? WHERE episode_id = ?", [common.Quality.compositeStatus(common.DOWNLOADED, newQuality), curUpdate["episode_id"]])
 
+        # if no updates were done then the backup is useless
+        if didUpdate:
+            os.remove(ek.ek(os.path.join, sickbeard.PROG_DIR, 'sickbeard.db.v0'))
+
 
         ### Update show qualities
         toUpdate = self.connection.select("SELECT * FROM tv_shows")
@@ -322,8 +352,50 @@ class PopulateRootDirs (AddLang):
         
         sickbeard.ROOT_DIRS = new_root_dirs
         
+        sickbeard.save_config()
+        
+        self.incDBVersion()
+        
+
+class SetNzbTorrentSettings(PopulateRootDirs):
+
+    def test(self):
+        return self.checkDBVersion() >= 8
+    
+    def execute(self):
+
+        use_torrents = False
+        use_nzbs = False
+
+        for cur_provider in sickbeard.providers.sortedProviderList():
+            if cur_provider.isEnabled():
+                if cur_provider.providerType == GenericProvider.NZB:
+                    use_nzbs = True
+                    logger.log(u"Provider "+cur_provider.name+" is enabled, enabling NZBs in the upgrade")
+                    break
+                elif cur_provider.providerType == GenericProvider.TORRENT:
+                    use_torrents = True
+                    logger.log(u"Provider "+cur_provider.name+" is enabled, enabling Torrents in the upgrade")
+                    break
+
+        sickbeard.USE_TORRENTS = use_torrents
+        sickbeard.USE_NZBS = use_nzbs
+        
+        sickbeard.save_config()
+        
         self.incDBVersion()
+
+class FixAirByDateSetting(SetNzbTorrentSettings):
+    
+    def test(self):
+        return self.checkDBVersion() >= 9
+
+    def execute(self):
         
+        shows = self.connection.select("SELECT * FROM tv_shows")
         
+        for cur_show in shows:
+            if cur_show["genre"] and "talk show" in cur_show["genre"].lower():
+                self.connection.action("UPDATE tv_shows SET air_by_date = ? WHERE tvdb_id = ?", [1, cur_show["tvdb_id"]])
         
-        
\ No newline at end of file
+        self.incDBVersion()
\ No newline at end of file
diff --git a/sickbeard/encodingKludge.py b/sickbeard/encodingKludge.py
index 9debc5a09bad281fc3d5281c65277c064fdcc765..6b505808c3d12f2b6d891f44e684c40fd71503b5 100644
--- a/sickbeard/encodingKludge.py
+++ b/sickbeard/encodingKludge.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import os
 import os.path
 import locale
diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py
index bb4fcaadde6e69ff7d4275ffc31b732c461980ff..47cbc0ab5ad59f68646636bb61722168a9e7850d 100644
--- a/sickbeard/helpers.py
+++ b/sickbeard/helpers.py
@@ -84,6 +84,10 @@ def isMediaFile (file):
     if re.search('(^|[\W_])sample\d*[\W_]', file):
         return False
 
+    # ignore MAC OS's retarded "resource fork" files
+    if file.startswith('._'):
+        return False
+
     sepFile = file.rpartition(".")
     if sepFile[2].lower() in mediaExtensions:
         return True
@@ -307,11 +311,11 @@ def buildNFOXML(myShow):
 
 def searchDBForShow(regShowName):
 
-    showNames = [regShowName.replace(' ','_')]
+    showNames = [re.sub('[. -]', ' ', regShowName)]
 
     myDB = db.DBConnection()
 
-    yearRegex = "(.*?)\s*([(]?)(\d{4})(?(2)[)]?).*"
+    yearRegex = "([^()]+?)\s*(\()?(\d{4})(?(2)\))$"
 
     for showName in showNames:
 
@@ -324,7 +328,7 @@ def searchDBForShow(regShowName):
 
             # if we didn't get exactly one result then try again with the year stripped off if possible
             match = re.match(yearRegex, showName)
-            if match:
+            if match and match.group(1):
                 logger.log(u"Unable to match original name but trying to manually strip and specify show year", logger.DEBUG)
                 sqlResults = myDB.select("SELECT * FROM tv_shows WHERE (show_name LIKE ? OR tvr_name LIKE ?) AND startyear = ?", [match.group(1)+'%', match.group(1)+'%', match.group(3)])
 
@@ -386,6 +390,7 @@ def copyFile(srcFile, destFile):
 def moveFile(srcFile, destFile):
     try:
         ek.ek(os.rename, srcFile, destFile)
+        fixSetGroupID(destFile)
     except OSError:
         copyFile(srcFile, destFile)
         ek.ek(os.unlink, srcFile)
@@ -415,7 +420,7 @@ def chmodAsParent(childPath):
     parentMode = stat.S_IMODE(os.stat(parentPath)[stat.ST_MODE])
 
     if ek.ek(os.path.isfile, childPath):
-        childMode = readwriteBits(parentMode)
+        childMode = fileBitFilter(parentMode)
     else:
         childMode = parentMode
 
@@ -425,14 +430,61 @@ def chmodAsParent(childPath):
     except OSError:
         logger.log(u"Failed to set permission for %s to %o" % (childPath, childMode), logger.ERROR)
 
-def readwriteBits(currentMode):
-    newMode = 0
+def fileBitFilter(mode):
+    for bit in [stat.S_IXUSR, stat.S_IXGRP, stat.S_IXOTH, stat.S_ISUID, stat.S_ISGID]:
+        if mode & bit:
+            mode -= bit
+
+    return mode
+
+def fixSetGroupID(childPath):
+    if os.name == 'nt' or os.name == 'ce':
+        return
+
+    parentPath = ek.ek(os.path.dirname, childPath)
+    parentStat = os.stat(parentPath)
+    parentMode = stat.S_IMODE(parentStat[stat.ST_MODE])
+
+    if parentMode & stat.S_ISGID:
+        parentGID = parentStat[stat.ST_GID]
+        childGID = os.stat(childPath)[stat.ST_GID]
+
+        if childGID == parentGID:
+            return
+
+        try:
+            ek.ek(os.chown, childPath, -1, parentGID)
+            logger.log(u"Respecting the set-group-ID bit on the parent directory for %s" % (childPath), logger.DEBUG)
+        except OSError:
+            logger.log(u"Failed to respect the set-group-ID bit on the parent directory for %s (setting group ID %i)" % (childPath, parentGID), logger.ERROR)
+
+def sanitizeSceneName (name, ezrss=False):
+    """
+    Takes a show name and returns the "scenified" version of it.
+    
+    ezrss: If true the scenified version will follow EZRSS's cracksmoker rules as best as possible
+    
+    Returns: A string containing the scene version of the show name given.
+    """
 
-    for bit in [stat.S_IRUSR, stat.S_IWUSR, stat.S_IRGRP, stat.S_IWGRP, stat.S_IROTH, stat.S_IWOTH]:
-        if currentMode & bit:
-            newMode += bit
+    if not ezrss:
+        bad_chars = ",:()'!?"
+    # ezrss leaves : and ! in their show names as far as I can tell
+    else:
+        bad_chars = ",()'?"
 
-    return newMode
+    # strip out any bad chars
+    for x in bad_chars:
+        name = name.replace(x, "")
+
+    # tidy up stuff that doesn't belong in scene names
+    name = name.replace("- ", ".").replace(" ", ".").replace("&", "and").replace('/','.')
+    name = re.sub("\.\.*", ".", name)
+
+    if name.endswith('.'):
+        name = name[:-1]
+
+    return name
 
 
 if __name__ == '__main__':
diff --git a/sickbeard/history.py b/sickbeard/history.py
index c8e2bcfb44cbd7c317f67491528d88383c132e04..a2eb4ce97e9025421b4d5983d7dfe992cfd9e0f0 100644
--- a/sickbeard/history.py
+++ b/sickbeard/history.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import db
 import sqlite3
 import datetime
diff --git a/sickbeard/image_cache.py b/sickbeard/image_cache.py
index d80021d1a2c914c569a106745d80d593663e9fd2..4f9640235751b67b951edcc853dcd916361ba837 100644
--- a/sickbeard/image_cache.py
+++ b/sickbeard/image_cache.py
@@ -36,22 +36,45 @@ class ImageCache:
         pass
     
     def _cache_dir(self):
+        """
+        Builds up the full path to the image cache directory
+        """
         return ek.ek(os.path.abspath, ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images'))
 
     def poster_path(self, tvdb_id):
+        """
+        Builds up the path to a poster cache for a given tvdb id
+
+        returns: a full path to the cached poster file for the given tvdb id 
+        
+        tvdb_id: ID of the show to use in the file name
+        """
         poster_file_name = str(tvdb_id) + '.poster.jpg'
         return ek.ek(os.path.join, self._cache_dir(), poster_file_name)
     
     def banner_path(self, tvdb_id):
+        """
+        Builds up the path to a banner cache for a given tvdb id
+
+        returns: a full path to the cached banner file for the given tvdb id 
+        
+        tvdb_id: ID of the show to use in the file name
+        """
         banner_file_name = str(tvdb_id) + '.banner.jpg'
         return ek.ek(os.path.join, self._cache_dir(), banner_file_name)
 
     def has_poster(self, tvdb_id):
+        """
+        Returns true if a cached poster exists for the given tvdb id
+        """
         poster_path = self.poster_path(tvdb_id)
         logger.log(u"Checking if file "+str(poster_path)+" exists", logger.DEBUG)
         return ek.ek(os.path.isfile, poster_path)
 
     def has_banner(self, tvdb_id):
+        """
+        Returns true if a cached banner exists for the given tvdb id
+        """
         banner_path = self.banner_path(tvdb_id)
         logger.log(u"Checking if file "+str(banner_path)+" exists", logger.DEBUG)
         return ek.ek(os.path.isfile, banner_path)
@@ -60,9 +83,19 @@ class ImageCache:
     POSTER = 2
     
     def which_type(self, path):
+        """
+        Analyzes the image provided and attempts to determine whether it is a poster or banner.
+        
+        returns: BANNER, POSTER if it concluded one or the other, or None if the image was neither (or didn't exist)
+        
+        path: full path to the image
+        """
+
         if not ek.ek(os.path.isfile, path):
             logger.log(u"Couldn't check the type of "+str(path)+" cause it doesn't exist", logger.WARNING)
             return None
+
+        # use hachoir to parse the image for us
         img_parser = createParser(path)
         img_metadata = extractMetadata(img_parser)
 
@@ -74,8 +107,11 @@ class ImageCache:
 
         img_parser.stream._input.close()
 
+        # most posters are around 0.68 width/height ratio (eg. 680/1000)
         if 0.55 < img_ratio < 0.8:
             return self.POSTER
+        
+        # most banners are around 5.4 width/height ratio (eg. 758/140)
         elif 5 < img_ratio < 6:
             return self.BANNER
         else:
@@ -83,6 +119,17 @@ class ImageCache:
             return None
     
     def _cache_image_from_file(self, image_path, img_type, tvdb_id):
+        """
+        Takes the image provided and copies it to the cache folder
+        
+        returns: bool representing success
+        
+        image_path: path to the image we're caching
+        img_type: BANNER or POSTER
+        tvdb_id: id of the show this image belongs to
+        """
+
+        # generate the path based on the type & tvdb_id
         if img_type == self.POSTER:
             dest_path = self.poster_path(tvdb_id)
         elif img_type == self.BANNER:
@@ -91,6 +138,7 @@ class ImageCache:
             logger.log(u"Invalid cache image type: "+str(img_type), logger.ERROR)
             return False
 
+        # make sure the cache folder exists before we try copying to it
         if not ek.ek(os.path.isdir, self._cache_dir()):
             logger.log(u"Image cache dir didn't exist, creating it at "+str(self._cache_dir()))
             ek.ek(os.makedirs, self._cache_dir())
@@ -101,6 +149,16 @@ class ImageCache:
         return True
 
     def _cache_image_from_tvdb(self, show_obj, img_type):
+        """
+        Retrieves an image of the type specified from TVDB and saves it to the cache folder
+        
+        returns: bool representing success
+        
+        show_obj: TVShow object that we want to cache an image for
+        img_type: BANNER or POSTER
+        """
+
+        # generate the path based on the type & tvdb_id
         if img_type == self.POSTER:
             img_type_name = 'poster'
             dest_path = self.poster_path(show_obj.tvdbid)
@@ -111,6 +169,7 @@ class ImageCache:
             logger.log(u"Invalid cache image type: "+str(img_type), logger.ERROR)
             return False
 
+        # retrieve the image from TVDB using the generic metadata class
         #TODO: refactor
         metadata_generator = GenericMetadata()
         img_data = metadata_generator._retrieve_show_image(img_type_name, show_obj)
@@ -119,6 +178,12 @@ class ImageCache:
         return result
     
     def fill_cache(self, show_obj):
+        """
+        Caches all images for the given show. Copies them from the show dir if possible, or
+        downloads them from TVDB if they aren't in the show dir.
+        
+        show_obj: TVShow object to cache images for
+        """
 
         logger.log(u"Checking if we need any cache images for show "+str(show_obj.tvdbid), logger.DEBUG)
 
diff --git a/sickbeard/metadata/__init__.py b/sickbeard/metadata/__init__.py
index 4bd27b5d8fa1cd77ffd90667c40e1b29361d3adf..e66ead3242f8e881fde72b7979ce4da56cb9ad88 100644
--- a/sickbeard/metadata/__init__.py
+++ b/sickbeard/metadata/__init__.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 __all__ = ['generic', 'helpers', 'xbmc', 'mediabrowser', 'ps3', 'wdtv']
 
 import sys
diff --git a/sickbeard/name_cache.py b/sickbeard/name_cache.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0629f4ce226eeaa28ad992a94b790aa0cc913b0
--- /dev/null
+++ b/sickbeard/name_cache.py
@@ -0,0 +1,67 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
+from sickbeard import db
+from sickbeard.helpers import sanitizeSceneName
+
+from sickbeard import logger
+
+def addNameToCache(name, tvdb_id):
+    """
+    Adds the show & tvdb id to the scene_names table in cache.db.
+    
+    name: The show name to cache
+    tvdb_id: The tvdb id that this show should be cached with (can be None/0 for unknown)
+    """
+    
+    # standardize the name we're using to account for small differences in providers (aka NZBMatrix sucks)
+    name = sanitizeSceneName(name)
+    
+    if not tvdb_id:
+        tvdb_id = 0
+    
+    cacheDB = db.DBConnection('cache.db')
+    cacheDB.action("INSERT INTO scene_names (tvdb_id, name) VALUES (?, ?)", [tvdb_id, name])
+
+def retrieveNameFromCache(name):
+    """
+    Looks up the given name in the scene_names table in cache.db.
+    
+    name: The show name to look up.
+    
+    Returns: the tvdb id that resulted from the cache lookup or None if the show wasn't found in the cache
+    """
+    
+    # standardize the name we're using to account for small differences in providers (aka NZBMatrix sucks)
+    name = sanitizeSceneName(name)
+    
+    cacheDB = db.DBConnection('cache.db')
+    cache_results = cacheDB.select("SELECT * FROM scene_names WHERE name = ?", [name])
+
+    if not cache_results:
+        return None
+    
+    return int(cache_results[0]["tvdb_id"])
+
+def clearCache():
+    """
+    Deletes all "unknown" entries from the cache (names with tvdb_id of 0).
+    """
+    cacheDB = db.DBConnection('cache.db')
+    cacheDB.action("DELETE FROM scene_names WHERE tvdb_id = ?", [0])
+
diff --git a/sickbeard/name_parser/parser.py b/sickbeard/name_parser/parser.py
index 85122677ea7f8e95efc6762c3139ed16304f9f2b..dd8c31f5f79d73477702fb221adf7e5e4c8d025e 100644
--- a/sickbeard/name_parser/parser.py
+++ b/sickbeard/name_parser/parser.py
@@ -114,7 +114,12 @@ class NameParser(object):
                     raise InvalidNameException(str(e))
 
             if 'extra_info' in named_groups:
-                result.extra_info = match.group('extra_info')
+                tmp_extra_info = match.group('extra_info')
+                
+                # Show.S04.Special is almost certainly not every episode in the season
+                if tmp_extra_info and cur_regex_name == 'season_only' and re.match(r'([. _-]|^)(special|extra)\w*([. _-]|$)', tmp_extra_info, re.I):
+                    continue
+                result.extra_info = tmp_extra_info
             
             if 'release_group' in named_groups:
                 result.release_group = match.group('release_group')
diff --git a/sickbeard/notifiers/__init__.py b/sickbeard/notifiers/__init__.py
index d5adfb9aaa11933690496cc3534cab04fbb4b6e0..d2e8d4c60eef7bfbd7569848ae5573261cbed0dd 100644
--- a/sickbeard/notifiers/__init__.py
+++ b/sickbeard/notifiers/__init__.py
@@ -1,29 +1,53 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import sickbeard
 
-import xbmc
+import xbmc
+import plex
 import growl
 import prowl
 import tweet
 from . import libnotify
 import notifo
+import nmj
 
 from sickbeard.common import *
 
-xbmc_notifier = xbmc.XBMCNotifier()
+xbmc_notifier = xbmc.XBMCNotifier()
+plex_notifier = plex.PLEXNotifier()
 growl_notifier = growl.GrowlNotifier()
 prowl_notifier = prowl.ProwlNotifier()
 twitter_notifier = tweet.TwitterNotifier()
 notifo_notifier = notifo.NotifoNotifier()
 libnotify_notifier = libnotify.LibnotifyNotifier()
+nmj_notifier = nmj.NMJNotifier()
 
 notifiers = [
     # Libnotify notifier goes first because it doesn't involve blocking on
     # network activity.
     libnotify_notifier,
-    xbmc_notifier,
+    xbmc_notifier,
+    plex_notifier,
     growl_notifier,
     prowl_notifier,
     twitter_notifier,
+    nmj_notifier,
 ]
 
 def notify_download(ep_name):
@@ -35,20 +59,3 @@ def notify_snatch(ep_name):
     for n in notifiers:
         n.notify_snatch(ep_name)
     notifo_notifier.notify_snatch(ep_name)
-
-def notify(type, message):
-
-    if type == NOTIFY_DOWNLOAD and sickbeard.XBMC_NOTIFY_ONDOWNLOAD == True:
-            xbmc.notifyXBMC(message, notifyStrings[type])
-
-    if type == NOTIFY_SNATCH and sickbeard.XBMC_NOTIFY_ONSNATCH:
-            xbmc.notifyXBMC(message, notifyStrings[type])
-
-    growl.sendGrowl(notifyStrings[type], message)
-    
-    prowl.sendProwl(message)
-
-    notifo.notifyNotifo(message)
-
-    if type == NOTIFY_DOWNLOAD:
-        tweet.notifyTwitter(message)
diff --git a/sickbeard/notifiers/growl.py b/sickbeard/notifiers/growl.py
index 6c0b81fcbb2d25d3edb05395fbeac4bc19b1ef08..68f94edde83d7df98b2442eb235fe6a9d16c3823 100644
--- a/sickbeard/notifiers/growl.py
+++ b/sickbeard/notifiers/growl.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import socket
 import sys
 
diff --git a/sickbeard/notifiers/libnotify.py b/sickbeard/notifiers/libnotify.py
index 6f79eef597a6d3d4051c11b014c642ba1c19917e..13cda96abfb0cbd8dce730cac574045a7118a378 100644
--- a/sickbeard/notifiers/libnotify.py
+++ b/sickbeard/notifiers/libnotify.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import os
 import cgi
 import sickbeard
diff --git a/sickbeard/notifiers/nmj.py b/sickbeard/notifiers/nmj.py
new file mode 100644
index 0000000000000000000000000000000000000000..de074f048547feb3fe9dda939fe130852abb37ba
--- /dev/null
+++ b/sickbeard/notifiers/nmj.py
@@ -0,0 +1,142 @@
+# Author: Nico Berlee http://nico.berlee.nl/
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
+import urllib, urllib2
+import sickbeard
+import telnetlib
+import re
+
+from sickbeard import logger
+
+try:
+    import xml.etree.cElementTree as etree
+except ImportError:
+    import xml.etree.ElementTree as etree
+
+
+class NMJNotifier:
+    def notify_settings(self, host):
+        terminal = False
+        try:
+            terminal = telnetlib.Telnet(host)
+        except Exception:
+            logger.log(u"Warning: unable to get a telnet session to %s" % (host), logger.ERROR)
+            return False
+
+        logger.log(u"Connected to %s via telnet" % (host), logger.DEBUG)
+        terminal.read_until("sh-3.00# ")
+        terminal.write("cat /tmp/source\n")
+        terminal.write("cat /tmp/netshare\n")
+        terminal.write("exit\n")
+        tnoutput = terminal.read_all()
+
+        database = ""
+        device = ""
+        match = re.search(r"(.+\.db)\r\n?(.+)(?=sh-3.00# cat /tmp/netshare)", tnoutput)
+
+        if match:
+            database = match.group(1)
+            device = match.group(2)
+            logger.log(u"Found NMJ database %s on device %s" % (database, device), logger.DEBUG)
+            sickbeard.NMJ_DATABASE = database
+        else:
+            logger.log(u"Could not get current NMJ database on %s, NMJ is probably not running!" % (host), logger.ERROR)
+            return False
+            
+        if device.startswith("NETWORK_SHARE/"):
+            match = re.search(".*(?=\r\n?%s)" % (re.escape(device[14:])), tnoutput)
+
+            if match:
+                mount = match.group().replace("127.0.0.1", host)
+                logger.log(u"Found mounting url on the Popcorn Hour in configuration: %s" % (mount), logger.DEBUG)
+                sickbeard.NMJ_MOUNT = mount
+            else:
+                logger.log(u"Detected a network share on the Popcorn Hour, but could not get the mounting url", logger.DEBUG)
+                return False
+
+        return True
+    
+    def notify_snatch(self, ep_name):
+        return False
+        #Not implemented: Start the scanner when snatched does not make any sense
+
+    def notify_download(self, ep_name):
+        self._notifyNMJ()
+
+    def test_notify(self, host, database, mount):
+        return self._sendNMJ(host, database, mount)
+
+    def _sendNMJ(self, host, database, mount=None):
+        if mount:
+            try:
+                req = urllib2.Request(mount)
+                logger.log(u"Try to mount network drive via url: %s" % (mount), logger.DEBUG)
+                handle = urllib2.urlopen(req)
+            except IOError, e:
+                logger.log(u"Warning: Couldn't contact popcorn hour on host %s: %s" % (host, e))
+                return False
+
+        UPDATE_URL = "http://%(host)s:8008/metadata_database?%(params)s"
+        params = {
+            "arg0": "scanner_start",
+            "arg1": database,
+            "arg2": "background",
+            "arg3": ""}
+        params = urllib.urlencode(params)
+        updateUrl = UPDATE_URL % {"host": host, "params": params}
+
+        try:
+            req = urllib2.Request(updateUrl)
+            logger.log(u"Sending NMJ scan update command via url: %s" % (updateUrl), logger.DEBUG)
+            handle = urllib2.urlopen(req)
+            response = handle.read()
+        except IOError, e:
+            logger.log(u"Warning: Couldn't contact Popcorn Hour on host %s: %s" % (host, e))
+            return False
+
+        try:
+            et = etree.fromstring(response)
+            result = et.findtext("returnValue")
+        except SyntaxError, e:
+            logger.log(u"Unable to parse XML returned from the Popcorn Hour: %s" % (e), logger.ERROR)
+            return False
+        
+        if int(result) > 0:
+            logger.log(u"Popcorn Hour returned an errorcode: %s" % (result))
+            return False
+        else:
+            logger.log(u"NMJ started background scan")
+            return True
+
+    def _notifyNMJ(self, host=None, database=None, mount=None, force=False):
+        if not sickbeard.USE_NMJ and not force:
+            logger.log("Notification for NMJ scan update not enabled, skipping this notification", logger.DEBUG)
+            return False
+
+        if not host:
+            host = sickbeard.NMJ_HOST
+        if not database:
+            database = sickbeard.NMJ_DATABASE
+        if not mount:
+            mount = sickbeard.NMJ_MOUNT
+
+        logger.log(u"Sending scan command for NMJ ", logger.DEBUG)
+
+        return self._sendNMJ(host, database, mount)
+
+notifier = NMJNotifier
diff --git a/sickbeard/notifiers/notifo.py b/sickbeard/notifiers/notifo.py
index ca26cfbdb9547520b508e38d912c37a4ad0fd44b..24b904b639355906eae921f9e3f69f7fc181adb1 100644
--- a/sickbeard/notifiers/notifo.py
+++ b/sickbeard/notifiers/notifo.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import urllib
 import sickbeard
 
@@ -23,14 +41,13 @@ class NotifoNotifier:
             "msg": msg,
         })
 
-        data = urllib.urlopen(apiurl, data)
         try:
-            try:
-                result = json.load(data)
-            except IOError:
-                return False
-        finally:
-            data.close()
+	    data = urllib.urlopen(apiurl, data)	
+            result = json.load(data)
+        except IOError:
+            return False
+        
+        data.close()
 
         if result["status"] != "success" or result["response_message"] != "OK":
             return False
diff --git a/sickbeard/notifiers/plex.py b/sickbeard/notifiers/plex.py
new file mode 100644
index 0000000000000000000000000000000000000000..1401d45460a464f01a851c2b69d2a57000b552ad
--- /dev/null
+++ b/sickbeard/notifiers/plex.py
@@ -0,0 +1,85 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
+import urllib
+import sickbeard
+
+from xml.dom import minidom
+from sickbeard import logger, common
+from sickbeard.notifiers.xbmc import XBMCNotifier 
+
+class PLEXNotifier(XBMCNotifier):
+
+    def notify_snatch(self, ep_name):
+        if sickbeard.PLEX_NOTIFY_ONSNATCH:
+            self._notifyXBMC(ep_name, common.notifyStrings[common.NOTIFY_SNATCH])
+
+    def notify_download(self, ep_name):
+        if sickbeard.PLEX_NOTIFY_ONDOWNLOAD:
+            self._notifyXBMC(ep_name, common.notifyStrings[common.NOTIFY_DOWNLOAD])
+
+    def test_notify(self, host, username, password):
+        return self._notifyXBMC("Testing Plex notifications from Sick Beard", "Test Notification", host, username, password, force=True)
+
+    def update_library(self):
+        if sickbeard.PLEX_UPDATE_LIBRARY:
+            self._update_library()
+
+    def _username(self):
+        return sickbeard.PLEX_USERNAME
+
+    def _password(self):
+        return sickbeard.PLEX_PASSWORD
+
+    def _use_me(self):
+        return sickbeard.USE_PLEX
+
+    def _hostname(self):
+        return sickbeard.PLEX_HOST
+
+
+    def _update_library(self):
+        if not sickbeard.USE_PLEX:
+            logger.log(u"Notifications for Plex Media Server not enabled, skipping library update", logger.DEBUG)
+            return False
+
+        logger.log(u"Updating Plex Media Server library", logger.DEBUG)
+
+        if not sickbeard.PLEX_SERVER_HOST:
+            logger.log(u"No host specified, no updates done", logger.DEBUG)
+            return False
+
+        logger.log(u"Plex Media Server updating " + sickbeard.PLEX_SERVER_HOST, logger.DEBUG)
+
+        url = "http://%s/library/sections" % sickbeard.PLEX_SERVER_HOST
+        xml_sections = minidom.parse(urllib.urlopen(url))
+        sections = xml_sections.getElementsByTagName('Directory')
+
+        for s in sections:
+            if s.getAttribute('type') == "show":
+                url = "http://%s/library/sections/%s/refresh" % (sickbeard.PLEX_SERVER_HOST, s.getAttribute('key'))
+
+                try:
+                    x = urllib.urlopen(url)
+                except Exception, e:
+                    logger.log(u"Error updating library section: "+str(e).decode('utf-8'), logger.ERROR)
+                    return False
+
+        return True
+
+notifier = PLEXNotifier
diff --git a/sickbeard/notifiers/prowl.py b/sickbeard/notifiers/prowl.py
index a9b330ac7e2063ad04f9590120efba20b162195d..6491db817872cf8e9dd30791f9c446a33027ead4 100644
--- a/sickbeard/notifiers/prowl.py
+++ b/sickbeard/notifiers/prowl.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import socket
 import sys
 from httplib import HTTPSConnection
diff --git a/sickbeard/notifiers/tweet.py b/sickbeard/notifiers/tweet.py
index 16b3b4d8ee2cebb5c1a3c0102d9c764aa802f50e..35a29027858bf4cd9cd9f0f7bf35fb4008f4f6ae 100644
--- a/sickbeard/notifiers/tweet.py
+++ b/sickbeard/notifiers/tweet.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import socket
 import os
 import sys
diff --git a/sickbeard/notifiers/xbmc.py b/sickbeard/notifiers/xbmc.py
index 0299316da053eea8ce99e66e17dd615c262805f4..8144b0fa4ccae32de6f67bfdd1e7dca6155808c0 100644
--- a/sickbeard/notifiers/xbmc.py
+++ b/sickbeard/notifiers/xbmc.py
@@ -57,6 +57,17 @@ class XBMCNotifier:
                     logger.log(u"Update of show directory failed on " + curHost + ", trying full update as requested", logger.ERROR)
                     self._update_library(curHost)
 
+    def _username(self):
+        return sickbeard.XBMC_USERNAME
+
+    def _password(self):
+        return sickbeard.XBMC_PASSWORD
+
+    def _use_me(self):
+        return sickbeard.USE_XBMC
+
+    def _hostname(self):
+        return sickbeard.XBMC_HOST
 
     def _sendToXBMC(self, command, host, username=None, password=None):
         '''
@@ -69,9 +80,9 @@ class XBMCNotifier:
         '''
     
         if not username:
-            username = sickbeard.XBMC_USERNAME
+            username = self._username()
         if not password:
-            password = sickbeard.XBMC_PASSWORD
+            password = self._password()
     
         for key in command:
             if type(command[key]) == unicode:
@@ -104,25 +115,31 @@ class XBMCNotifier:
 
     def _notifyXBMC(self, input, title="Sick Beard", host=None, username=None, password=None, force=False):
     
-        if not sickbeard.USE_XBMC and not force:
+        if not self._use_me() and not force:
             logger.log("Notification for XBMC not enabled, skipping this notification", logger.DEBUG)
             return False
     
         if not host:
-            host = sickbeard.XBMC_HOST
+            host = self._hostname()
         if not username:
-            username = sickbeard.XBMC_USERNAME
+            username = self._username()
         if not password:
-            password = sickbeard.XBMC_PASSWORD
+            password = self._password()
     
         logger.log(u"Sending notification for " + input, logger.DEBUG)
     
         fileString = title + "," + input
     
+        result = ''
+    
         for curHost in [x.strip() for x in host.split(",")]:
             command = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' +fileString + ')' }
             logger.log(u"Sending notification to XBMC via host: "+ curHost +"username: "+ username + " password: " + password, logger.DEBUG)
-            return self._sendToXBMC(command, curHost, username, password)
+            if result:
+                result += ', '
+            result += curHost + ':' + self._sendToXBMC(command, curHost, username, password)
+
+        return result
 
     def _update_library(self, host, showName=None):
     
diff --git a/sickbeard/nzbSplitter.py b/sickbeard/nzbSplitter.py
index 50e3cd3c7c948f3f3a5abee02ed6d2c240ad79d1..9de912fc049d304a238474e1972bb3d8e7cfeeae 100644
--- a/sickbeard/nzbSplitter.py
+++ b/sickbeard/nzbSplitter.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import urllib2
 
 import xml.etree.cElementTree as etree
diff --git a/sickbeard/nzbget.py b/sickbeard/nzbget.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d73d1b4cda2e97beba68010b8b81b991c20785b
--- /dev/null
+++ b/sickbeard/nzbget.py
@@ -0,0 +1,89 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+import httplib
+import datetime
+
+import sickbeard
+
+from base64 import standard_b64encode
+import xmlrpclib
+
+from sickbeard.providers.generic import GenericProvider
+
+from sickbeard.common import *
+from sickbeard import logger, classes
+
+def sendNZB(nzb):
+
+    addToTop = False
+    nzbgetXMLrpc = "http://nzbget:%(password)s@%(host)s/xmlrpc"
+
+    if sickbeard.NZBGET_HOST == None:
+        logger.log(u"No NZBget host found in configuration. Please configure it.", logger.ERROR)
+        return False
+
+    url = nzbgetXMLrpc % {"host": sickbeard.NZBGET_HOST, "password": sickbeard.NZBGET_PASSWORD}
+
+    nzbGetRPC = xmlrpclib.ServerProxy(url)
+    try:
+        if nzbGetRPC.writelog("INFO", "Sickbeard connected to drop of %s any moment now." % (nzb.name + ".nzb")):
+            logger.log(u"Successful connected to NZBget", logger.DEBUG)
+        else:
+            logger.log(u"Successful connected to NZBget, but unable to send a message" % (nzb.name + ".nzb"), logger.ERROR)
+
+    except httplib.socket.error:
+        logger.log(u"Please check your NZBget host and port (if it is running). NZBget is not responding to this combination", logger.ERROR)
+        return False
+
+    except xmlrpclib.ProtocolError, e:
+        if (e.errmsg == "Unauthorized"):
+            logger.log(u"NZBget password is incorrect.", logger.ERROR)
+        else:
+            logger.log(u"Protocol Error: " + e.errmsg, logger.ERROR)
+        return False
+
+    # if it aired recently make it high priority
+    for curEp in nzb.episodes:
+        if datetime.date.today() - curEp.airdate <= datetime.timedelta(days=7):
+            addToTop = True
+
+    # if it's a normal result need to download the NZB content
+    if nzb.resultType == "nzb":
+        genProvider = GenericProvider("")
+        data = genProvider.getURL(nzb.url)
+        if (data == None):
+            return False
+
+    # if we get a raw data result thats even better
+    elif nzb.resultType == "nzbdata":
+        data = nzb.extraInfo[0]
+
+    nzbcontent64 = standard_b64encode(data)
+
+    logger.log(u"Sending NZB to NZBget")
+    logger.log(u"URL: " + url, logger.DEBUG)
+
+    if nzbGetRPC.append(nzb.name + ".nzb", sickbeard.NZBGET_CATEGORY, addToTop, nzbcontent64):
+        logger.log(u"NZB sent to NZBget successfully", logger.DEBUG)
+        return True
+    else:
+        logger.log(u"NZBget could not add %s to the queue" % (nzb.name + ".nzb"), logger.ERROR)
+        return False
\ No newline at end of file
diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py
index 3ff63365af2b0fd3e75411119a4a7778f8619999..3dd8f229e6b443d8d7ff3a54102c5b7b9cd6e303 100755
--- a/sickbeard/postProcessor.py
+++ b/sickbeard/postProcessor.py
@@ -35,7 +35,8 @@ from sickbeard import helpers
 from sickbeard import history
 from sickbeard import logger
 from sickbeard import notifiers
-from sickbeard import sceneHelpers
+from sickbeard import show_name_helpers
+from sickbeard import scene_exceptions
 
 from sickbeard import encodingKludge as ek
 
@@ -104,7 +105,7 @@ class PostProcessor(object):
 
     def _list_associated_files(self, file_path):
     
-        if not file_path or not ek.ek(os.path.isfile, file_path):
+        if not file_path:
             return []
 
         file_path_list = []
@@ -248,7 +249,7 @@ class PostProcessor(object):
             # if we couldn't find the right one then just use the season folder defaut format
             if season_folder == '':
                 # for air-by-date shows use the year as the season folder
-                if ep_obj.show.is_air_by_date:
+                if ep_obj.show.air_by_date:
                     season_folder = str(ep_obj.airdate.year)
                 else:
                     season_folder = sickbeard.SEASON_FOLDERS_FORMAT % (ep_obj.season)
@@ -327,7 +328,7 @@ class PostProcessor(object):
         to_return = (None, season, episodes)
     
         # do a scene reverse-lookup to get a list of all possible names
-        name_list = sceneHelpers.sceneToNormalShowNames(parse_result.series_name)
+        name_list = show_name_helpers.sceneToNormalShowNames(parse_result.series_name)
 
         if not name_list:
             return (None, season, episodes)
@@ -340,13 +341,11 @@ class PostProcessor(object):
         # for each possible interpretation of that scene name
         for cur_name in name_list:
             self._log(u"Checking scene exceptions for a match on "+cur_name, logger.DEBUG)
-            for exceptionID in common.sceneExceptions:
-                # for each exception name
-                for curException in common.sceneExceptions[exceptionID]:
-                    if cur_name.lower() in (curException.lower(), sceneHelpers.sanitizeSceneName(curException).lower().replace('.',' ')):
-                        self._log(u"Scene exception lookup got tvdb id "+str(exceptionID)+u", using that", logger.DEBUG)
-                        _finalize(parse_result)
-                        return (exceptionID, season, episodes)
+            scene_id = scene_exceptions.get_scene_exception_by_name(cur_name)
+            if scene_id:
+                self._log(u"Scene exception lookup got tvdb id "+str(scene_id)+u", using that", logger.DEBUG)
+                _finalize(parse_result)
+                return (scene_id, season, episodes)
 
         # see if we can find the name directly in the DB, if so use it
         for cur_name in name_list:
@@ -701,8 +700,11 @@ class PostProcessor(object):
         ep_obj.createMetaFiles()
         ep_obj.saveToDB()
 
-        # do the library update
-        notifiers.xbmc_notifier.update_library(ep_obj.show.name)
+        # do the library update
+        notifiers.xbmc_notifier.update_library(ep_obj.show.name)
+
+        # do the library update for Plex Media Server
+        notifiers.plex_notifier.update_library()
 
         # run extra_scripts
         self._run_extra_scripts(ep_obj)
diff --git a/sickbeard/properFinder.py b/sickbeard/properFinder.py
index 0dba779c15da58412f1798a8f39035881793a82f..e21c70354c0289419ce7f3c8605debe923065a18 100644
--- a/sickbeard/properFinder.py
+++ b/sickbeard/properFinder.py
@@ -22,7 +22,7 @@ import operator
 import sickbeard
 
 from sickbeard import db
-from sickbeard import classes, common, helpers, logger, sceneHelpers
+from sickbeard import classes, common, helpers, logger, show_name_helpers
 from sickbeard import providers
 from sickbeard import search
 from sickbeard import history
@@ -118,7 +118,7 @@ class ProperFinder():
                 genericName = self._genericName(parse_result.series_name)
 
                 # get the scene name masks
-                sceneNames = set(sceneHelpers.makeSceneShowSearchStrings(curShow))
+                sceneNames = set(show_name_helpers.makeSceneShowSearchStrings(curShow))
 
                 # for each scene name mask
                 for curSceneName in sceneNames:
@@ -140,7 +140,7 @@ class ProperFinder():
             if curProper.tvdbid == -1:
                 continue
             
-            if not sceneHelpers.filterBadReleases(curProper.name):
+            if not show_name_helpers.filterBadReleases(curProper.name):
                 logger.log(u"Proper "+curProper.name+" isn't a valid scene release that we want, igoring it", logger.DEBUG)
                 continue
 
diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py
index 8242fbe89e61a71e2744bb09ccf57dfae40b6ca7..f642a1200abc97bb8b383f4c21f09b5b25abd6c6 100644
--- a/sickbeard/providers/__init__.py
+++ b/sickbeard/providers/__init__.py
@@ -1,4 +1,23 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 __all__ = ['ezrss',
+           'tvtorrents',
            'nzbmatrix',
            'nzbs_org',
            'tvbinz',
diff --git a/sickbeard/providers/ezrss.py b/sickbeard/providers/ezrss.py
index 29cc174424ad538ed8b3be0374aa7d30c49916f3..f0d2ba9580ea7b28aca5915d360d09db93ec957d 100644
--- a/sickbeard/providers/ezrss.py
+++ b/sickbeard/providers/ezrss.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import urllib
 import re
 
@@ -8,7 +26,8 @@ import generic
 
 from sickbeard.common import *
 from sickbeard import logger
-from sickbeard import tvcache, sceneHelpers
+from sickbeard import tvcache
+from sickbeard.helpers import sanitizeSceneName
 
 class EZRSSProvider(generic.TorrentProvider):
 
@@ -40,7 +59,7 @@ class EZRSSProvider(generic.TorrentProvider):
         
         results = {}
         
-        if show.is_air_by_date:
+        if show.air_by_date:
             logger.log(u"EZRSS doesn't support air-by-date backlog because of limitations on their RSS search.", logger.WARNING)
             return results
         
@@ -54,7 +73,7 @@ class EZRSSProvider(generic.TorrentProvider):
         if not show:
             return params
         
-        params['show_name'] = sceneHelpers.sanitizeSceneName(show.name).replace('.',' ').encode('utf-8')
+        params['show_name'] = sanitizeSceneName(show.name, ezrss=True).replace('.',' ').encode('utf-8')
           
         if season != None:
             params['season'] = season
@@ -68,9 +87,9 @@ class EZRSSProvider(generic.TorrentProvider):
         if not ep_obj:
             return params
                    
-        params['show_name'] = sceneHelpers.sanitizeSceneName(ep_obj.show.name).replace('.',' ').encode('utf-8')
+        params['show_name'] = sanitizeSceneName(ep_obj.show.name, ezrss=True).replace('.',' ').encode('utf-8')
         
-        if ep_obj.show.is_air_by_date:
+        if ep_obj.show.air_by_date:
             params['date'] = str(ep_obj.airdate)
         else:
             params['season'] = ep_obj.season
diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py
index cbce6ba235f9b393a60360ef6c843fc4e54e015c..ced160fb7f8667d48213691209b2fd6fc3f0734a 100644
--- a/sickbeard/providers/generic.py
+++ b/sickbeard/providers/generic.py
@@ -34,6 +34,8 @@ from sickbeard.common import *
 from sickbeard import tvcache
 from sickbeard import encodingKludge as ek
 
+from lib.hachoir_parser import createParser
+
 from sickbeard.name_parser.parser import NameParser, InvalidNameException
 
 class GenericProvider:
@@ -66,9 +68,9 @@ class GenericProvider:
         return
 
     def isActive(self):
-        if self.providerType == GenericProvider.NZB:
+        if self.providerType == GenericProvider.NZB and sickbeard.USE_NZBS:
             return self.isEnabled()
-        elif self.providerType == GenericProvider.TORRENT:
+        elif self.providerType == GenericProvider.TORRENT and sickbeard.USE_TORRENTS:
             return self.isEnabled()
         else:
             return False
@@ -116,6 +118,9 @@ class GenericProvider:
         return result
 
     def downloadResult(self, result):
+        """
+        Save the result to disk.
+        """
 
         logger.log(u"Downloading a result from " + self.name+" at " + result.url)
 
@@ -124,6 +129,7 @@ class GenericProvider:
         if data == None:
             return False
 
+        # use the appropriate watch folder
         if self.providerType == GenericProvider.NZB:
             saveDir = sickbeard.NZB_DIR
             writeMode = 'w'
@@ -133,6 +139,7 @@ class GenericProvider:
         else:
             return False
 
+        # use the result name as the filename
         fileName = ek.ek(os.path.join, saveDir, helpers.sanitizeFileName(result.name) + '.' + self.providerType)
 
         logger.log(u"Saving to " + fileName, logger.DEBUG)
@@ -141,10 +148,26 @@ class GenericProvider:
             fileOut = open(fileName, writeMode)
             fileOut.write(data)
             fileOut.close()
+            helpers.chmodAsParent(fileName)
         except IOError, e:
-            logger.log("Unable to save the NZB: "+str(e).decode('utf-8'), logger.ERROR)
+            logger.log("Unable to save the file: "+str(e).decode('utf-8'), logger.ERROR)
             return False
 
+        # as long as it's a valid download then consider it a successful snatch
+        return self._verify_download(fileName)
+
+    def _verify_download(self, file_name=None):
+        """
+        Checks the saved file to see if it was actually valid, if not then consider the download a failure.
+        """
+
+        # primitive verification of torrents, just make sure we didn't get a text file or something
+        if self.providerType == GenericProvider.TORRENT:
+            parser = createParser(file_name)
+            if not parser or parser._getMimeType() != 'application/x-bittorrent':
+                logger.log(u"Result is not a valid torrent file", logger.WARNING)
+                return False
+
         return True
 
     def searchRSS(self):
@@ -206,7 +229,7 @@ class GenericProvider:
                 logger.log(u"Unable to parse the filename "+title+" into a valid episode", logger.WARNING)
                 continue
 
-            if episode.show.is_air_by_date:
+            if episode.show.air_by_date:
                 if parse_result.air_date != episode.airdate:
                     logger.log("Episode "+title+" didn't air on "+str(episode.airdate)+", skipping it", logger.DEBUG)
                     continue
@@ -255,7 +278,7 @@ class GenericProvider:
                 logger.log(u"Unable to parse the filename "+title+" into a valid episode", logger.WARNING)
                 continue
 
-            if not show.is_air_by_date:
+            if not show.air_by_date:
                 # this check is meaningless for non-season searches
                 if (parse_result.season_number != None and parse_result.season_number != season) or (parse_result.season_number == None and season != 1):
                     logger.log(u"The result "+title+" doesn't seem to be a valid episode for season "+str(season)+", ignoring")
diff --git a/sickbeard/providers/newzbin.py b/sickbeard/providers/newzbin.py
index 5622859abfe9f6a98184b6ee2ca76ad4102fd352..e3d72ef18ea405aa94349a8c04108fa79bb4110b 100644
--- a/sickbeard/providers/newzbin.py
+++ b/sickbeard/providers/newzbin.py
@@ -27,7 +27,7 @@ import sickbeard
 import generic
 
 import sickbeard.encodingKludge as ek
-from sickbeard import classes, logger, helpers, exceptions, sceneHelpers, db
+from sickbeard import classes, logger, helpers, exceptions, db, show_name_helpers
 from sickbeard import tvcache
 from sickbeard.common import *
 
@@ -238,9 +238,9 @@ class NewzbinProvider(generic.NZBProvider):
 
     def _get_season_search_strings(self, show, season):
 
-        nameList = set(sceneHelpers.allPossibleShowNames(show))
+        nameList = set(show_name_helpers.allPossibleShowNames(show))
 
-        if show.is_air_by_date:
+        if show.air_by_date:
             suffix = ''
         else:
             suffix = 'x'
@@ -256,8 +256,8 @@ class NewzbinProvider(generic.NZBProvider):
 
     def _get_episode_search_strings(self, ep_obj):
 
-        nameList = set(sceneHelpers.allPossibleShowNames(ep_obj.show))
-        if not ep_obj.show.is_air_by_date:
+        nameList = set(show_name_helpers.allPossibleShowNames(ep_obj.show))
+        if not ep_obj.show.air_by_date:
             searchStr = " OR ".join(['^"'+x+' - %dx%02d"'%(ep_obj.season, ep_obj.episode) for x in nameList])
         else:
             searchStr = " OR ".join(['^"'+x+' - '+str(ep_obj.airdate)+'"' for x in nameList])
diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py
index b43df70f4bb3967c805fcc83512b15fc7f9b8d4a..a1827531d73c9f074a4ba5fc6fd25b0edbd5ff08 100644
--- a/sickbeard/providers/newznab.py
+++ b/sickbeard/providers/newznab.py
@@ -27,7 +27,8 @@ import xml.etree.cElementTree as etree
 import sickbeard
 import generic
 
-from sickbeard import classes, sceneHelpers
+from sickbeard import classes
+from sickbeard.helpers import sanitizeSceneName
 
 from sickbeard import exceptions
 from sickbeard.common import *
@@ -71,11 +72,11 @@ class NewznabProvider(generic.NZBProvider):
 			params['rid'] = show.tvrid
 		# if we can't then fall back on a very basic name search
 		else:
-			params['q'] = sceneHelpers.sanitizeSceneName(show.name)
+			params['q'] = sanitizeSceneName(show.name)
 
 		if season != None:
 			# air-by-date means &season=2010&q=2010.03, no other way to do it atm
-			if show.is_air_by_date:
+			if show.air_by_date:
 				params['season'] = season.split('-')[0]
 				if 'q' in params:
 					params['q'] += '.' + season.replace('-', '.')
@@ -98,9 +99,9 @@ class NewznabProvider(generic.NZBProvider):
 			params['rid'] = ep_obj.show.tvrid
 		# if we can't then fall back on a very basic name search
 		else:
-			params['q'] = sceneHelpers.sanitizeSceneName(ep_obj.show.name)
+			params['q'] = sanitizeSceneName(ep_obj.show.name)
 
-		if ep_obj.show.is_air_by_date:
+		if ep_obj.show.air_by_date:
 			date_str = str(ep_obj.airdate)
 			
 			params['season'] = date_str.partition('-')[0]
diff --git a/sickbeard/providers/nzbmatrix.py b/sickbeard/providers/nzbmatrix.py
index d8a5563198e3314bbd4e4fbb3fa72b5908c7bc44..f74de9bfed8fd78649e4eaac62bfbd2577c69b12 100644
--- a/sickbeard/providers/nzbmatrix.py
+++ b/sickbeard/providers/nzbmatrix.py
@@ -26,7 +26,7 @@ import xml.etree.cElementTree as etree
 import sickbeard
 import generic
 
-from sickbeard import classes, logger, sceneHelpers, db
+from sickbeard import classes, logger, show_name_helpers, db
 from sickbeard import tvcache
 from sickbeard.common import *
 
@@ -46,14 +46,14 @@ class NZBMatrixProvider(generic.NZBProvider):
         return sickbeard.NZBMATRIX
 
     def _get_season_search_strings(self, show, season):
-        sceneSearchStrings = set(sceneHelpers.makeSceneSeasonSearchString(show, season, "nzbmatrix"))
+        sceneSearchStrings = set(show_name_helpers.makeSceneSeasonSearchString(show, season, "nzbmatrix"))
 
         # search for all show names and episode numbers like ("a","b","c") in a single search
         return [' '.join(sceneSearchStrings)]
 
     def _get_episode_search_strings(self, ep_obj):
 
-        sceneSearchStrings = set(sceneHelpers.makeSceneSearchString(ep_obj))
+        sceneSearchStrings = set(show_name_helpers.makeSceneSearchString(ep_obj))
 
         # search for all show names and episode numbers like ("a","b","c") in a single search
         return ['("' + '","'.join(sceneSearchStrings) + '")']
diff --git a/sickbeard/providers/nzbs_org.py b/sickbeard/providers/nzbs_org.py
index 1d9914c97039e844f43f83f6deb5c2592a2d3d13..b390c2eed178defb7cf6ebf6360ab6d26757ecfe 100644
--- a/sickbeard/providers/nzbs_org.py
+++ b/sickbeard/providers/nzbs_org.py
@@ -27,7 +27,7 @@ import xml.etree.cElementTree as etree
 import sickbeard
 import generic
 
-from sickbeard import classes, sceneHelpers
+from sickbeard import classes, show_name_helpers
 
 from sickbeard import exceptions, logger, db
 from sickbeard.common import *
@@ -53,10 +53,10 @@ class NZBsProvider(generic.NZBProvider):
 			raise exceptions.AuthException("NZBs.org authentication details are empty, check your config")
 
 	def _get_season_search_strings(self, show, season):
-		return ['^'+x for x in sceneHelpers.makeSceneSeasonSearchString(show, season)]
+		return ['^'+x for x in show_name_helpers.makeSceneSeasonSearchString(show, season)]
 
 	def _get_episode_search_strings(self, ep_obj):
-		return ['^'+x for x in sceneHelpers.makeSceneSearchString(ep_obj)]
+		return ['^'+x for x in show_name_helpers.makeSceneSearchString(ep_obj)]
 
 	def _doSearch(self, curString, show=None):
 
diff --git a/sickbeard/providers/tvtorrents.py b/sickbeard/providers/tvtorrents.py
new file mode 100644
index 0000000000000000000000000000000000000000..5281a9a37531ff06fc7d599873f3419225095696
--- /dev/null
+++ b/sickbeard/providers/tvtorrents.py
@@ -0,0 +1,91 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
+import urllib
+
+import xml.etree.cElementTree as etree
+
+import sickbeard
+import generic
+
+from sickbeard.common import *
+from sickbeard import logger
+from sickbeard import tvcache
+
+class TvTorrentsProvider(generic.TorrentProvider):
+
+    def __init__(self):
+
+        generic.TorrentProvider.__init__(self, "TvTorrents")
+        
+        self.supportsBacklog = False
+
+        self.cache = TvTorrentsCache(self)
+
+        self.url = 'http://www.tvtorrents.com/'
+
+    def isEnabled(self):
+        return sickbeard.TVTORRENTS
+        
+    def imageName(self):
+        return 'tvtorrents.gif'
+
+class TvTorrentsCache(tvcache.TVCache):
+
+    def __init__(self, provider):
+
+        tvcache.TVCache.__init__(self, provider)
+
+        # only poll TvTorrents every 15 minutes max
+        self.minTime = 15
+
+
+    def _getRSSData(self):
+        # These will be ignored on the serverside.
+        ignore_regex = "all.month|month.of|season[\s\d]*complete"
+    
+        url = 'http://www.tvtorrents.com/RssServlet?digest='+ sickbeard.TVTORRENTS_DIGEST +'&hash='+ sickbeard.TVTORRENTS_HASH +'&fname=true&exclude=(' + ignore_regex + ')'
+        logger.log(u"TvTorrents cache update URL: "+ url, logger.DEBUG)
+
+        data = self.provider.getURL(url)
+        
+        xml_content = etree.fromstring(data)
+        description = xml_content.findtext('channel/description')
+
+        if "User can't be found" in description:
+            logger.log(u"TvTorrents invalid digest, check your config", logger.ERROR)
+
+        if "Invalid Hash" in description:
+            logger.log(u"TvTorrents invalid hash, check your config", logger.ERROR)
+
+        return data
+
+    def _parseItem(self, item):
+
+        title = item.findtext('title')
+        url = item.findtext('link')
+
+        if not title or not url:
+            logger.log(u"The XML returned from the TvTorrents RSS feed is incomplete, this result is unusable", logger.ERROR)
+            return
+
+        logger.log(u"Adding item from RSS to cache: "+title, logger.DEBUG)
+
+        self._addCacheEntry(title, url)
+
+provider = TvTorrentsProvider()
\ No newline at end of file
diff --git a/sickbeard/scene_exceptions.py b/sickbeard/scene_exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..999f869dd176c03528bffe81c7cf2373a7b2cd47
--- /dev/null
+++ b/sickbeard/scene_exceptions.py
@@ -0,0 +1,96 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import urllib
+
+from sickbeard.helpers import sanitizeSceneName
+from sickbeard import name_cache
+from sickbeard import logger
+from sickbeard import db
+
+def get_scene_exceptions(tvdb_id):
+    """
+    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])
+    return [cur_exception["show_name"] for cur_exception in exceptions]
+
+def get_scene_exception_by_name(show_name):
+    """
+    Given a show name, return the tvdbid of the exception, None if no exception
+    is present.
+    """
+
+    myDB = db.DBConnection("cache.db")
+    
+    # try the obvious case first
+    exception_result = myDB.select("SELECT tvdb_id FROM scene_exceptions WHERE LOWER(show_name) = ?", [show_name.lower()])
+    if exception_result:
+        return int(exception_result[0]["tvdb_id"])
+
+    all_exception_results = myDB.select("SELECT show_name, tvdb_id FROM scene_exceptions")
+    for cur_exception in all_exception_results:
+
+        cur_exception_name = cur_exception["show_name"]
+        cur_tvdb_id = int(cur_exception["tvdb_id"])
+
+        if show_name.lower() in (cur_exception_name.lower(), sanitizeSceneName(cur_exception_name).lower().replace('.',' ')):
+            logger.log(u"Scene exception lookup got tvdb id "+str(cur_tvdb_id)+u", using that", logger.DEBUG)
+            return cur_tvdb_id
+
+    return None
+
+def retrieve_exceptions():
+    """
+    Looks up the exceptions on github, parses them into a dict, and inserts them into the
+    scene_exceptions table in cache.db. Also clears the scene name cache.
+    """
+
+    exception_dict = {}
+
+    # exceptions are stored on github pages
+    url = 'http://midgetspy.github.com/sb_tvdb_scene_exceptions/exceptions.txt'
+    open_url = urllib.urlopen(url)
+    
+    # each exception is on one line with the format tvdb_id: 'show name 1', 'show name 2', etc
+    for cur_line in open_url.readlines():
+        tvdb_id, sep, aliases = cur_line.partition(':')
+        
+        if not aliases:
+            continue
+    
+        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)]
+        
+        exception_dict[tvdb_id] = alias_list
+
+    myDB = db.DBConnection("cache.db")
+    myDB.action("DELETE FROM scene_exceptions WHERE 1=1")
+
+    # write all the exceptions we got off the net into the database
+    for cur_tvdb_id in exception_dict:
+        for cur_exception in exception_dict[cur_tvdb_id]:
+            myDB.action("INSERT INTO scene_exceptions (tvdb_id, show_name) VALUES (?,?)", [cur_tvdb_id, cur_exception])
+
+    # since this could invalidate the results of the cache we clear it out after updating
+    name_cache.clearCache()
\ No newline at end of file
diff --git a/sickbeard/scheduler.py b/sickbeard/scheduler.py
index fb7ce97c03b4dc15ad5a468a44ff790a4a390595..55b6deefea3dbee7731ae724e6ef1f56dbea7ab2 100644
--- a/sickbeard/scheduler.py
+++ b/sickbeard/scheduler.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import datetime
 import time
 import threading
diff --git a/sickbeard/search.py b/sickbeard/search.py
index aca2b7ce44e9e36962618a0f42f8558c9bd44af5..f4a1726ee13ea3d713b8537a23a0f39de20d0ad2 100644
--- a/sickbeard/search.py
+++ b/sickbeard/search.py
@@ -24,16 +24,26 @@ import sickbeard
 
 from common import *
 
-from sickbeard import logger, db, sceneHelpers, exceptions, helpers
+from sickbeard import logger, db, show_name_helpers, exceptions, helpers
 from sickbeard import sab
+from sickbeard import nzbget
 from sickbeard import history
 from sickbeard import notifiers
 from sickbeard import nzbSplitter
 
+from sickbeard import encodingKludge as ek
+
 from sickbeard.providers import *
 from sickbeard import providers
 
 def _downloadResult(result):
+    """
+    Downloads a result to the appropriate black hole folder.
+    
+    Returns a bool representing success.
+    
+    result: SearchResult instance to download.
+    """
 
     resProvider = result.provider
 
@@ -43,25 +53,33 @@ def _downloadResult(result):
         logger.log(u"Invalid provider name - this is a coding error, report it please", logger.ERROR)
         return False
 
+    # nzbs with an URL can just be downloaded from the provider
     if result.resultType == "nzb":
         newResult = resProvider.downloadResult(result)
+
+    # if it's an nzb data result 
     elif result.resultType == "nzbdata":
-        fileName = os.path.join(sickbeard.NZB_DIR, result.name + ".nzb")
+        
+        # get the final file path to the nzb
+        fileName = ek.ek(os.path.join, sickbeard.NZB_DIR, result.name + ".nzb")
 
         logger.log(u"Saving NZB to " + fileName)
 
         newResult = True
 
+        # save the data to disk
         try:
             fileOut = open(fileName, "w")
             fileOut.write(result.extraInfo[0])
             fileOut.close()
+            helpers.chmodAsParent(fileName)
         except IOError, e:
             logger.log(u"Error trying to save NZB to black hole: "+str(e).decode('utf-8'), logger.ERROR)
             newResult = False
 
     elif resProvider.providerType == "torrent":
         newResult = resProvider.downloadResult(result)
+
     else:
         logger.log(u"Invalid provider type - this is a coding error, report it please", logger.ERROR)
         return False
@@ -69,15 +87,29 @@ def _downloadResult(result):
     return newResult
 
 def snatchEpisode(result, endStatus=SNATCHED):
-
+    """
+    Contains the internal logic necessary to actually "snatch" a result that
+    has been found.
+    
+    Returns a bool representing success.
+    
+    result: SearchResult instance to be snatched.
+    endStatus: the episode status that should be used for the episode object once it's snatched.
+    """
+
+    # NZBs can be sent straight to SAB or saved to disk
     if result.resultType in ("nzb", "nzbdata"):
         if sickbeard.NZB_METHOD == "blackhole":
             dlResult = _downloadResult(result)
         elif sickbeard.NZB_METHOD == "sabnzbd":
             dlResult = sab.sendNZB(result)
+        elif sickbeard.NZB_METHOD == "nzbget":
+            dlResult = nzbget.sendNZB(result)
         else:
             logger.log(u"Unknown NZB action specified in config: " + sickbeard.NZB_METHOD, logger.ERROR)
             dlResult = False
+
+    # torrents are always saved to disk
     elif result.resultType == "torrent":
         dlResult = _downloadResult(result)
     else:
@@ -162,7 +194,7 @@ def pickBestResult(results, quality_list=None):
     # find the best result for the current episode
     bestResult = None
     for cur_result in results:
-        logger.log("Quality of "+cur_result.name+" is "+str(cur_result.quality))
+        logger.log("Quality of "+cur_result.name+" is "+Quality.qualityStrings[cur_result.quality])
         
         if quality_list and cur_result.quality not in quality_list:
             logger.log(cur_result.name+" is a quality we know we don't want, rejecting it", logger.DEBUG)
@@ -210,7 +242,7 @@ def findEpisode(episode, manualSearch=False):
         didSearch = True
 
         # skip non-tv crap
-        curFoundResults = filter(lambda x: sceneHelpers.filterBadReleases(x.name) and sceneHelpers.isGoodResult(x.name, episode.show), curFoundResults)
+        curFoundResults = filter(lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, episode.show), curFoundResults)
 
         foundResults += curFoundResults
 
@@ -241,7 +273,7 @@ def findSeason(show, season):
             for curEp in curResults:
 
                 # skip non-tv crap
-                curResults[curEp] = filter(lambda x:  sceneHelpers.filterBadReleases(x.name) and sceneHelpers.isGoodResult(x.name, show), curResults[curEp])
+                curResults[curEp] = filter(lambda x:  show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), curResults[curEp])
 
                 if curEp in foundResults:
                     foundResults[curEp] += curResults[curEp]
@@ -316,7 +348,7 @@ def findSeason(show, season):
             # if not, break it apart and add them as the lowest priority results
             individualResults = nzbSplitter.splitResult(bestSeasonNZB)
 
-            individualResults = filter(lambda x:  sceneHelpers.filterBadReleases(x.name) and sceneHelpers.isGoodResult(x.name, show), individualResults)
+            individualResults = filter(lambda x:  show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), individualResults)
 
             for curResult in individualResults:
                 if len(curResult.episodes) == 1:
diff --git a/sickbeard/searchBacklog.py b/sickbeard/searchBacklog.py
index e4c86466832408d8cda6f59ae0353140aba40e2f..11e2bbf83a552b49dabdc16738bb49e4318d35aa 100644
--- a/sickbeard/searchBacklog.py
+++ b/sickbeard/searchBacklog.py
@@ -94,8 +94,8 @@ class BacklogSearcher:
         numSeasonResults = myDB.select("SELECT DISTINCT(season), showid FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.tvdb_id AND show.paused = 0 AND ep.airdate > ?", [fromDate.toordinal()])
 
         # get separate lists of the season/date shows
-        season_shows = [x for x in show_list if not x.is_air_by_date]
-        air_by_date_shows = [x for x in show_list if x.is_air_by_date]
+        season_shows = [x for x in show_list if not x.air_by_date]
+        air_by_date_shows = [x for x in show_list if x.air_by_date]
 
         # figure out how many segments of air by date shows we're going to do
         air_by_date_segments = []
@@ -113,7 +113,7 @@ class BacklogSearcher:
             if curShow.paused:
                 continue
 
-            if curShow.is_air_by_date:
+            if curShow.air_by_date:
                 segments = [x[1] for x in self._get_air_by_date_segments(curShow.tvdbid, fromDate)]
             else:
                 segments = self._get_season_segments(curShow.tvdbid, fromDate)
diff --git a/sickbeard/search_queue.py b/sickbeard/search_queue.py
index 963c6bc8d0c9da9b01a47be03f88881c876cf4f7..da136ade643be0334740c89a9ed866b8882c8167 100644
--- a/sickbeard/search_queue.py
+++ b/sickbeard/search_queue.py
@@ -129,7 +129,7 @@ class BacklogQueueItem(generic_queue.QueueItem):
         myDB = db.DBConnection()
 
         # see if there is anything in this season worth searching for
-        if not self.show.is_air_by_date:
+        if not self.show.air_by_date:
             statusResults = myDB.select("SELECT status FROM tv_episodes WHERE showid = ? AND season = ?", [self.show.tvdbid, self.segment])
         else:
             segment_year, segment_month = map(int, self.segment.split('-'))
diff --git a/sickbeard/showUpdater.py b/sickbeard/showUpdater.py
index d8d7c1626d41a2ae373c71ddcd0e012ff42e42d0..5ffd5008874a32903bd5bf433ac8531366072887 100644
--- a/sickbeard/showUpdater.py
+++ b/sickbeard/showUpdater.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import datetime
 
 from sickbeard.common import *
diff --git a/sickbeard/sceneHelpers.py b/sickbeard/show_name_helpers.py
similarity index 79%
rename from sickbeard/sceneHelpers.py
rename to sickbeard/show_name_helpers.py
index 0ef745b3e489101a61125c7875e5a18ea71561ec..7b7944c70210270eef883cb5b5855a44b685ec06 100644
--- a/sickbeard/sceneHelpers.py
+++ b/sickbeard/show_name_helpers.py
@@ -16,20 +16,32 @@
 # You should have received a copy of the GNU General Public License
 # along with Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
 
-from sickbeard import common
+from sickbeard.common import countryList
+from sickbeard.helpers import sanitizeSceneName
+from sickbeard.scene_exceptions import get_scene_exceptions
 from sickbeard import logger
 from sickbeard import db
 
 import re
 import datetime
+import urllib
 
 from name_parser.parser import NameParser, InvalidNameException
 
 resultFilters = ("sub(pack|s|bed)", "nlsub(bed|s)?", "swesub(bed)?",
                  "(dir|sample|nfo)fix", "sample", "(dvd)?extras", 
-                 "dub(bed)?", "german", "french", "core2hd")
+                 "dub(bed)?", "german", "french", "core2hd",
+                 "dutch", "swedish")
 
 def filterBadReleases(name):
+    """
+    Filters out non-english and just all-around stupid releases by comparing them
+    to the resultFilters contents.
+    
+    name: the release name to check
+    
+    Returns: True if the release name is OK, False if it's bad.
+    """
 
     try:
         fp = NameParser()
@@ -50,19 +62,14 @@ def filterBadReleases(name):
 
     return True
 
-def sanitizeSceneName (name):
-    for x in ",:()'!?":
-        name = name.replace(x, "")
-
-    name = name.replace("- ", ".").replace(" ", ".").replace("&", "and").replace('/','.')
-    name = re.sub("\.\.*", ".", name)
-
-    if name.endswith('.'):
-        name = name[:-1]
-
-    return name
-
 def sceneToNormalShowNames(name):
+    """
+    Takes a show name from a scene dirname and converts it to a more "human-readable" format.
+    
+    name: The show name to convert
+    
+    Returns: a list of all the possible "normal" names
+    """
 
     if not name:
         return []
@@ -81,7 +88,7 @@ def sceneToNormalShowNames(name):
         results.append(re.sub('(\D)(\d{4})$', '\\1(\\2)', cur_name))
     
         # add brackets around the country
-        country_match_str = '|'.join(common.countryList.values())
+        country_match_str = '|'.join(countryList.values())
         results.append(re.sub('(?i)([. _-])('+country_match_str+')$', '\\1(\\2)', cur_name))
 
     results += name_list
@@ -100,7 +107,7 @@ def makeSceneSeasonSearchString (show, segment, extraSearchType=None):
 
     myDB = db.DBConnection()
 
-    if show.is_air_by_date:
+    if show.air_by_date:
         numseasons = 0
         
         # the search string for air by date shows is just 
@@ -140,7 +147,7 @@ def makeSceneSeasonSearchString (show, segment, extraSearchType=None):
                 toReturn.append('"'+curShow+' '+str(segment).replace('-',' ')+'"')
             else:
                 term_list = [x+'*' for x in seasonStrings]
-                if show.is_air_by_date:
+                if show.air_by_date:
                     term_list = ['"'+x+'"' for x in term_list]
 
                 toReturn.append('"'+curShow+'"')
@@ -159,7 +166,7 @@ def makeSceneSearchString (episode):
     numseasons = int(numseasonsSQlResult[0][0])
 
     # see if we should use dates instead of episodes
-    if episode.show.is_air_by_date and episode.airdate != datetime.date.fromordinal(1):
+    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)),
@@ -179,12 +186,42 @@ def makeSceneSearchString (episode):
 
     return toReturn
 
+def isGoodResult(name, show, log=True):
+    """
+    Use an automatically-created regex to make sure the result actually is the show it claims to be
+    """
+
+    all_show_names = allPossibleShowNames(show)
+    showNames = map(sanitizeSceneName, all_show_names) + all_show_names
+
+    for curName in set(showNames):
+        escaped_name = re.sub('\\\\[\\s.-]', '\W+', re.escape(curName))
+        curRegex = '^' + escaped_name + '\W+(?:(?:S\d[\dE._ -])|(?:\d\d?x)|(?:\d{4}\W\d\d\W\d\d)|(?:(?:part|pt)[\._ -]?(\d|[ivx]))|Season\W+\d+\W+|E\d+\W+)'
+        if log:
+            logger.log(u"Checking if show "+name+" matches " + curRegex, logger.DEBUG)
+
+        match = re.search(curRegex, name, re.I)
+
+        if match:
+            logger.log(u"Matched "+curRegex+" to "+name, logger.DEBUG)
+            return True
+
+    if log:
+        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):
+    """
+    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.
+    
+    show: a TVShow object that we should get the names of
+    
+    Returns: a list of all the possible show names
+    """
 
     showNames = [show.name]
-
-    if int(show.tvdbid) in common.sceneExceptions:
-        showNames += common.sceneExceptions[int(show.tvdbid)]
+    showNames += [name for name in get_scene_exceptions(show.tvdbid)]
 
     # if we have a tvrage name then use it
     if show.tvrname != "" and show.tvrname != None:
@@ -192,8 +229,8 @@ def allPossibleShowNames(show):
 
     newShowNames = []
 
-    country_list = common.countryList
-    country_list.update(dict(zip(common.countryList.values(), common.countryList.keys())))
+    country_list = countryList
+    country_list.update(dict(zip(countryList.values(), countryList.keys())))
 
     # if we have "Show Name Australia" or "Show Name (Australia)" this will add "Show Name (AU)" for
     # any countries defined in common.countryList
@@ -211,26 +248,3 @@ def allPossibleShowNames(show):
 
     return showNames
 
-def isGoodResult(name, show, log=True):
-    """
-    Use an automatically-created regex to make sure the result actually is the show it claims to be
-    """
-
-    all_show_names = allPossibleShowNames(show)
-    showNames = map(sanitizeSceneName, all_show_names) + all_show_names
-
-    for curName in set(showNames):
-        escaped_name = re.sub('\\\\[\\s.-]', '\W+', re.escape(curName))
-        curRegex = '^' + escaped_name + '\W+(?:(?:S\d\d)|(?:\d\d?x)|(?:\d{4}\W\d\d\W\d\d)|(?:(?:part|pt)[\._ -]?(\d|[ivx]))|Season\W+\d+\W+|E\d+\W+)'
-        if log:
-            logger.log(u"Checking if show "+name+" matches " + curRegex, logger.DEBUG)
-
-        match = re.search(curRegex, name, re.I)
-
-        if match:
-            logger.log(u"Matched "+curRegex+" to "+name, logger.DEBUG)
-            return True
-
-    if log:
-        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
diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py
index 83785fd636af22f119d9571c76482af3b41852be..1ff65aa50043c459fe631e90037b61ecdfd15001 100644
--- a/sickbeard/show_queue.py
+++ b/sickbeard/show_queue.py
@@ -29,6 +29,7 @@ from sickbeard.common import *
 from sickbeard.tv import TVShow
 from sickbeard import exceptions, helpers, logger, ui, db
 from sickbeard import generic_queue
+from sickbeard import name_cache
 
 class ShowQueue(generic_queue.GenericQueue):
 
@@ -177,6 +178,10 @@ class QueueItemAdd(ShowQueueItem):
         ShowQueueItem.__init__(self, ShowQueueActions.ADD, self.show)
         
     def _getName(self):
+        """
+        Returns the show name if there is a show object created, if not returns
+        the dir that the show is being added to.
+        """
         if self.show == None:
             return self.showDir
         return self.show.name
@@ -184,6 +189,10 @@ class QueueItemAdd(ShowQueueItem):
     show_name = property(_getName)
 
     def _isLoading(self):
+        """
+        Returns True if we've gotten far enough to have a show object, or False
+        if we still only know the folder name.
+        """
         if self.show == None:
             return True
         return False
@@ -203,17 +212,26 @@ class QueueItemAdd(ShowQueueItem):
                 if self.lang:
                     ltvdb_api_parms['language'] = self.lang
         
+                logger.log(u"TVDB: "+repr(ltvdb_api_parms))
+        
                 t = tvdb_api.Tvdb(**ltvdb_api_parms)
                 s = t[self.tvdb_id]
+
+                # this usually only happens if they have an NFO in their show dir which gave us a TVDB ID that has no
+                # proper english version of the show
                 if not s or not s['seriesname']:
-                    ui.flash.error("Unable to add show", "Show in "+str(self.showDir)+" has no name on TVDB, probably the wrong language. Delete .nfo and add manually in the correct language.")
+                    ui.flash.error("Unable to add show", "Show in "+self.showDir+" has no name on TVDB, probably the wrong language. Delete .nfo and add manually in the correct language.")
                     self._finishEarly()
                     return
             except tvdb_exceptions.tvdb_exception, e:
-                ui.flash.error("Unable to add show", "Unable to look up the show in "+str(self.showDir)+" on TVDB, not using the NFO. Delete .nfo and add manually in the correct language.")
+                logger.log(u"Error contacting TVDB: "+str(e), logger.ERROR)
+                ui.flash.error("Unable to add show", "Unable to look up the show in "+self.showDir+" on TVDB, not using the NFO. Delete .nfo and add manually in the correct language.")
                 self._finishEarly()
                 return
 
+            # clear the name cache
+            name_cache.clearCache()
+
             newShow = TVShow(self.tvdb_id, self.lang)
             newShow.loadFromTVDB()
 
@@ -224,6 +242,10 @@ class QueueItemAdd(ShowQueueItem):
             self.show.quality = self.quality if self.quality else sickbeard.QUALITY_DEFAULT
             self.show.seasonfolders = self.season_folders if self.season_folders != None else sickbeard.SEASON_FOLDERS_DEFAULT
             self.show.paused = False
+            
+            # be smartish about this
+            if self.show.genre and "talk show" in self.show.genre.lower():
+                self.show.air_by_date = 1
 
         except tvdb_exceptions.tvdb_exception, e:
             logger.log(u"Unable to add show due to an error with TVDB: "+str(e).decode('utf-8'), logger.ERROR)
diff --git a/sickbeard/tv.py b/sickbeard/tv.py
index a2f337ad49ceb4f0b1d0cc1c69c0d7f6d7839bf2..885b7428191b62bc43451fad59428c497c4f3639 100644
--- a/sickbeard/tv.py
+++ b/sickbeard/tv.py
@@ -37,6 +37,7 @@ from sickbeard import helpers, exceptions, logger
 from sickbeard import tvrage
 from sickbeard import config
 from sickbeard import image_cache
+from sickbeard import postProcessor
 
 from sickbeard import encodingKludge as ek
 
@@ -78,11 +79,6 @@ class TVShow(object):
 
         self.saveToDB()
 
-    def _is_air_by_date(self):
-        return self.air_by_date or (self.genre and "Talk Show" in self.genre)
-    
-    is_air_by_date = property(_is_air_by_date)
-    
     def _getLocation(self):
         if ek.ek(os.path.isdir, self._location):
             return self._location
@@ -770,7 +766,8 @@ class TVShow(object):
                     for relEp in rootEp.relatedEps:
                         relEp.location = result
 
-            fileList = ek.ek(glob.glob, ek.ek(os.path.join, curEpDir, actualName[0] + "*").replace("[","*").replace("]","*"))
+            fileList = postProcessor.PostProcessor(curLocation)._list_associated_files(curLocation)
+            logger.log(u"Files associated to "+curLocation+": "+str(fileList), logger.DEBUG)
 
             for file in fileList:
                 result = helpers.rename_file(file, rootEp.prettyName())
@@ -1396,7 +1393,7 @@ class TVEpisode(object):
         if naming_quality == None:
             naming_quality = sickbeard.NAMING_QUALITY
 
-        if ((self.show.genre and "Talk Show" in self.show.genre) or self.show.air_by_date) and sickbeard.NAMING_DATES:
+        if self.show.air_by_date and sickbeard.NAMING_DATES:
             try:
                 goodEpString = self.airdate.strftime("%Y.%m.%d")
             except ValueError:
diff --git a/sickbeard/tvcache.py b/sickbeard/tvcache.py
index 92740d538c35fbe0335345fa8dfbbde05e463d93..f2b1fae485c8a678fc1caa0dedc05f24d5fbeac7 100644
--- a/sickbeard/tvcache.py
+++ b/sickbeard/tvcache.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import time
 import datetime
 import sqlite3
@@ -8,8 +26,9 @@ from sickbeard import db
 from sickbeard import logger
 from sickbeard.common import *
 
-from sickbeard import helpers, classes, exceptions, sceneHelpers
+from sickbeard import helpers, classes, exceptions, show_name_helpers
 from sickbeard import providers
+from sickbeard import name_cache
 
 import xml.etree.cElementTree as etree
 
@@ -207,30 +226,52 @@ class TVCache():
             # if they're both empty then fill out as much info as possible by searching the show name
             else:
 
-                showResult = helpers.searchDBForShow(parse_result.series_name)
-                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]
-
+                # check the name cache and see if we already know what show this is
+                logger.log(u"Checking the cache to see if we already know the tvdb id of "+parse_result.series_name, logger.DEBUG)
+                tvdb_id = name_cache.retrieveNameFromCache(parse_result.series_name)
+                
+                # remember if the cache lookup worked or not so we know whether we should bother updating it later
+                if tvdb_id == None:
+                    logger.log(u"No cache results returned, continuing on with the search", logger.DEBUG)
+                    from_cache = False
                 else:
+                    logger.log(u"Cache lookup found "+repr(tvdb_id)+", using that", logger.DEBUG)
+                    from_cache = True
+                
+                # if the cache failed, try looking up the show name in the database
+                if tvdb_id == None:
+                    logger.log(u"Trying to look the show up in the show database", logger.DEBUG)
+                    showResult = helpers.searchDBForShow(parse_result.series_name)
+                    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]
+
+                # 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 sceneHelpers.isGoodResult(name, curShow, False):
+                        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
                             break
 
-                if tvdb_id:
+                # 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)
 
-                    showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id)
-                    if not showObj:
-                        logger.log(u"This should never have happened, post a bug about this!", logger.ERROR)
-                        raise Exception("BAD STUFF HAPPENED")
-                    tvrage_id = showObj.tvrid
-                    tvdb_lang = showObj.lang
+                # if we came out with tvdb_id = None it means we couldn't figure it out at all, just use 0 for that
+                if tvdb_id == None:
+                    tvdb_id = 0
 
+                # if we found the show then retrieve the show object
+                if tvdb_id:
+                    showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id)
+                    if showObj:
+                        tvrage_id = showObj.tvrid
+                        tvdb_lang = showObj.lang
 
+        # if we weren't provided with season/episode information then get it from the name that we parsed
         if not season:
             season = parse_result.season_number if parse_result.season_number != None else 1
         if not episodes:
@@ -256,7 +297,6 @@ class TVCache():
 
         episodeText = "|"+"|".join(map(str, episodes))+"|"
 
-
         # get the current timestamp
         curTimestamp = int(time.mktime(datetime.datetime.today().timetuple()))
 
@@ -300,7 +340,7 @@ class TVCache():
         for curResult in sqlResults:
 
             # skip non-tv crap (but allow them for Newzbin cause we assume it's filtered well)
-            if self.providerID != 'newzbin' and not sceneHelpers.filterBadReleases(curResult["name"]):
+            if self.providerID != 'newzbin' and not show_name_helpers.filterBadReleases(curResult["name"]):
                 continue
 
             # get the show object, or if it's not one of our shows then ignore it
diff --git a/sickbeard/versionChecker.py b/sickbeard/versionChecker.py
index d5b59d940b5165fe304d7dba2acd5464d64b862f..e91c7e0d0b9790764a0a0830e123ff2bb0cae65a 100644
--- a/sickbeard/versionChecker.py
+++ b/sickbeard/versionChecker.py
@@ -19,6 +19,7 @@
 import sickbeard
 from sickbeard import helpers, version, ui
 from sickbeard import logger
+from sickbeard import scene_exceptions
 
 import os, os.path, platform, shutil, time
 import subprocess, re
@@ -29,6 +30,9 @@ from urllib2 import URLError
 from lib.pygithub import github
 
 class CheckVersion():
+    """
+    Version check class meant to run as a thread object with the SB scheduler.
+    """
 
     def __init__(self):
         self.install_type = self.find_install_type()
@@ -44,8 +48,19 @@ class CheckVersion():
 
     def run(self):
         self.check_for_new_version()
+        
+        # refresh scene exceptions too
+        scene_exceptions.retrieve_exceptions()
 
     def find_install_type(self):
+        """
+        Determines how this copy of SB was installed.
+        
+        returns: type of installation. Possible values are:
+            'win': any compiled windows build
+            'git': running from source using git
+            'source': running from source without git
+        """
 
         # check if we're a windows build
         if version.SICKBEARD_VERSION.startswith('build '):
@@ -58,6 +73,13 @@ class CheckVersion():
         return install_type
 
     def check_for_new_version(self, force=False):
+        """
+        Checks the internet for a newer version.
+        
+        returns: bool, True for new version or False for no new version.
+        
+        force: if true the VERSION_NOTIFY setting will be ignored and a check will be forced
+        """
 
         if not sickbeard.VERSION_NOTIFY and not force:
             logger.log(u"Version checking is disabled, not checking for the newest version")
@@ -74,7 +96,6 @@ class CheckVersion():
         return True
 
     def update(self):
-
         if self.updater.need_update():
             return self.updater.update()
 
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index 3501c5a997c4ef7f85266378ec61bba8bdbe2dba..9d06b381d1493da5684bc2e391e780015b072d85 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -42,6 +42,7 @@ from sickbeard import search_queue
 from sickbeard import image_cache
 
 from sickbeard.notifiers import xbmc
+from sickbeard.notifiers import plex
 from sickbeard.providers import newznab
 from sickbeard.common import *
 
@@ -589,9 +590,10 @@ class History:
 
 ConfigMenu = [
     { 'title': 'General',           'path': 'config/general/'          },
-    { 'title': 'Episode Downloads', 'path': 'config/episodedownloads/' },
-    { 'title': 'Notifications',     'path': 'config/notifications/'    },
+    { 'title': 'Search Settings',   'path': 'config/search/'           },
     { 'title': 'Search Providers',  'path': 'config/providers/'        },
+    { 'title': 'Post Processing',   'path': 'config/postProcessing/'   },
+    { 'title': 'Notifications',     'path': 'config/notifications/'    },
 ]
 
 class ConfigGeneral:
@@ -636,12 +638,7 @@ class ConfigGeneral:
     @cherrypy.expose
     def saveGeneral(self, log_dir=None, web_port=None, web_log=None, web_ipv6=None,
                     launch_browser=None, web_username=None,
-                    web_password=None, season_folders_format=None, 
-                    version_notify=None, naming_show_name=None, naming_ep_type=None,
-                    naming_multi_ep_type=None, naming_ep_name=None,
-                    naming_use_periods=None, naming_sep_type=None, naming_quality=None, naming_dates=None,
-                    xbmc_data=None, mediabrowser_data=None, sony_ps3_data=None,
-                    wdtv_data=None, use_banner=None):
+                    web_password=None, version_notify=None):
 
         results = []
 
@@ -665,6 +662,134 @@ class ConfigGeneral:
         else:
             version_notify = 0
 
+        if not config.change_LOG_DIR(log_dir):
+            results += ["Unable to create directory " + os.path.normpath(log_dir) + ", log dir not changed."]
+
+        sickbeard.LAUNCH_BROWSER = launch_browser
+
+        sickbeard.WEB_PORT = int(web_port)
+        sickbeard.WEB_IPV6 = web_ipv6
+        sickbeard.WEB_LOG = web_log
+        sickbeard.WEB_USERNAME = web_username
+        sickbeard.WEB_PASSWORD = web_password
+
+        config.change_VERSION_NOTIFY(version_notify)
+
+        sickbeard.save_config()
+
+        if len(results) > 0:
+            for x in results:
+                logger.log(x, logger.ERROR)
+            ui.flash.error('Error(s) Saving Configuration',
+                        '<br />\n'.join(results))
+        else:
+            ui.flash.message('Configuration Saved', ek.ek(os.path.join, sickbeard.PROG_DIR, 'config.ini') )
+
+        redirect("/config/general/")
+
+
+class ConfigSearch:
+
+    @cherrypy.expose
+    def index(self):
+
+        t = PageTemplate(file="config_search.tmpl")
+        t.submenu = ConfigMenu
+        return _munge(t)
+
+    @cherrypy.expose
+    def saveSearch(self, use_nzbs=None, use_torrents=None, nzb_dir=None, sab_username=None, sab_password=None,
+                       sab_apikey=None, sab_category=None, sab_host=None, nzbget_password=None, nzbget_category=None, nzbget_host=None,
+                       torrent_dir=None, nzb_method=None, usenet_retention=None, search_frequency=None, download_propers=None):
+
+        results = []
+
+        if not config.change_NZB_DIR(nzb_dir):
+            results += ["Unable to create directory " + os.path.normpath(nzb_dir) + ", dir not changed."]
+
+        if not config.change_TORRENT_DIR(torrent_dir):
+            results += ["Unable to create directory " + os.path.normpath(torrent_dir) + ", dir not changed."]
+
+        config.change_SEARCH_FREQUENCY(search_frequency)
+
+        if download_propers == "on":
+            download_propers = 1
+        else:
+            download_propers = 0
+
+        if use_nzbs == "on":
+            use_nzbs = 1
+        else:
+            use_nzbs = 0
+
+        if use_torrents == "on":
+            use_torrents = 1
+        else:
+            use_torrents = 0
+
+        if usenet_retention == None:
+            usenet_retention = 200
+
+        sickbeard.USE_NZBS = use_nzbs
+        sickbeard.USE_TORRENTS = use_torrents
+
+        sickbeard.NZB_METHOD = nzb_method
+        sickbeard.USENET_RETENTION = int(usenet_retention)
+
+        sickbeard.DOWNLOAD_PROPERS = download_propers
+
+        sickbeard.SAB_USERNAME = sab_username
+        sickbeard.SAB_PASSWORD = sab_password
+        sickbeard.SAB_APIKEY = sab_apikey.strip()
+        sickbeard.SAB_CATEGORY = sab_category
+
+        if sab_host and not re.match('https?://.*', sab_host):
+            sab_host = 'http://' + sab_host
+
+        if not sab_host.endswith('/'):
+            sab_host = sab_host + '/'
+
+        sickbeard.SAB_HOST = sab_host
+
+        sickbeard.NZBGET_PASSWORD = nzbget_password
+        sickbeard.NZBGET_CATEGORY = nzbget_category
+        sickbeard.NZBGET_HOST = nzbget_host
+
+
+        sickbeard.save_config()
+
+        if len(results) > 0:
+            for x in results:
+                logger.log(x, logger.ERROR)
+            ui.flash.error('Error(s) Saving Configuration',
+                        '<br />\n'.join(results))
+        else:
+            ui.flash.message('Configuration Saved', ek.ek(os.path.join, sickbeard.PROG_DIR, 'config.ini') )
+
+        redirect("/config/search/")
+
+class ConfigPostProcessing:
+
+    @cherrypy.expose
+    def index(self):
+
+        t = PageTemplate(file="config_postProcessing.tmpl")
+        t.submenu = ConfigMenu
+        return _munge(t)
+
+    @cherrypy.expose
+    def savePostProcessing(self, season_folders_format=None, naming_show_name=None, naming_ep_type=None,
+                    naming_multi_ep_type=None, naming_ep_name=None, naming_use_periods=None,
+                    naming_sep_type=None, naming_quality=None, naming_dates=None,
+                    xbmc_data=None, mediabrowser_data=None, sony_ps3_data=None, wdtv_data=None, use_banner=None,
+                    keep_processed_dir=None, process_automatically=None, rename_episodes=None,
+                    move_associated_files=None, tv_download_dir=None):
+
+        results = []
+
+        if not config.change_TV_DOWNLOAD_DIR(tv_download_dir):
+            results += ["Unable to create directory " + os.path.normpath(tv_download_dir) + ", dir not changed."]
+
         if naming_show_name == "on":
             naming_show_name = 1
         else:
@@ -695,10 +820,30 @@ class ConfigGeneral:
         else:
             use_banner = 0
 
-        if not config.change_LOG_DIR(log_dir):
-            results += ["Unable to create directory " + os.path.normpath(log_dir) + ", log dir not changed."]
+        if process_automatically == "on":
+            process_automatically = 1
+        else:
+            process_automatically = 0
 
-        sickbeard.LAUNCH_BROWSER = launch_browser
+        if rename_episodes == "on":
+            rename_episodes = 1
+        else:
+            rename_episodes = 0
+
+        if keep_processed_dir == "on":
+            keep_processed_dir = 1
+        else:
+            keep_processed_dir = 0
+
+        if move_associated_files == "on":
+            move_associated_files = 1
+        else:
+            move_associated_files = 0
+
+        sickbeard.PROCESS_AUTOMATICALLY = process_automatically
+        sickbeard.KEEP_PROCESSED_DIR = keep_processed_dir
+        sickbeard.RENAME_EPISODES = rename_episodes
+        sickbeard.MOVE_ASSOCIATED_FILES = move_associated_files
 
         sickbeard.metadata_provider_dict['XBMC'].set_config(xbmc_data)
         sickbeard.metadata_provider_dict['MediaBrowser'].set_config(mediabrowser_data)
@@ -716,16 +861,8 @@ class ConfigGeneral:
         sickbeard.NAMING_MULTI_EP_TYPE = int(naming_multi_ep_type)
         sickbeard.NAMING_SEP_TYPE = int(naming_sep_type)
 
-        sickbeard.WEB_PORT = int(web_port)
-        sickbeard.WEB_IPV6 = web_ipv6
-        sickbeard.WEB_LOG = web_log
-        sickbeard.WEB_USERNAME = web_username
-        sickbeard.WEB_PASSWORD = web_password
-
         sickbeard.USE_BANNER = use_banner
 
-        config.change_VERSION_NOTIFY(version_notify)
-
         sickbeard.save_config()
 
         if len(results) > 0:
@@ -734,10 +871,9 @@ class ConfigGeneral:
             ui.flash.error('Error(s) Saving Configuration',
                         '<br />\n'.join(results))
         else:
-            ui.flash.message('Configuration Saved', os.path.join(sickbeard.PROG_DIR, 'config.ini') )
-
-        redirect("/config/general/")
+            ui.flash.message('Configuration Saved', ek.ek(os.path.join, sickbeard.PROG_DIR, 'config.ini') )
 
+        redirect("/config/postProcessing/")
 
     @cherrypy.expose
     def testNaming(self, show_name=None, ep_type=None, multi_ep_type=None, ep_name=None,
@@ -820,99 +956,6 @@ class ConfigGeneral:
 
         return name
 
-class ConfigEpisodeDownloads:
-
-    @cherrypy.expose
-    def index(self):
-
-        t = PageTemplate(file="config_episodedownloads.tmpl")
-        t.submenu = ConfigMenu
-        return _munge(t)
-
-    @cherrypy.expose
-    def saveEpisodeDownloads(self, nzb_dir=None, sab_username=None, sab_password=None,
-                       sab_apikey=None, sab_category=None, sab_host=None,
-                       torrent_dir=None, nzb_method=None, usenet_retention=None,
-                       search_frequency=None, tv_download_dir=None,
-                       keep_processed_dir=None, process_automatically=None, rename_episodes=None,
-                       download_propers=None, move_associated_files=None):
-
-        results = []
-
-        if not config.change_TV_DOWNLOAD_DIR(tv_download_dir):
-            results += ["Unable to create directory " + os.path.normpath(tv_download_dir) + ", dir not changed."]
-
-        if not config.change_NZB_DIR(nzb_dir):
-            results += ["Unable to create directory " + os.path.normpath(nzb_dir) + ", dir not changed."]
-
-        if not config.change_TORRENT_DIR(torrent_dir):
-            results += ["Unable to create directory " + os.path.normpath(torrent_dir) + ", dir not changed."]
-
-        config.change_SEARCH_FREQUENCY(search_frequency)
-
-        if download_propers == "on":
-            download_propers = 1
-        else:
-            download_propers = 0
-
-        if process_automatically == "on":
-            process_automatically = 1
-        else:
-            process_automatically = 0
-
-        if rename_episodes == "on":
-            rename_episodes = 1
-        else:
-            rename_episodes = 0
-
-        if keep_processed_dir == "on":
-            keep_processed_dir = 1
-        else:
-            keep_processed_dir = 0
-
-        if move_associated_files == "on":
-            move_associated_files = 1
-        else:
-            move_associated_files = 0
-
-        if usenet_retention == None:
-            usenet_retention = 200
-
-        sickbeard.PROCESS_AUTOMATICALLY = process_automatically
-        sickbeard.KEEP_PROCESSED_DIR = keep_processed_dir
-        sickbeard.RENAME_EPISODES = rename_episodes
-        sickbeard.MOVE_ASSOCIATED_FILES = move_associated_files
-
-        sickbeard.NZB_METHOD = nzb_method
-        sickbeard.USENET_RETENTION = int(usenet_retention)
-
-        sickbeard.DOWNLOAD_PROPERS = download_propers
-
-        sickbeard.SAB_USERNAME = sab_username
-        sickbeard.SAB_PASSWORD = sab_password
-        sickbeard.SAB_APIKEY = sab_apikey.strip()
-        sickbeard.SAB_CATEGORY = sab_category
-
-        if sab_host and not re.match('https?://.*', sab_host):
-            sab_host = 'http://' + sab_host
-
-        if not sab_host.endswith('/'):
-            sab_host = sab_host + '/'
-
-        sickbeard.SAB_HOST = sab_host
-
-        sickbeard.save_config()
-
-        if len(results) > 0:
-            for x in results:
-                logger.log(x, logger.ERROR)
-            ui.flash.error('Error(s) Saving Configuration',
-                        '<br />\n'.join(results))
-        else:
-            ui.flash.message('Configuration Saved', os.path.join(sickbeard.PROG_DIR, 'config.ini') )
-
-        redirect("/config/episodedownloads/")
-
 class ConfigProviders:
 
     @cherrypy.expose
@@ -985,6 +1028,7 @@ class ConfigProviders:
                       nzbs_org_hash=None, nzbmatrix_username=None, nzbmatrix_apikey=None,
                       tvbinz_auth=None, provider_order=None,
                       nzbs_r_us_uid=None, nzbs_r_us_hash=None, newznab_string=None,
+                      tvtorrents_digest=None, tvtorrents_hash=None, 
                       newzbin_username=None, newzbin_password=None):
 
         results = []
@@ -1048,6 +1092,8 @@ class ConfigProviders:
                 sickbeard.WOMBLE = curEnabled
             elif curProvider == 'ezrss':
                 sickbeard.EZRSS = curEnabled
+            elif curProvider == 'tvtorrents':
+                sickbeard.TVTORRENTS = curEnabled
             elif curProvider in newznabProviderDict:
                 newznabProviderDict[curProvider].enabled = bool(curEnabled)
             else:
@@ -1059,6 +1105,9 @@ class ConfigProviders:
             sickbeard.TVBINZ_HASH = tvbinz_hash.strip()
         if tvbinz_auth:
             sickbeard.TVBINZ_AUTH = tvbinz_auth.strip()
+            
+        sickbeard.TVTORRENTS_DIGEST = tvtorrents_digest.strip()
+        sickbeard.TVTORRENTS_HASH = tvtorrents_hash.strip()
 
         sickbeard.NZBS_UID = nzbs_org_uid.strip()
         sickbeard.NZBS_HASH = nzbs_org_hash.strip()
@@ -1082,7 +1131,7 @@ class ConfigProviders:
             ui.flash.error('Error(s) Saving Configuration',
                         '<br />\n'.join(results))
         else:
-            ui.flash.message('Configuration Saved', os.path.join(sickbeard.PROG_DIR, 'config.ini') )
+            ui.flash.message('Configuration Saved', ek.ek(os.path.join, sickbeard.PROG_DIR, 'config.ini') )
 
         redirect("/config/providers/")
 
@@ -1097,11 +1146,14 @@ class ConfigNotifications:
     @cherrypy.expose
     def saveNotifications(self, use_xbmc=None, xbmc_notify_onsnatch=None, xbmc_notify_ondownload=None,
                           xbmc_update_library=None, xbmc_update_full=None, xbmc_host=None, xbmc_username=None, xbmc_password=None,
+                          use_plex=None, plex_notify_onsnatch=None, plex_notify_ondownload=None, plex_update_library=None,
+                          plex_server_host=None, plex_host=None, plex_username=None, plex_password=None,
                           use_growl=None, growl_notify_onsnatch=None, growl_notify_ondownload=None, growl_host=None, growl_password=None, 
                           use_prowl=None, prowl_notify_onsnatch=None, prowl_notify_ondownload=None, prowl_api=None, prowl_priority=0, 
                           use_twitter=None, twitter_notify_onsnatch=None, twitter_notify_ondownload=None, 
                           use_notifo=None, notifo_notify_onsnatch=None, notifo_notify_ondownload=None, notifo_username=None, notifo_apisecret=None,
-                          use_libnotify=None, libnotify_notify_onsnatch=None, libnotify_notify_ondownload=None):
+                          use_libnotify=None, libnotify_notify_onsnatch=None, libnotify_notify_ondownload=None,
+                          use_nmj=None, nmj_host=None, nmj_database=None, nmj_mount=None):
 
         results = []
 
@@ -1129,7 +1181,27 @@ class ConfigNotifications:
             use_xbmc = 1
         else:
             use_xbmc = 0
-            
+
+        if plex_update_library == "on":
+            plex_update_library = 1
+        else:
+            plex_update_library = 0
+
+        if plex_notify_onsnatch == "on":
+            plex_notify_onsnatch = 1
+        else:
+            plex_notify_onsnatch = 0
+
+        if plex_notify_ondownload == "on":
+            plex_notify_ondownload = 1
+        else:
+            plex_notify_ondownload = 0
+
+        if use_plex == "on":
+            use_plex = 1
+        else:
+            use_plex = 0
+
         if growl_notify_onsnatch == "on":
             growl_notify_onsnatch = 1
         else:
@@ -1139,6 +1211,7 @@ class ConfigNotifications:
             growl_notify_ondownload = 1
         else:
             growl_notify_ondownload = 0
+
         if use_growl == "on":
             use_growl = 1
         else:
@@ -1186,6 +1259,11 @@ class ConfigNotifications:
         else:
             use_notifo = 0
 
+        if use_nmj == "on":
+            use_nmj = 1
+        else:
+            use_nmj = 0
+
         sickbeard.USE_XBMC = use_xbmc
         sickbeard.XBMC_NOTIFY_ONSNATCH = xbmc_notify_onsnatch
         sickbeard.XBMC_NOTIFY_ONDOWNLOAD = xbmc_notify_ondownload
@@ -1195,6 +1273,15 @@ class ConfigNotifications:
         sickbeard.XBMC_USERNAME = xbmc_username
         sickbeard.XBMC_PASSWORD = xbmc_password
 
+        sickbeard.USE_PLEX = use_plex
+        sickbeard.PLEX_NOTIFY_ONSNATCH = plex_notify_onsnatch
+        sickbeard.PLEX_NOTIFY_ONDOWNLOAD = plex_notify_ondownload
+        sickbeard.PLEX_UPDATE_LIBRARY = plex_update_library
+        sickbeard.PLEX_HOST = plex_host
+        sickbeard.PLEX_SERVER_HOST = plex_server_host
+        sickbeard.PLEX_USERNAME = plex_username
+        sickbeard.PLEX_PASSWORD = plex_password
+
         sickbeard.USE_GROWL = use_growl
         sickbeard.GROWL_NOTIFY_ONSNATCH = growl_notify_onsnatch
         sickbeard.GROWL_NOTIFY_ONDOWNLOAD = growl_notify_ondownload
@@ -1221,6 +1308,11 @@ class ConfigNotifications:
         sickbeard.LIBNOTIFY_NOTIFY_ONSNATCH = libnotify_notify_onsnatch == "on"
         sickbeard.LIBNOTIFY_NOTIFY_ONDOWNLOAD = libnotify_notify_ondownload == "on"
 
+        sickbeard.USE_NMJ = use_nmj
+        sickbeard.NMJ_HOST = nmj_host
+        sickbeard.NMJ_DATABASE = nmj_database
+        sickbeard.NMJ_MOUNT = nmj_mount
+
         sickbeard.save_config()
 
         if len(results) > 0:
@@ -1229,7 +1321,7 @@ class ConfigNotifications:
             ui.flash.error('Error(s) Saving Configuration',
                         '<br />\n'.join(results))
         else:
-            ui.flash.message('Configuration Saved', os.path.join(sickbeard.PROG_DIR, 'config.ini') )
+            ui.flash.message('Configuration Saved', ek.ek(os.path.join, sickbeard.PROG_DIR, 'config.ini') )
 
         redirect("/config/notifications/")
 
@@ -1245,20 +1337,26 @@ class Config:
 
     general = ConfigGeneral()
 
-    episodedownloads = ConfigEpisodeDownloads()
+    search = ConfigSearch()
+    
+    postProcessing = ConfigPostProcessing()
 
     providers = ConfigProviders()
 
     notifications = ConfigNotifications()
 
-def haveXBMC():
-    return sickbeard.XBMC_HOST != None and len(sickbeard.XBMC_HOST) > 0
-
+def haveXBMC():
+    return sickbeard.XBMC_HOST
+
+def havePLEX():
+    return sickbeard.PLEX_SERVER_HOST
+
 def HomeMenu():
     return [
     { 'title': 'Add Shows',               'path': 'home/addShows/',                         },
     { 'title': 'Manual Post-Processing', 'path': 'home/postprocess/'                        },
-    { 'title': 'Update XBMC',            'path': 'home/updateXBMC/', 'requires': haveXBMC   },
+    { 'title': 'Update XBMC',            'path': 'home/updateXBMC/', 'requires': haveXBMC   },
+    { 'title': 'Update Plex',            'path': 'home/updatePLEX/', 'requires': havePLEX   },
     { 'title': 'Restart',                'path': 'home/restart/?pid='+str(sickbeard.PID)    },
     { 'title': 'Shutdown',               'path': 'home/shutdown/'                           },
     ]
@@ -1699,6 +1797,15 @@ class ErrorLogs:
 
 class Home:
 
+    @cherrypy.expose
+    def is_alive(self):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
+        if sickbeard.started:
+            return str(sickbeard.PID)
+        else:
+            return "nope"
+
     @cherrypy.expose
     def index(self):
 
@@ -1712,6 +1819,8 @@ class Home:
 
     @cherrypy.expose
     def testGrowl(self, host=None, password=None):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
         result = notifiers.growl_notifier.test_notify(host, password)
         if password==None or password=='':
             pw_append = ''
@@ -1725,6 +1834,8 @@ class Home:
 
     @cherrypy.expose
     def testProwl(self, prowl_api=None, prowl_priority=0):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
         result = notifiers.prowl_notifier.test_notify(prowl_api, prowl_priority)
         if result:
             return "Test prowl notice sent successfully"
@@ -1733,6 +1844,8 @@ class Home:
 
     @cherrypy.expose
     def testNotifo(self, username=None, apisecret=None):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
         result = notifiers.notifo_notifier.test_notify(username, apisecret)
         if result:
             return "Notifo notification succeeded. Check your Notifo clients to make sure it worked"
@@ -1741,10 +1854,14 @@ class Home:
 
     @cherrypy.expose
     def twitterStep1(self):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
         return notifiers.twitter_notifier._get_authorization()
 
     @cherrypy.expose
     def twitterStep2(self, key):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
         result = notifiers.twitter_notifier._get_credentials(key)
         logger.log(u"result: "+str(result))
         if result:
@@ -1754,6 +1871,8 @@ class Home:
 
     @cherrypy.expose
     def testTwitter(self):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
         result = notifiers.twitter_notifier.test_notify()
         if result:
             return "Tweet successful, check your twitter to make sure it worked"
@@ -1762,19 +1881,53 @@ class Home:
 
     @cherrypy.expose
     def testXBMC(self, host=None, username=None, password=None):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
         result = notifiers.xbmc_notifier.test_notify(urllib.unquote_plus(host), username, password)
         if result:
             return "Test notice sent successfully to "+urllib.unquote_plus(host)
         else:
             return "Test notice failed to "+urllib.unquote_plus(host)
 
+    @cherrypy.expose
+    def testPLEX(self, host=None, username=None, password=None):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
+        result = notifiers.plex_notifier.test_notify(urllib.unquote_plus(host), username, password)
+        if result:
+            return "Test notice sent successfully to "+urllib.unquote_plus(host)
+        else:
+            return "Test notice failed to "+urllib.unquote_plus(host)
+
     @cherrypy.expose
     def testLibnotify(self):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
         if notifiers.libnotify_notifier.test_notify():
             return "Tried sending desktop notification via libnotify"
         else:
             return notifiers.libnotify.diagnose()
 
+    @cherrypy.expose
+    def testNMJ(self, host=None, database=None, mount=None):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
+        result = notifiers.nmj_notifier.test_notify(urllib.unquote_plus(host), database, mount)
+        if result:
+            return "Successfull started the scan update"
+        else:
+            return "Test failed to start the scan update"
+
+    @cherrypy.expose
+    def settingsNMJ(self, host=None):
+        cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+
+        result = notifiers.nmj_notifier.notify_settings(urllib.unquote_plus(host))
+        if result:
+            return '{"message": "Got settings from %(host)s", "database": "%(database)s", "mount": "%(mount)s"}' % {"host": host, "database": sickbeard.NMJ_DATABASE, "mount": sickbeard.NMJ_MOUNT}
+        else:
+            return '{"message": "Failed! Make sure your Popcorn is on and NMJ is running. (see Log & Errors -> Debug for detailed info)", "database": "", "mount": ""}'
+
 
     @cherrypy.expose
     def shutdown(self):
@@ -1792,13 +1945,13 @@ class Home:
         if str(pid) != str(sickbeard.PID):
             redirect("/home")
 
+        t = PageTemplate(file="restart.tmpl")
+        t.submenu = HomeMenu()
+
         # do a soft restart
         threading.Timer(2, sickbeard.invoke_restart, [False]).start()
 
-        title = "Restarting"
-        message = "Sick Beard is restarting, refresh in 30 seconds."
-
-        return _genericMessage(title, message)
+        return _munge(t)
 
     @cherrypy.expose
     def update(self, pid=None):
@@ -1811,7 +1964,8 @@ class Home:
         if updated:
             # do a hard restart
             threading.Timer(2, sickbeard.invoke_restart, [False]).start()
-            return "Sick Beard is restarting, refresh in 30 seconds."
+            t = PageTemplate(file="restart_bare.tmpl")
+            return _munge(t)
         else:
             return _genericMessage("Update Failed","Update wasn't successful, not restarting. Check your log for more information.")
 
@@ -2091,15 +2245,27 @@ class Home:
         redirect("/home/displayShow?show="+str(showObj.tvdbid))
 
 
-    @cherrypy.expose
-    def updateXBMC(self, showName=None):
-
-        for curHost in [x.strip() for x in sickbeard.XBMC_HOST.split(",")]:
-            if notifiers.xbmc_notifier._update_library(curHost, showName=showName):
-                ui.flash.message("Command sent to XBMC host " + curHost + " to update library")
-            else:
-                ui.flash.error("Unable to contact XBMC host " + curHost)
-        redirect('/home')
+    @cherrypy.expose
+    def updateXBMC(self, showName=None):
+
+        for curHost in [x.strip() for x in sickbeard.XBMC_HOST.split(",")]:
+            if notifiers.xbmc_notifier._update_library(curHost, showName=showName):
+                ui.flash.message("Command sent to XBMC host " + curHost + " to update library")
+            else:
+                ui.flash.error("Unable to contact XBMC host " + curHost)
+        redirect('/home')
+
+
+    @cherrypy.expose
+    def updatePLEX(self):
+
+        if notifiers.plex_notifier._update_library():
+            ui.flash.message("Command sent to Plex Media Server host " + sickbeard.PLEX_HOST + " to update library")
+            logger.log(u"Plex library update initiated for host " + sickbeard.PLEX_HOST, logger.DEBUG)
+        else:
+            ui.flash.error("Unable to contact Plex Media Server host " + sickbeard.PLEX_HOST)
+            logger.log(u"Plex library update failed for host " + sickbeard.PLEX_HOST, logger.ERROR)
+        redirect('/home')
 
 
     @cherrypy.expose
@@ -2163,7 +2329,7 @@ class Home:
 
                 if int(status) == WANTED:
                     # figure out what segment the episode is in and remember it so we can backlog it
-                    if epObj.show.is_air_by_date:
+                    if epObj.show.air_by_date:
                         ep_segment = str(epObj.airdate)[:7]
                     else:
                         ep_segment = epObj.season
diff --git a/sickbeard/webserveInit.py b/sickbeard/webserveInit.py
index 640e37a4efebac50ea796b5d092520dba54eb651..26275c159f733ee52bcafdd98633122454ef3ffc 100644
--- a/sickbeard/webserveInit.py
+++ b/sickbeard/webserveInit.py
@@ -1,3 +1,21 @@
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard 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.
+#
+# Sick Beard 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 Sick Beard.  If not, see <http://www.gnu.org/licenses/>.
+
 import cherrypy
 import cherrypy.lib.auth_basic
 import os.path
diff --git a/tests/scene_helpers_tests.py b/tests/scene_helpers_tests.py
index b7e518405467247a8d4e24a04f50a50efd577850..6f4fc626b2c5a5277de4738ee735c3e8716b4c80 100644
--- a/tests/scene_helpers_tests.py
+++ b/tests/scene_helpers_tests.py
@@ -3,7 +3,11 @@ import unittest
 import sys, os.path
 sys.path.append(os.path.abspath('..'))
 
-from sickbeard import sceneHelpers, common
+from sickbeard import show_name_helpers, scene_exceptions, common
+
+import sickbeard
+from sickbeard import db
+from sickbeard.databases import cache_db
 
 class Show:
     def __init__(self, name, tvdbid, tvrname):
@@ -14,24 +18,24 @@ class Show:
 class SceneTests(unittest.TestCase):
     
     def _test_sceneToNormalShowNames(self, name, expected):
-        result = sceneHelpers.sceneToNormalShowNames(name)
+        result = show_name_helpers.sceneToNormalShowNames(name)
         self.assertTrue(len(set(expected).intersection(set(result))) == len(expected))
 
-        dot_result = sceneHelpers.sceneToNormalShowNames(name.replace(' ','.'))
+        dot_result = show_name_helpers.sceneToNormalShowNames(name.replace(' ','.'))
         dot_expected = [x.replace(' ','.') for x in expected]
         self.assertTrue(len(set(dot_expected).intersection(set(dot_result))) == len(dot_expected))
         
     def _test_allPossibleShowNames(self, name, tvdbid=0, tvrname=None, expected=[]):
         
-        result = sceneHelpers.allPossibleShowNames(Show(name, tvdbid, tvrname))
+        result = show_name_helpers.allPossibleShowNames(Show(name, tvdbid, tvrname))
         self.assertTrue(len(set(expected).intersection(set(result))) == len(expected))
 
     def _test_filterBadReleases(self, name, expected):
-        result = sceneHelpers.filterBadReleases(name)
+        result = show_name_helpers.filterBadReleases(name)
         self.assertEqual(result, expected)
 
     def _test_isGoodName(self, name, show):
-        self.assertTrue(sceneHelpers.isGoodResult(name, show))
+        self.assertTrue(show_name_helpers.isGoodResult(name, show))
 
     def test_isGoodName(self):
         self._test_isGoodName('Show.Name.S01E02.Test-Test', Show('Show/Name', 0, ''))
@@ -58,7 +62,9 @@ class SceneTests(unittest.TestCase):
         self._test_sceneToNormalShowNames('Show Name YA', ['Show Name YA'])
 
     def test_allPossibleShowNames(self):
-        common.sceneExceptions[-1] = ['Exception Test']
+        #common.sceneExceptions[-1] = ['Exception Test']
+        myDB = db.DBConnection("cache.db")
+        myDB.action("INSERT INTO scene_exceptions (tvdb_id, show_name) VALUES (?,?)", [-1, 'Exception Test'])
         common.countryList['Full Country Name'] = 'FCN'
         
         self._test_allPossibleShowNames('Show Name', expected=['Show Name'])
@@ -77,9 +83,38 @@ class SceneTests(unittest.TestCase):
         self._test_filterBadReleases('German.Show.S02.Some.Stuff-Grp', True)
         self._test_filterBadReleases('Show.S02.This.Is.German', False)
 
+
+
+
+print 'Loading exceptions...',
+db.upgradeDatabase(db.DBConnection("cache.db"), cache_db.InitialSchema)
+scene_exceptions.retrieve_exceptions()
+print 'done.'
+
+class SceneExceptionTestCase(unittest.TestCase):
+
+    def test_sceneExceptionsEmpty(self):
+        self.assertEqual(scene_exceptions.get_scene_exceptions(0), [])
+
+    def test_sceneExceptionsBabylon5(self):
+        self.assertEqual(sorted(scene_exceptions.get_scene_exceptions(70726)), ['Babylon 5', 'Babylon5'])
+
+    def test_sceneExceptionByName(self):
+        self.assertEqual(scene_exceptions.get_scene_exception_by_name('Babylon5'), 70726)
+        self.assertEqual(scene_exceptions.get_scene_exception_by_name('babylon 5'), 70726)
+        self.assertEqual(scene_exceptions.get_scene_exception_by_name('Carlos 2010'), 164451)
+        
+    def test_sceneExceptionByNameEmpty(self):
+        self.assertEqual(scene_exceptions.get_scene_exception_by_name('nothing useful'), None)
+
+
+
 if __name__ == '__main__':
     if len(sys.argv) > 1:
-        suite = unittest.TestLoader().loadTestsFromName('scene_helpers_tests.SceneTests.test_'+sys.argv[1])
+        suite = unittest.TestLoader().loadTestsFromName('scene_helpers_tests.SceneExceptionTestCase.test_'+sys.argv[1])
+        unittest.TextTestRunner(verbosity=2).run(suite)
     else:
         suite = unittest.TestLoader().loadTestsFromTestCase(SceneTests)
-    unittest.TextTestRunner(verbosity=2).run(suite)
+        unittest.TextTestRunner(verbosity=2).run(suite)
+        suite = unittest.TestLoader().loadTestsFromTestCase(SceneExceptionTestCase)
+        unittest.TextTestRunner(verbosity=2).run(suite)