[freeside-commits] branch master updated. aa38c070977cf63365a4d26a3e4a7e5049ad70d0

Ivan ivan at 420.am
Sun Sep 23 14:57:17 PDT 2012


The branch, master has been updated
       via  aa38c070977cf63365a4d26a3e4a7e5049ad70d0 (commit)
       via  0bff2e665b3a6389b47510e4c04a5a454f6dd7d4 (commit)
       via  806d426d106efea2b2b13314108c4ac046511e1c (commit)
       via  1ad547a47f16b4230762e752fbe48d460ed997e1 (commit)
      from  54422869b5d895058a78454ddfc7c01789cb56f7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit aa38c070977cf63365a4d26a3e4a7e5049ad70d0
Merge: 0bff2e6 5442286
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Sun Sep 23 14:57:08 2012 -0700

    Merge branch 'master' of git.freeside.biz:/home/git/freeside


commit 0bff2e665b3a6389b47510e4c04a5a454f6dd7d4
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Sun Sep 23 14:56:51 2012 -0700

    rt 4.0.7

diff --git a/rt/bin/rt b/rt/bin/rt
index 32f459a..89873f5 100755
--- a/rt/bin/rt
+++ b/rt/bin/rt
@@ -420,7 +420,7 @@ sub show {
         }
         elsif (my $spec = is_object_spec($_, $type)) {
             push @objects, $spec;
-            $rawprint = 1 if $_ =~ /\/content$/ or $_ !~ /^ticket/;
+            $rawprint = 1 if $_ =~ /\/content$/ or $_ =~ /\/links/ or $_ !~ /^ticket/;
         }
         else {
             my $datum = /^-/ ? "option" : "argument";
diff --git a/rt/bin/rt.in b/rt/bin/rt.in
index e54a07a..2a9f643 100644
--- a/rt/bin/rt.in
+++ b/rt/bin/rt.in
@@ -420,7 +420,7 @@ sub show {
         }
         elsif (my $spec = is_object_spec($_, $type)) {
             push @objects, $spec;
-            $rawprint = 1 if $_ =~ /\/content$/ or $_ !~ /^ticket/;
+            $rawprint = 1 if $_ =~ /\/content$/ or $_ =~ /\/links/ or $_ !~ /^ticket/;
         }
         else {
             my $datum = /^-/ ? "option" : "argument";
diff --git a/rt/configure b/rt/configure
index 1862c5f..76ef85b 100755
--- a/rt/configure
+++ b/rt/configure
@@ -1,7 +1,7 @@
 #! /bin/sh
 # From configure.ac Revision.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.67 for RT rt-4.0.6.
+# Generated by GNU Autoconf 2.68 for RT rt-4.0.7.
 #
 # Report bugs to <rt-bugs at bestpractical.com>.
 #
@@ -92,6 +92,7 @@ fi
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
 case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -216,11 +217,18 @@ IFS=$as_save_IFS
   # We cannot yet assume a decent shell, so we have to provide a
 	# neutralization value for shells without unset; and this also
 	# works around shells that cannot unset nonexistent variables.
+	# Preserve -v and -x to the replacement shell.
 	BASH_ENV=/dev/null
 	ENV=/dev/null
 	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
 	export CONFIG_SHELL
-	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+	case $- in # ((((
+	  *v*x* | *x*v* ) as_opts=-vx ;;
+	  *v* ) as_opts=-v ;;
+	  *x* ) as_opts=-x ;;
+	  * ) as_opts= ;;
+	esac
+	exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
 fi
 
     if test x$as_have_required = xno; then :
@@ -552,8 +560,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='RT'
 PACKAGE_TARNAME='rt'
-PACKAGE_VERSION='rt-4.0.6'
-PACKAGE_STRING='RT rt-4.0.6'
+PACKAGE_VERSION='rt-4.0.7'
+PACKAGE_STRING='RT rt-4.0.7'
 PACKAGE_BUGREPORT='rt-bugs at bestpractical.com'
 PACKAGE_URL=''
 
@@ -1165,7 +1173,7 @@ Try \`$0 --help' for more information"
     $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
     expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
       $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
     ;;
 
   esac
@@ -1303,7 +1311,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures RT rt-4.0.6 to adapt to many kinds of systems.
+\`configure' configures RT rt-4.0.7 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1364,7 +1372,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of RT rt-4.0.6:";;
+     short | recursive ) echo "Configuration of RT rt-4.0.7:";;
    esac
   cat <<\_ACEOF
 
@@ -1488,8 +1496,8 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-RT configure rt-4.0.6
-generated by GNU Autoconf 2.67
+RT configure rt-4.0.7
+generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
@@ -1535,7 +1543,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 
 	ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_compile
@@ -1581,7 +1589,7 @@ fi
   # interfere with the next link command; also delete a directory that is
   # left behind by Apple's compiler.  We do this before executing the actions.
   rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_link
@@ -1589,8 +1597,8 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by RT $as_me rt-4.0.6, which was
-generated by GNU Autoconf 2.67.  Invocation command line was
+It was created by RT $as_me rt-4.0.7, which was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
 
@@ -1848,7 +1856,7 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;}
       || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "failed to load site script $ac_site_file
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
   fi
 done
 
@@ -1946,7 +1954,7 @@ rt_version_major=4
 
 rt_version_minor=0
 
-rt_version_patch=6
+rt_version_patch=7
 
 test "x$rt_version_major" = 'x' && rt_version_major=0
 test "x$rt_version_minor" = 'x' && rt_version_minor=0
@@ -1998,7 +2006,7 @@ ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
 $as_echo_n "checking for a BSD-compatible install... " >&6; }
 if test -z "$INSTALL"; then
-if test "${ac_cv_path_install+set}" = set; then :
+if ${ac_cv_path_install+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -2079,7 +2087,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 set dummy perl; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_PERL+set}" = set; then :
+if ${ac_cv_path_PERL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $PERL in
@@ -2800,7 +2808,7 @@ if test -n "$ac_tool_prefix"; then
 set dummy ${ac_tool_prefix}gcc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -2840,7 +2848,7 @@ if test -z "$ac_cv_prog_CC"; then
 set dummy gcc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
@@ -2893,7 +2901,7 @@ if test -z "$CC"; then
 set dummy ${ac_tool_prefix}cc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -2933,7 +2941,7 @@ if test -z "$CC"; then
 set dummy cc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -2992,7 +3000,7 @@ if test -z "$CC"; then
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -3036,7 +3044,7 @@ do
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
@@ -3091,7 +3099,7 @@ fi
 test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 
 # Provide some information about the compiler.
 $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
@@ -3206,7 +3214,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error 77 "C compiler cannot create executables
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
@@ -3249,7 +3257,7 @@ else
   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 rm -f conftest conftest$ac_cv_exeext
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -3308,7 +3316,7 @@ $as_echo "$ac_try_echo"; } >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot run C compiled programs.
 If you meant to cross compile, use \`--host'.
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
     fi
   fi
 fi
@@ -3319,7 +3327,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
 ac_clean_files=$ac_clean_files_save
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
 $as_echo_n "checking for suffix of object files... " >&6; }
-if test "${ac_cv_objext+set}" = set; then :
+if ${ac_cv_objext+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3360,7 +3368,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 rm -f conftest.$ac_cv_objext conftest.$ac_ext
 fi
@@ -3370,7 +3378,7 @@ OBJEXT=$ac_cv_objext
 ac_objext=$OBJEXT
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+if ${ac_cv_c_compiler_gnu+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3407,7 +3415,7 @@ ac_test_CFLAGS=${CFLAGS+set}
 ac_save_CFLAGS=$CFLAGS
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
 $as_echo_n "checking whether $CC accepts -g... " >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then :
+if ${ac_cv_prog_cc_g+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_save_c_werror_flag=$ac_c_werror_flag
@@ -3485,7 +3493,7 @@ else
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then :
+if ${ac_cv_prog_cc_c89+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_prog_cc_c89=no
@@ -3583,7 +3591,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for aginitlib in -lgraph" >&5
 $as_echo_n "checking for aginitlib in -lgraph... " >&6; }
-if test "${ac_cv_lib_graph_aginitlib+set}" = set; then :
+if ${ac_cv_lib_graph_aginitlib+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -3617,7 +3625,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_graph_aginitlib" >&5
 $as_echo "$ac_cv_lib_graph_aginitlib" >&6; }
-if test "x$ac_cv_lib_graph_aginitlib" = x""yes; then :
+if test "x$ac_cv_lib_graph_aginitlib" = xyes; then :
   RT_GRAPHVIZ="1"
 fi
 
@@ -3643,7 +3651,7 @@ fi
 set dummy gdlib-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_RT_GD+set}" = set; then :
+if ${ac_cv_prog_RT_GD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$RT_GD"; then
@@ -3699,7 +3707,7 @@ fi
 set dummy gpg; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_RT_GPG+set}" = set; then :
+if ${ac_cv_prog_RT_GPG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$RT_GPG"; then
@@ -3984,10 +3992,21 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      :end' >>confcache
 if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
   if test -w "$cache_file"; then
-    test "x$cache_file" != "x/dev/null" &&
+    if test "x$cache_file" != "x/dev/null"; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
 $as_echo "$as_me: updating cache $cache_file" >&6;}
-    cat confcache >$cache_file
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
   else
     { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
@@ -4055,7 +4074,7 @@ LTLIBOBJS=$ac_ltlibobjs
 
 
 
-: ${CONFIG_STATUS=./config.status}
+: "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
 ac_clean_files_save=$ac_clean_files
 ac_clean_files="$ac_clean_files $CONFIG_STATUS"
@@ -4156,6 +4175,7 @@ fi
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
 case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -4462,8 +4482,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by RT $as_me rt-4.0.6, which was
-generated by GNU Autoconf 2.67.  Invocation command line was
+This file was extended by RT $as_me rt-4.0.7, which was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -4515,8 +4535,8 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-RT config.status rt-4.0.6
-configured by $0, generated by GNU Autoconf 2.67,
+RT config.status rt-4.0.7
+configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -4658,7 +4678,7 @@ do
     "t/data/configs/apache2.2+mod_perl.conf") CONFIG_FILES="$CONFIG_FILES t/data/configs/apache2.2+mod_perl.conf" ;;
     "t/data/configs/apache2.2+fastcgi.conf") CONFIG_FILES="$CONFIG_FILES t/data/configs/apache2.2+fastcgi.conf" ;;
 
-  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
 done
 
@@ -4679,9 +4699,10 @@ fi
 # after its creation but before its name has been assigned to `$tmp'.
 $debug ||
 {
-  tmp=
+  tmp= ac_tmp=
   trap 'exit_status=$?
-  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
 ' 0
   trap 'as_fn_exit 1' 1 2 13 15
 }
@@ -4689,12 +4710,13 @@ $debug ||
 
 {
   tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
+  test -d "$tmp"
 }  ||
 {
   tmp=./conf$$-$RANDOM
   (umask 077 && mkdir "$tmp")
 } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
 
 # Set up the scripts for CONFIG_FILES section.
 # No need to generate them if there are no CONFIG_FILES.
@@ -4716,7 +4738,7 @@ else
   ac_cs_awk_cr=$ac_cr
 fi
 
-echo 'BEGIN {' >"$tmp/subs1.awk" &&
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
 _ACEOF
 
 
@@ -4744,7 +4766,7 @@ done
 rm -f conf$$subs.sh
 
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
 _ACEOF
 sed -n '
 h
@@ -4792,7 +4814,7 @@ t delim
 rm -f conf$$subs.awk
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 _ACAWK
-cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
   for (key in S) S_is_set[key] = 1
   FS = ""
 
@@ -4824,7 +4846,7 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
   sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
 else
   cat
-fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
   || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
 _ACEOF
 
@@ -4864,7 +4886,7 @@ do
   esac
   case $ac_mode$ac_tag in
   :[FHL]*:*);;
-  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
   :[FH]-) ac_tag=-:-;;
   :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
   esac
@@ -4883,7 +4905,7 @@ do
     for ac_f
     do
       case $ac_f in
-      -) ac_f="$tmp/stdin";;
+      -) ac_f="$ac_tmp/stdin";;
       *) # Look for the file first in the build tree, then in the source tree
 	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
 	 # because $ac_f cannot contain `:'.
@@ -4892,7 +4914,7 @@ do
 	   [\\/$]*) false;;
 	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
 	   esac ||
-	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
       esac
       case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
       as_fn_append ac_file_inputs " '$ac_f'"
@@ -4918,8 +4940,8 @@ $as_echo "$as_me: creating $ac_file" >&6;}
     esac
 
     case $ac_tag in
-    *:-:* | *:-) cat >"$tmp/stdin" \
-      || as_fn_error $? "could not create $ac_file" "$LINENO" 5  ;;
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
     esac
     ;;
   esac
@@ -5049,21 +5071,22 @@ s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
 s&@INSTALL@&$ac_INSTALL&;t t
 $ac_datarootdir_hack
 "
-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
-  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 
 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
-  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
-  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&5
 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&2;}
 
-  rm -f "$tmp/stdin"
+  rm -f "$ac_tmp/stdin"
   case $ac_file in
-  -) cat "$tmp/out" && rm -f "$tmp/out";;
-  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
   esac \
   || as_fn_error $? "could not create $ac_file" "$LINENO" 5
  ;;
diff --git a/rt/docs/web_deployment.pod b/rt/docs/web_deployment.pod
index 4c3f73f..5d2cd4c 100644
--- a/rt/docs/web_deployment.pod
+++ b/rt/docs/web_deployment.pod
@@ -23,7 +23,7 @@ to use L<Starman>, a high performance preforking server:
     /opt/rt4/sbin/rt-server --server Starman --port 8080
 
 B<NOTICE>: After you run the standalone server as root, you will need to
-remove your C<var/mason> directory, or the non-standalone servers
+remove your C<var/mason_data> directory, or the non-standalone servers
 (Apache, etc), which run as a non-privileged user, will not be able to
 write to it and will not work.
 
diff --git a/rt/etc/initialdata b/rt/etc/initialdata
index cc07cec..7ab746d 100644
--- a/rt/etc/initialdata
+++ b/rt/etc/initialdata
@@ -1,4 +1,4 @@
-# Initial data for a fresh RT3 Installation.
+# Initial data for a fresh RT installation.
 
 @Users = (
     {  Name         => 'root',
diff --git a/rt/etc/schema.SQLite b/rt/etc/schema.SQLite
index 138971c..6897be2 100644
--- a/rt/etc/schema.SQLite
+++ b/rt/etc/schema.SQLite
@@ -3,7 +3,7 @@
 CREATE TABLE Attachments (
   id INTEGER PRIMARY KEY  ,
   TransactionId INTEGER  ,
-  Parent integer NULL  ,
+  Parent integer NULL DEFAULT 0 ,
   MessageId varchar(160) NULL  ,
   Subject varchar(255) NULL  ,
   Filename varchar(255) NULL  ,
@@ -11,7 +11,7 @@ CREATE TABLE Attachments (
   ContentEncoding varchar(80) NULL  ,
   Content LONGTEXT NULL  ,
   Headers LONGTEXT NULL  ,
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL 
   
 ) ;
@@ -30,12 +30,12 @@ CREATE TABLE Queues (
   CommentAddress varchar(120) NULL  ,
   Lifecycle varchar(32) NULL  ,
   SubjectTag varchar(120) NULL  ,
-  InitialPriority integer NULL  ,
-  FinalPriority integer NULL  ,
-  DefaultDueIn integer NULL  ,
-  Creator integer NULL  ,
+  InitialPriority integer NULL DEFAULT 0 ,
+  FinalPriority integer NULL DEFAULT 0 ,
+  DefaultDueIn integer NULL DEFAULT 0 ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  ,
   Disabled int2 NOT NULL DEFAULT 0 
  
@@ -51,11 +51,11 @@ CREATE TABLE Links (
   Base varchar(240) NULL  ,
   Target varchar(240) NULL  ,
   Type varchar(20) NOT NULL  ,
-  LocalTarget integer NULL  ,
-  LocalBase integer NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LocalTarget integer NULL DEFAULT 0 ,
+  LocalBase integer NULL DEFAULT 0 ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  ,
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  
   
 ) ;
@@ -106,9 +106,9 @@ CREATE TABLE ScripConditions (
   Argument varchar(255) NULL  ,
   ApplicableTransTypes varchar(60) NULL  ,
 
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
   
 ) ;
@@ -119,8 +119,8 @@ CREATE TABLE ScripConditions (
 CREATE TABLE Transactions (
   id INTEGER PRIMARY KEY  ,
   ObjectType varchar(255) NULL  ,
-  ObjectId integer NULL  ,
-  TimeTaken integer NULL  ,
+  ObjectId integer NULL DEFAULT 0 ,
+  TimeTaken integer NULL DEFAULT 0 ,
   Type varchar(20) NULL  ,
   Field varchar(40) NULL  ,
   OldValue varchar(255) NULL  ,
@@ -130,7 +130,7 @@ CREATE TABLE Transactions (
   NewReference integer NULL  ,
   Data varchar(255) NULL  ,
 
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  
   
 ) ;
@@ -143,19 +143,19 @@ CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
 CREATE TABLE Scrips (
   id INTEGER PRIMARY KEY  ,
   Description varchar(255),
-  ScripCondition integer NULL  ,
-  ScripAction integer NULL  ,
+  ScripCondition integer NULL DEFAULT 0 ,
+  ScripAction integer NULL DEFAULT 0 ,
   ConditionRules text NULL  ,
   ActionRules text NULL  ,
   CustomIsApplicableCode text NULL  ,
   CustomPrepareCode text NULL  ,
   CustomCommitCode text NULL  ,
   Stage varchar(32) NULL  ,
-  Queue integer NULL  ,
-  Template integer NULL  ,
-  Creator integer NULL  ,
+  Queue integer NULL DEFAULT 0 ,
+  Template integer NULL DEFAULT 0 ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
   
 ) ;
@@ -167,7 +167,7 @@ CREATE TABLE ACL (
   id INTEGER PRIMARY KEY  ,
   PrincipalType varchar(25) NOT NULL,
 
-  PrincipalId INTEGER,
+  PrincipalId INTEGER DEFAULT 0,
   RightName varchar(25) NOT NULL  ,
   ObjectType varchar(25) NOT NULL  ,
   ObjectId INTEGER default 0,
@@ -185,8 +185,8 @@ CREATE TABLE ACL (
 
 CREATE TABLE GroupMembers (
   id INTEGER PRIMARY KEY  ,
-  GroupId integer NULL,
-  MemberId integer NULL,
+  GroupId integer NULL DEFAULT 0,
+  MemberId integer NULL DEFAULT 0,
   Creator integer NOT NULL DEFAULT 0  ,
   Created DATETIME NULL  ,
   LastUpdatedBy integer NOT NULL DEFAULT 0  ,
@@ -250,9 +250,9 @@ CREATE TABLE Users (
   Timezone char(50) NULL  ,
   PGPKey text NULL,
 
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
   
 ) ;
@@ -270,20 +270,20 @@ CREATE INDEX Users4 ON Users (EmailAddress);
 
 CREATE TABLE Tickets (
   id INTEGER PRIMARY KEY  ,
-  EffectiveId integer NULL  ,
-  Queue integer NULL  ,
+  EffectiveId integer NULL DEFAULT 0 ,
+  Queue integer NULL DEFAULT 0 ,
   Type varchar(16) NULL  ,
-  IssueStatement integer NULL  ,
-  Resolution integer NULL  ,
-  Owner integer NULL  ,
+  IssueStatement integer NULL DEFAULT 0 ,
+  Resolution integer NULL DEFAULT 0 ,
+  Owner integer NULL DEFAULT 0 ,
   Subject varchar(200) NULL DEFAULT '[no subject]' ,
-  InitialPriority integer NULL  ,
-  FinalPriority integer NULL  ,
-  Priority integer NULL  ,
-  TimeEstimated integer NULL  ,
-  TimeWorked integer NULL  ,
+  InitialPriority integer NULL DEFAULT 0 ,
+  FinalPriority integer NULL DEFAULt 0 ,
+  Priority integer NULL DEFAULT 0 ,
+  TimeEstimated integer NULL DEFAULT 0 ,
+  TimeWorked integer NULL DEFAULT 0 ,
   Status varchar(64) NULL  ,
-  TimeLeft integer NULL  ,
+  TimeLeft integer NULL DEFAULT 0 ,
   Told DATETIME NULL  ,
   Starts DATETIME NULL  ,
   Started DATETIME NULL  ,
@@ -291,9 +291,9 @@ CREATE TABLE Tickets (
   Resolved DATETIME NULL  ,
 
 
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  ,
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
   Disabled int2 NOT NULL DEFAULT 0
   
@@ -315,9 +315,9 @@ CREATE TABLE ScripActions (
   Description varchar(255) NULL  ,
   ExecModule varchar(60) NULL  ,
   Argument varchar(255) NULL  ,
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
   
 ) ;
@@ -333,11 +333,11 @@ CREATE TABLE Templates (
   Description varchar(255) NULL  ,
   Type varchar(16) NULL  ,
   Language varchar(16) NULL  ,
-  TranslationOf integer NULL  ,
+  TranslationOf integer NULL DEFAULT 0 ,
   Content blob NULL  ,
   LastUpdated DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
-  Creator integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  
   
 ) ;
@@ -437,10 +437,10 @@ CREATE TABLE Attributes (
   Content LONGTEXT NULL  ,
   ContentType varchar(16),
   ObjectType varchar(25) NOT NULL  ,
-  ObjectId INTEGER default 0,
-  Creator integer NULL  ,
+  ObjectId INTEGER ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
  
 ) ;
@@ -483,22 +483,22 @@ Parent integer NOT NULL DEFAULT 0,
 Name varchar(255) NOT NULL DEFAULT '',
 Description varchar(255) NOT NULL DEFAULT '',
 ObjectType varchar(64) NOT NULL DEFAULT '',
-ObjectId integer NOT NULL
+ObjectId integer NOT NULL DEFAULT 0
 );
 
 
 CREATE TABLE ObjectTopics (
 id INTEGER PRIMARY KEY,
-Topic integer NOT NULL,
+Topic integer NOT NULL DEFAULT 0,
 ObjectType varchar(64) NOT NULL DEFAULT '',
-ObjectId integer NOT NULL
+ObjectId integer NOT NULL DEFAULT 0
 );
 
 CREATE TABLE ObjectClasses (
 id INTEGER PRIMARY KEY,
-Class integer NOT NULL,
+Class integer NOT NULL DEFAULT 0,
 ObjectType varchar(64) NOT NULL DEFAULT '',
-ObjectId integer NOT NULL,
+ObjectId integer NOT NULL DEFAULT 0,
 Creator integer NOT NULL DEFAULT 0,
 Created TIMESTAMP NULL,
 LastUpdatedBy integer NOT NULL DEFAULT 0,
diff --git a/rt/etc/upgrade/3.3.0/schema.mysql b/rt/etc/upgrade/3.3.0/schema.mysql
index f699836..d8b0499 100644
--- a/rt/etc/upgrade/3.3.0/schema.mysql
+++ b/rt/etc/upgrade/3.3.0/schema.mysql
@@ -1,37 +1,32 @@
-alter Table Transactions ADD Column (ObjectType varchar(64) not null);
-update Transactions set ObjectType = 'RT::Ticket';
-alter table Transactions drop column EffectiveTicket;
-alter table Transactions add column ReferenceType varchar(255) NULL;
-alter table Transactions add column OldReference integer NULL;      
-alter table Transactions add column NewReference integer NULL;
-alter table Transactions drop index transactions1;            
-alter table Transactions change Ticket ObjectId integer NOT NULL DEFAULT 0  ;
+drop index transactions1 ON Transactions;
 
-CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
-
-alter table TicketCustomFieldValues rename ObjectCustomFieldValues;
+alter Table Transactions
+    ADD COLUMN  (ObjectType varchar(64) not null),
+    DROP COLUMN EffectiveTicket,
+    ADD COLUMN  ReferenceType varchar(255) NULL,
+    ADD COLUMN  OldReference integer NULL,
+    ADD COLUMN  NewReference integer NULL,
+    CHANGE      Ticket ObjectId integer NOT NULL DEFAULT 0;
 
-alter table ObjectCustomFieldValues  change Ticket ObjectId integer NOT NULL DEFAULT 0  ;
+UPDATE Transactions set ObjectType = 'RT::Ticket';
+CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
 
-alter table ObjectCustomFieldValues add column ObjectType varchar(255) not null;
+alter table TicketCustomFieldValues rename ObjectCustomFieldValues,
+    change Ticket ObjectId integer NOT NULL DEFAULT 0  ,
+    add column ObjectType varchar(255) not null,
+    add column Current bool default 1,
+    add column LargeContent LONGTEXT NULL,
+    add column ContentType varchar(80) NULL,
+    add column ContentEncoding varchar(80) NULL;
 
 update ObjectCustomFieldValues set ObjectType = 'RT::Ticket';
 
-alter table ObjectCustomFieldValues add column Current bool default 1;  
-
-alter table ObjectCustomFieldValues add column LargeContent LONGTEXT NULL;
-
-alter table ObjectCustomFieldValues add column ContentType varchar(80) NULL;
-
-alter table ObjectCustomFieldValues add column ContentEncoding varchar(80) NULL;
-
 # These could fail if there's no such index and there's no "drop index if exists" syntax
 #alter table ObjectCustomFieldValues drop index ticketcustomfieldvalues1;
 #alter table ObjectCustomFieldValues drop index ticketcustomfieldvalues2;
 
-alter table ObjectCustomFieldValues add index ObjectCustomFieldValues1 (Content); 
-
-alter table ObjectCustomFieldValues add index ObjectCustomFieldValues2 (CustomField,ObjectType,ObjectId); 
+alter table ObjectCustomFieldValues add index ObjectCustomFieldValues1 (Content),
+    add index ObjectCustomFieldValues2 (CustomField,ObjectType,ObjectId);
 
 
 CREATE TABLE ObjectCustomFields (
@@ -50,10 +45,10 @@ CREATE TABLE ObjectCustomFields (
 
 INSERT into ObjectCustomFields (id, CustomField, ObjectId, SortOrder, Creator, LastUpdatedBy) SELECT  null, id, Queue, SortOrder, Creator, LastUpdatedBy from CustomFields;
 
-alter table CustomFields add column LookupType varchar(255) NOT NULL;
-alter table CustomFields add column Repeated int2 NOT NULL DEFAULT 0 ;
-alter table CustomFields add column Pattern varchar(255) NULL;
-alter table CustomFields add column MaxValues integer;
+alter table CustomFields add column LookupType varchar(255) NOT NULL,
+    add column Repeated int2 NOT NULL DEFAULT 0 ,
+    add column Pattern varchar(255) NULL,
+    add column MaxValues integer;
 # See above
 # alter table CustomFields drop index CustomFields1;
 
@@ -62,4 +57,4 @@ UPDATE CustomFields SET MaxValues = 1 WHERE Type LIKE '%Single';
 UPDATE CustomFields SET Type = 'Select' WHERE Type LIKE 'Select%';
 UPDATE CustomFields SET Type = 'Freeform' WHERE Type LIKE 'Freeform%';
 UPDATE CustomFields Set LookupType = 'RT::Queue-RT::Ticket';
-alter table CustomFields drop column Queue; 
+alter table CustomFields drop column Queue;
diff --git a/rt/etc/upgrade/3.3.11/schema.mysql b/rt/etc/upgrade/3.3.11/schema.mysql
index cc35d40..eff8478 100644
--- a/rt/etc/upgrade/3.3.11/schema.mysql
+++ b/rt/etc/upgrade/3.3.11/schema.mysql
@@ -1,5 +1,5 @@
-ALTER TABLE ObjectCustomFieldValues ADD COLUMN SortOrder INTEGER NOT NULL DEFAULT 0;
-ALTER TABLE ObjectCustomFieldValues ADD COLUMN Disabled int2 NOT NULL DEFAULT 0;
+ALTER TABLE ObjectCustomFieldValues ADD COLUMN SortOrder INTEGER NOT NULL DEFAULT 0,
+                                    ADD COLUMN Disabled int2 NOT NULL DEFAULT 0;
 
 UPDATE ObjectCustomFieldValues SET Disabled = 1 WHERE Current = 0;
 ALTER TABLE ObjectCustomFieldValues DROP COLUMN Current;
diff --git a/rt/etc/upgrade/3.9.5/schema.mysql b/rt/etc/upgrade/3.9.5/schema.mysql
index 4bd0907..fe5018c 100644
--- a/rt/etc/upgrade/3.9.5/schema.mysql
+++ b/rt/etc/upgrade/3.9.5/schema.mysql
@@ -6,15 +6,15 @@ AND CustomFieldValues.id = Attributes.ObjectId);
 
 DELETE FROM Attributes WHERE Name = 'Category' AND ObjectType = 'RT::CustomFieldValue';
 
-ALTER TABLE Groups ADD COLUMN Creator integer NOT NULL DEFAULT 0;
-ALTER TABLE Groups ADD COLUMN Created DATETIME NULL;
-ALTER TABLE Groups ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0;
-ALTER TABLE Groups ADD COLUMN LastUpdated DATETIME NULL;
-ALTER TABLE GroupMembers ADD COLUMN Creator integer NOT NULL DEFAULT 0;
-ALTER TABLE GroupMembers ADD COLUMN Created DATETIME NULL;
-ALTER TABLE GroupMembers ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0;
-ALTER TABLE GroupMembers ADD COLUMN LastUpdated DATETIME NULL;
-ALTER TABLE ACL ADD COLUMN Creator integer NOT NULL DEFAULT 0;
-ALTER TABLE ACL ADD COLUMN Created DATETIME NULL;
-ALTER TABLE ACL ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0;
-ALTER TABLE ACL ADD COLUMN LastUpdated DATETIME NULL;
+ALTER TABLE Groups ADD COLUMN Creator integer NOT NULL DEFAULT 0,
+    ADD COLUMN Created DATETIME NULL,
+    ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0,
+    ADD COLUMN LastUpdated DATETIME NULL;
+ALTER TABLE GroupMembers ADD COLUMN Creator integer NOT NULL DEFAULT 0,
+    ADD COLUMN Created DATETIME NULL,
+    ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0,
+    ADD COLUMN LastUpdated DATETIME NULL;
+ALTER TABLE ACL ADD COLUMN Creator integer NOT NULL DEFAULT 0,
+    ADD COLUMN Created DATETIME NULL,
+    ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0,
+    ADD COLUMN LastUpdated DATETIME NULL;
diff --git a/rt/etc/upgrade/3.9.7/schema.mysql b/rt/etc/upgrade/3.9.7/schema.mysql
index 1be1656..4cbed6c 100644
--- a/rt/etc/upgrade/3.9.7/schema.mysql
+++ b/rt/etc/upgrade/3.9.7/schema.mysql
@@ -1,6 +1,6 @@
 ALTER TABLE Users ADD COLUMN AuthToken VARCHAR(16) CHARACTER SET ascii NULL;
-ALTER TABLE CustomFields ADD COLUMN BasedOn INTEGER NULL;
-ALTER TABLE CustomFields ADD COLUMN RenderType VARCHAR(64) NULL;
-ALTER TABLE CustomFields ADD COLUMN ValuesClass VARCHAR(64) CHARACTER SET ascii NULL;
-ALTER TABLE Queues ADD COLUMN SubjectTag VARCHAR(120) NULL;
-ALTER TABLE Queues ADD COLUMN Lifecycle VARCHAR(32) NULL;
+ALTER TABLE CustomFields ADD COLUMN BasedOn INTEGER NULL,
+    ADD COLUMN RenderType VARCHAR(64) NULL,
+    ADD COLUMN ValuesClass VARCHAR(64) CHARACTER SET ascii NULL;
+ALTER TABLE Queues ADD COLUMN SubjectTag VARCHAR(120) NULL,
+    ADD COLUMN Lifecycle VARCHAR(32) NULL;
diff --git a/rt/lib/RT/Action/CreateTickets.pm b/rt/lib/RT/Action/CreateTickets.pm
index 31489c8..efd2bda 100644
--- a/rt/lib/RT/Action/CreateTickets.pm
+++ b/rt/lib/RT/Action/CreateTickets.pm
@@ -567,7 +567,8 @@ sub Parse {
         $self->_ParseMultilineTemplate(%args);
     } elsif ( $args{'Content'} =~ /(?:\t|,)/i ) {
         $self->_ParseXSVTemplate(%args);
-
+    } else {
+        RT->Logger->error("Invalid Template Content (Couldn't find ===, and is not a csv/tsv template) - unable to parse: $args{Content}");
     }
 }
 
diff --git a/rt/lib/RT/Articles.pm b/rt/lib/RT/Articles.pm
index 8dd661d..47d0ebe 100644
--- a/rt/lib/RT/Articles.pm
+++ b/rt/lib/RT/Articles.pm
@@ -360,6 +360,7 @@ sub LimitCustomField {
             QUOTEVALUE      => $args{'QUOTEVALUE'},
             ENTRYAGGREGATOR => 'AND', #$args{'ENTRYAGGREGATOR'},
             SUBCLAUSE       => $clause,
+            CASESENSITIVE   => 0,
         );
         $self->SUPER::Limit(
             ALIAS           => $ObjectValuesAlias,
@@ -380,6 +381,7 @@ sub LimitCustomField {
             QUOTEVALUE      => $args{'QUOTEVALUE'},
             ENTRYAGGREGATOR => $args{'ENTRYAGGREGATOR'},
             SUBCLAUSE       => $clause,
+            CASESENSITIVE   => 0,
         );
         $self->SUPER::Limit(
             ALIAS           => $ObjectValuesAlias,
@@ -389,6 +391,7 @@ sub LimitCustomField {
             QUOTEVALUE      => $args{'QUOTEVALUE'},
             ENTRYAGGREGATOR => $args{'ENTRYAGGREGATOR'},
             SUBCLAUSE       => $clause,
+            CASESENSITIVE   => 0,
         );
     }
 }
diff --git a/rt/lib/RT/Config.pm b/rt/lib/RT/Config.pm
index f87ef84..014c764 100644
--- a/rt/lib/RT/Config.pm
+++ b/rt/lib/RT/Config.pm
@@ -411,8 +411,8 @@ our %META = (
             Description => q|What tickets to display in the 'More about requestor' box|,                #loc
             Values      => [qw(Active Inactive All None)],
             ValuesLabel => {
-                Active   => "Show the Requestor's 10 highest priority open tickets",                  #loc
-                Inactive => "Show the Requestor's 10 highest priority closed tickets",      #loc
+                Active   => "Show the Requestor's 10 highest priority active tickets",                  #loc
+                Inactive => "Show the Requestor's 10 highest priority inactive tickets",      #loc
                 All      => "Show the Requestor's 10 highest priority tickets",      #loc
                 None     => "Show no tickets for the Requestor", #loc
             },
@@ -749,7 +749,7 @@ our %META = (
 
             my %seen;
             foreach my $encoding ( grep defined && length, splice @$value ) {
-                next if $seen{ $encoding }++;
+                next if $seen{ $encoding };
                 if ( $encoding eq '*' ) {
                     unshift @$value, '*';
                     next;
diff --git a/rt/lib/RT/Crypt/GnuPG.pm b/rt/lib/RT/Crypt/GnuPG.pm
index ab444d0..c5fb12b 100644
--- a/rt/lib/RT/Crypt/GnuPG.pm
+++ b/rt/lib/RT/Crypt/GnuPG.pm
@@ -1683,6 +1683,7 @@ my %ignore_keyword = map { $_ => 1 } qw(
     BEGIN_ENCRYPTION SIG_ID VALIDSIG
     ENC_TO BEGIN_DECRYPTION END_DECRYPTION GOODMDC
     TRUST_UNDEFINED TRUST_NEVER TRUST_MARGINAL TRUST_FULLY TRUST_ULTIMATE
+    DECRYPTION_INFO
 );
 
 sub ParseStatus {
diff --git a/rt/lib/RT/Dashboard.pm b/rt/lib/RT/Dashboard.pm
index 14ffa6a..2e2bbc4 100644
--- a/rt/lib/RT/Dashboard.pm
+++ b/rt/lib/RT/Dashboard.pm
@@ -454,6 +454,36 @@ sub CurrentUserCanCreateAny {
     return 0;
 }
 
+=head2 Delete
+
+Deletes the dashboard and related subscriptions.
+Returns a tuple of status and message, where status is true upon success.
+
+=cut
+
+sub Delete {
+    my $self = shift;
+    my $id = $self->id;
+    my ( $status, $msg ) = $self->SUPER::Delete(@_);
+    if ( $status ) {
+        # delete all the subscriptions
+        my $subscriptions = RT::Attributes->new( RT->SystemUser );
+        $subscriptions->Limit(
+            FIELD => 'Name',
+            VALUE => 'Subscription',
+        );
+        $subscriptions->Limit(
+            FIELD => 'Description',
+            VALUE => "Subscription to dashboard $id",
+        );
+        while ( my $subscription = $subscriptions->Next ) {
+            $subscription->Delete();
+        }
+    }
+
+    return ( $status, $msg );
+}
+
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/rt/lib/RT/Generated.pm b/rt/lib/RT/Generated.pm
index 2abcf3b..9fd946f 100644
--- a/rt/lib/RT/Generated.pm
+++ b/rt/lib/RT/Generated.pm
@@ -50,7 +50,7 @@ package RT;
 use warnings;
 use strict;
 
-our $VERSION = '4.0.6';
+our $VERSION = '4.0.7';
 
 
 
diff --git a/rt/lib/RT/I18N.pm b/rt/lib/RT/I18N.pm
index cadf7cc..e453cfa 100644
--- a/rt/lib/RT/I18N.pm
+++ b/rt/lib/RT/I18N.pm
@@ -227,7 +227,7 @@ sub SetMIMEEntityToEncoding {
 
     my $body = $entity->bodyhandle;
 
-    if ( $enc ne $charset && $body ) {
+    if ( $body && ($enc ne $charset || $enc =~ /^utf-?8(?:-strict)?$/i) ) {
         my $string = $body->as_string or return;
 
         $RT::Logger->debug( "Converting '$charset' to '$enc' for "
@@ -335,7 +335,7 @@ sub DecodeMIMEWordsToEncoding {
             }
 
             # now we have got a decoded subject, try to convert into the encoding
-            unless ( $charset eq $to_charset ) {
+            if ( $charset ne $to_charset || $charset =~ /^utf-?8(?:-strict)?$/i ) {
                 Encode::from_to( $enc_str, $charset, $to_charset );
             }
 
@@ -537,7 +537,7 @@ sub SetMIMEHeadToEncoding {
         my @values = $head->get_all($tag);
         $head->delete($tag);
         foreach my $value (@values) {
-            if ( $charset ne $enc ) {
+            if ( $charset ne $enc || $enc =~ /^utf-?8(?:-strict)?$/i ) {
                 Encode::_utf8_off($value);
                 Encode::from_to( $value, $charset => $enc );
             }
diff --git a/rt/lib/RT/Interface/Email.pm b/rt/lib/RT/Interface/Email.pm
index 02a1ec0..4c3ee99 100755
--- a/rt/lib/RT/Interface/Email.pm
+++ b/rt/lib/RT/Interface/Email.pm
@@ -787,7 +787,7 @@ sub GetForwardFrom {
     my $ticket = $args{Ticket} || $txn->Object;
 
     if ( RT->Config->Get('ForwardFromUser') ) {
-        return ( $txn || $ticket )->CurrentUser->UserObj->EmailAddress;
+        return ( $txn || $ticket )->CurrentUser->EmailAddress;
     }
     else {
         return $ticket->QueueObj->CorrespondAddress
@@ -1221,8 +1221,16 @@ sub SetInReplyTo {
         if @references > 10;
 
     my $mail = $args{'Message'};
-    $mail->head->set( 'In-Reply-To' => join ' ', @rtid? (@rtid) : (@id) ) if @id || @rtid;
-    $mail->head->set( 'References' => join ' ', @references );
+    $mail->head->set( 'In-Reply-To' => Encode::encode_utf8(join ' ', @rtid? (@rtid) : (@id)) ) if @id || @rtid;
+    $mail->head->set( 'References' => Encode::encode_utf8(join ' ', @references) );
+}
+
+sub ExtractTicketId {
+    my $entity = shift;
+
+    my $subject = $entity->head->get('Subject') || '';
+    chomp $subject;
+    return ParseTicketId( $subject );
 }
 
 sub ParseTicketId {
@@ -1448,7 +1456,7 @@ sub Gateway {
     }
     # }}}
 
-    $args{'ticket'} ||= ParseTicketId( $Subject );
+    $args{'ticket'} ||= ExtractTicketId( $Message );
 
     $SystemTicket = RT::Ticket->new( RT->SystemUser );
     $SystemTicket->Load( $args{'ticket'} ) if ( $args{'ticket'} ) ;
@@ -1704,17 +1712,20 @@ sub _RunUnsafeAction {
             return ( 0, "Ticket not taken" );
         }
     } elsif ( $args{'Action'} =~ /^resolve$/i ) {
-        my ( $status, $msg ) = $args{'Ticket'}->SetStatus('resolved');
-        unless ($status) {
+        my $new_status = $args{'Ticket'}->FirstInactiveStatus;
+        if ($new_status) {
+            my ( $status, $msg ) = $args{'Ticket'}->SetStatus($new_status);
+            unless ($status) {
 
-            #Warn the sender that we couldn't actually submit the comment.
-            MailError(
-                To          => $args{'ErrorsTo'},
-                Subject     => "Ticket not resolved",
-                Explanation => $msg,
-                MIMEObj     => $args{'Message'}
-            );
-            return ( 0, "Ticket not resolved" );
+                #Warn the sender that we couldn't actually submit the comment.
+                MailError(
+                    To          => $args{'ErrorsTo'},
+                    Subject     => "Ticket not resolved",
+                    Explanation => $msg,
+                    MIMEObj     => $args{'Message'}
+                );
+                return ( 0, "Ticket not resolved" );
+            }
         }
     } else {
         return ( 0, "Not supported unsafe action $args{'Action'}", $args{'Ticket'} );
diff --git a/rt/lib/RT/Interface/Web.pm b/rt/lib/RT/Interface/Web.pm
index 94da307..1aae758 100644
--- a/rt/lib/RT/Interface/Web.pm
+++ b/rt/lib/RT/Interface/Web.pm
@@ -261,7 +261,15 @@ sub HandleRequest {
 
     $HTML::Mason::Commands::m->comp( '/Elements/SetupSessionCookie', %$ARGS );
     SendSessionCookie();
-    $HTML::Mason::Commands::session{'CurrentUser'} = RT::CurrentUser->new() unless _UserLoggedIn();
+
+    if ( _UserLoggedIn() ) {
+        # make user info up to date
+        $HTML::Mason::Commands::session{'CurrentUser'}
+          ->Load( $HTML::Mason::Commands::session{'CurrentUser'}->id );
+    }
+    else {
+        $HTML::Mason::Commands::session{'CurrentUser'} = RT::CurrentUser->new();
+    }
 
     # Process session-related callbacks before any auth attempts
     $HTML::Mason::Commands::m->callback( %$ARGS, CallbackName => 'Session', CallbackPage => '/autohandler' );
@@ -287,7 +295,7 @@ sub HandleRequest {
             my $m = $HTML::Mason::Commands::m;
 
             # REST urls get a special 401 response
-            if ($m->request_comp->path =~ '^/REST/\d+\.\d+/') {
+            if ($m->request_comp->path =~ m{^/REST/\d+\.\d+/}) {
                 $HTML::Mason::Commands::r->content_type("text/plain");
                 $m->error_format("text");
                 $m->out("RT/$RT::VERSION 401 Credentials required\n");
@@ -457,7 +465,7 @@ sub MaybeShowInstallModePage {
     my $m = $HTML::Mason::Commands::m;
     if ( $m->base_comp->path =~ RT->Config->Get('WebNoAuthRegex') ) {
         $m->call_next();
-    } elsif ( $m->request_comp->path !~ '^(/+)Install/' ) {
+    } elsif ( $m->request_comp->path !~ m{^(/+)Install/} ) {
         RT::Interface::Web::Redirect( RT->Config->Get('WebURL') . "Install/index.html" );
     } else {
         $m->call_next();
@@ -557,7 +565,7 @@ sub ShowRequestedPage {
     unless ( $HTML::Mason::Commands::session{'CurrentUser'}->Privileged ) {
 
         # if the user is trying to access a ticket, redirect them
-        if ( $m->request_comp->path =~ '^(/+)Ticket/Display.html' && $ARGS->{'id'} ) {
+        if ( $m->request_comp->path =~ m{^(/+)Ticket/Display.html} && $ARGS->{'id'} ) {
             RT::Interface::Web::Redirect( RT->Config->Get('WebURL') . "SelfService/Display.html?id=" . $ARGS->{'id'} );
         }
 
@@ -659,7 +667,7 @@ sub AttemptExternalAuth {
             delete $HTML::Mason::Commands::session{'CurrentUser'};
             $user = $orig_user;
 
-            if ( RT->Config->Get('WebExternalOnly') ) {
+            unless ( RT->Config->Get('WebFallbackToInternalAuth') ) {
                 TangentForLoginWithError('You are not an authorized user');
             }
         }
@@ -970,7 +978,7 @@ sub MobileClient {
     my $self = shift;
 
 
-if (($ENV{'HTTP_USER_AGENT'} || '') =~ /(?:hiptop|Blazer|Novarra|Vagabond|SonyEricsson|Symbian|NetFront|UP.Browser|UP.Link|Windows CE|MIDP|J2ME|DoCoMo|J-PHONE|PalmOS|PalmSource|iPhone|iPod|AvantGo|Nokia|Android|WebOS|S60)/io && !$HTML::Mason::Commands::session{'NotMobile'})  {
+if (($ENV{'HTTP_USER_AGENT'} || '') =~ /(?:hiptop|Blazer|Novarra|Vagabond|SonyEricsson|Symbian|NetFront|UP.Browser|UP.Link|Windows CE|MIDP|J2ME|DoCoMo|J-PHONE|PalmOS|PalmSource|iPhone|iPod|AvantGo|Nokia|Android|WebOS|S60|Mobile)/io && !$HTML::Mason::Commands::session{'NotMobile'})  {
     return 1;
 } else {
     return undef;
@@ -1183,6 +1191,14 @@ our %is_whitelisted_component = (
     # information for the search.  Because it's a straight-up read, in
     # addition to embedding its own auth, it's fine.
     '/NoAuth/rss/dhandler' => 1,
+
+    # While these can be used for denial-of-service against RT
+    # (construct a very inefficient query and trick lots of users into
+    # running them against RT) it's incredibly useful to be able to link
+    # to a search result or bookmark a result page.
+    '/Search/Results.html' => 1,
+    '/Search/Simple.html'  => 1,
+    '/m/tickets/search'     => 1,
 );
 
 sub IsCompCSRFWhitelisted {
@@ -1237,7 +1253,19 @@ sub IsRefererCSRFWhitelisted {
     my $configs;
     for my $config ( $base_url, RT->Config->Get('ReferrerWhitelist') ) {
         push @$configs,$config;
-        return 1 if $referer->host_port eq $config;
+
+        my $host_port = $referer->host_port;
+        if ($config =~ /\*/) {
+            # Turn a literal * into a domain component or partial component match.
+            # Refer to http://tools.ietf.org/html/rfc2818#page-5
+            my $regex = join "[a-zA-Z0-9\-]*",
+                         map { quotemeta($_) }
+                       split /\*/, $config;
+
+            return 1 if $host_port =~ /^$regex$/i;
+        } else {
+            return 1 if $host_port eq $config;
+        }
     }
 
     return (0,$referer,$configs);
@@ -1962,7 +1990,7 @@ sub MakeMIMEEntity {
     );
     my $Message = MIME::Entity->build(
         Type    => 'multipart/mixed',
-        "Message-Id" => RT::Interface::Email::GenMessageId,
+        "Message-Id" => Encode::encode_utf8( RT::Interface::Email::GenMessageId ),
         map { $_ => Encode::encode_utf8( $args{ $_} ) }
             grep defined $args{$_}, qw(Subject From Cc)
     );
diff --git a/rt/lib/RT/Record.pm b/rt/lib/RT/Record.pm
index e134178..fd238de 100755
--- a/rt/lib/RT/Record.pm
+++ b/rt/lib/RT/Record.pm
@@ -639,6 +639,8 @@ sub __Value {
 
     my $value = $self->SUPER::__Value($field);
 
+    return undef if (!defined $value);
+
     if ( $args{'decode_utf8'} ) {
         if ( !utf8::is_utf8($value) ) {
             utf8::decode($value);
@@ -1675,7 +1677,7 @@ sub _AddCustomFieldValue {
             0,
             $self->loc(
                 "Custom field [_1] does not apply to this object",
-                $args{'Field'}
+                ref $args{'Field'} ? $args{'Field'}->id : $args{'Field'}
             )
         );
     }
diff --git a/rt/lib/RT/Scrip.pm b/rt/lib/RT/Scrip.pm
index 9506616..8f97e74 100755
--- a/rt/lib/RT/Scrip.pm
+++ b/rt/lib/RT/Scrip.pm
@@ -545,7 +545,7 @@ sub _Set {
         }
     }
 
-    return $self->__Set(@_);
+    return $self->SUPER::_Set(@_);
 }
 
 
diff --git a/rt/lib/RT/Scrips.pm b/rt/lib/RT/Scrips.pm
index 13a4b7d..fa33f7e 100755
--- a/rt/lib/RT/Scrips.pm
+++ b/rt/lib/RT/Scrips.pm
@@ -178,16 +178,6 @@ Commit all of this object's prepared scrips
 sub Commit {
     my $self = shift;
 
-    # RT::Scrips->_SetupSourceObjects will clobber
-    # the CurrentUser, but we need to keep this ticket
-    # so that the _TransactionBatch cache is maintained
-    # and doesn't run twice.  sigh.
-    $self->_StashCurrentUser( TicketObj => $self->{TicketObj} ) if $self->{TicketObj};
-
-    #We're really going to need a non-acled ticket for the scrips to work
-    $self->_SetupSourceObjects( TicketObj      => $self->{'TicketObj'},
-                                TransactionObj => $self->{'TransactionObj'} );
-    
     foreach my $scrip (@{$self->Prepared}) {
         $RT::Logger->debug(
             "Committing scrip #". $scrip->id
@@ -199,8 +189,6 @@ sub Commit {
                         TransactionObj => $self->{'TransactionObj'} );
     }
 
-    # Apply the bandaid.
-    $self->_RestoreCurrentUser( TicketObj => $self->{TicketObj} ) if $self->{TicketObj};
 }
 
 
@@ -221,12 +209,6 @@ sub Prepare {
                  Type           => undef,
                  @_ );
 
-    # RT::Scrips->_SetupSourceObjects will clobber
-    # the CurrentUser, but we need to keep this ticket
-    # so that the _TransactionBatch cache is maintained
-    # and doesn't run twice.  sigh.
-    $self->_StashCurrentUser( TicketObj => $args{TicketObj} ) if $args{TicketObj};
-
     #We're really going to need a non-acled ticket for the scrips to work
     $self->_SetupSourceObjects( TicketObj      => $args{'TicketObj'},
                                 Ticket         => $args{'Ticket'},
@@ -259,10 +241,6 @@ sub Prepare {
 
     }
 
-    # Apply the bandaid.
-    $self->_RestoreCurrentUser( TicketObj => $args{TicketObj} ) if $args{TicketObj};
-
-
     return (@{$self->Prepared});
 
 };
@@ -279,40 +257,6 @@ sub Prepared {
     return ($self->{'prepared_scrips'} || []);
 }
 
-=head2 _StashCurrentUser TicketObj => RT::Ticket
-
-Saves aside the current user of the original ticket that was passed to these scrips.
-This is used to make sure that we don't accidentally leak the RT_System current user
-back to the calling code.
-
-=cut
-
-sub _StashCurrentUser {
-    my $self = shift;
-    my %args = @_;
-
-    $self->{_TicketCurrentUser} = $args{TicketObj}->CurrentUser;
-}
-
-=head2 _RestoreCurrentUser TicketObj => RT::Ticket
-
-Uses the current user saved by _StashCurrentUser to reset a Ticket object
-back to the caller's current user and avoid leaking an RT_System ticket to
-calling code.
-
-=cut
-
-sub _RestoreCurrentUser {
-    my $self = shift;
-    my %args = @_;
-    unless ( $self->{_TicketCurrentUser} ) {
-        RT->Logger->debug("Called _RestoreCurrentUser without a stashed current user object");
-        return;
-    }
-    $args{TicketObj}->CurrentUser($self->{_TicketCurrentUser});
-
-}
-
 =head2  _SetupSourceObjects { TicketObj , Ticket, Transaction, TransactionObj }
 
 Setup a ticket and transaction for this Scrip collection to work with as it runs through the 
@@ -334,14 +278,22 @@ sub _SetupSourceObjects {
             @_ );
 
 
-    if ( $self->{'TicketObj'} = $args{'TicketObj'} ) {
-        # This clobbers the passed in TicketObj by turning it into one
-        # whose current user is RT_System.  Anywhere in the Web UI
-        # currently calling into this is thus susceptable to a privilege
-        # leak; the only current call site is ->Apply, which bandaids
-        # over the top of this by re-asserting the CurrentUser
-        # afterwards.
-        $self->{'TicketObj'}->CurrentUser( $self->CurrentUser );
+    if ( $args{'TicketObj'} ) {
+        # This loads a clean copy of the Ticket object to ensure that we
+        # don't accidentally escalate the privileges of the passed in
+        # ticket (this function can be invoked from the UI).
+        # We copy the TransactionBatch transactions so that Scrips
+        # running against the new Ticket will have access to them. We
+        # use RanTransactionBatch to guard against running
+        # TransactionBatch Scrips more than once.
+        $self->{'TicketObj'} = RT::Ticket->new( $self->CurrentUser );
+        $self->{'TicketObj'}->Load( $args{'TicketObj'}->Id );
+        if ( $args{'TicketObj'}->TransactionBatch ) {
+            # try to ensure that we won't infinite loop if something dies, triggering DESTROY while 
+            # we have the _TransactionBatch objects;
+            $self->{'TicketObj'}->RanTransactionBatch(1);
+            $self->{'TicketObj'}->{'_TransactionBatch'} = $args{'TicketObj'}->{'_TransactionBatch'};
+        }
     }
     else {
         $self->{'TicketObj'} = RT::Ticket->new( $self->CurrentUser );
diff --git a/rt/lib/RT/Search/Googleish.pm b/rt/lib/RT/Search/Googleish.pm
index a125483..1b4071f 100644
--- a/rt/lib/RT/Search/Googleish.pm
+++ b/rt/lib/RT/Search/Googleish.pm
@@ -110,7 +110,7 @@ sub QueryToSQL {
                             (\w+)  # A straight word
                             (?:\.  # With an optional .foo
                                 ($RE{delimited}{-delim=>q['"]}
-                                |\w+
+                                |[\w-]+  # Allow \w + dashes
                                 ) # Which could be ."foo bar", too
                             )?
                         )
@@ -225,6 +225,11 @@ sub GuessType {
     return "default";
 }
 
+# $_[0] is $self
+# $_[1] is escaped value without surrounding single quotes
+# $_[2] is a boolean of "was quoted by the user?"
+#       ensure this is false before you do smart matching like $_[1] eq "me"
+# $_[3] is escaped subkey, if any (see HandleCf)
 sub HandleDefault   { return subject   => "Subject LIKE '$_[1]'"; }
 sub HandleSubject   { return subject   => "Subject LIKE '$_[1]'"; }
 sub HandleFulltext  { return content   => "Content LIKE '$_[1]'"; }
@@ -242,7 +247,14 @@ sub HandleStatus    {
     }
 }
 sub HandleOwner     {
-    return owner  => (!$_[2] and $_[1] eq "me") ? "Owner.id = '__CurrentUser__'" : "Owner = '$_[1]'";
+    if (!$_[2] and $_[1] eq "me") {
+        return owner => "Owner.id = '__CurrentUser__'";
+    }
+    elsif (!$_[2] and $_[1] =~ /\w+@\w+/) {
+        return owner => "Owner.EmailAddress = '$_[1]'";
+    } else {
+        return owner => "Owner = '$_[1]'";
+    }
 }
 sub HandleWatcher     {
     return watcher => (!$_[2] and $_[1] eq "me") ? "Watcher.id = '__CurrentUser__'" : "Watcher = '$_[1]'";
diff --git a/rt/lib/RT/SearchBuilder.pm b/rt/lib/RT/SearchBuilder.pm
index 3e98551..4278f75 100644
--- a/rt/lib/RT/SearchBuilder.pm
+++ b/rt/lib/RT/SearchBuilder.pm
@@ -211,29 +211,35 @@ sub LimitCustomField {
                  @_ );
 
     my $alias = $self->Join(
-	TYPE       => 'left',
-	ALIAS1     => 'main',
-	FIELD1     => 'id',
-	TABLE2     => 'ObjectCustomFieldValues',
-	FIELD2     => 'ObjectId'
+        TYPE       => 'left',
+        ALIAS1     => 'main',
+        FIELD1     => 'id',
+        TABLE2     => 'ObjectCustomFieldValues',
+        FIELD2     => 'ObjectId'
     );
     $self->Limit(
-	ALIAS      => $alias,
-	FIELD      => 'CustomField',
-	OPERATOR   => '=',
-	VALUE      => $args{'CUSTOMFIELD'},
+        ALIAS      => $alias,
+        FIELD      => 'CustomField',
+        OPERATOR   => '=',
+        VALUE      => $args{'CUSTOMFIELD'},
     ) if ($args{'CUSTOMFIELD'});
     $self->Limit(
-	ALIAS      => $alias,
-	FIELD      => 'ObjectType',
-	OPERATOR   => '=',
-	VALUE      => $self->_SingularClass,
+        ALIAS      => $alias,
+        FIELD      => 'ObjectType',
+        OPERATOR   => '=',
+        VALUE      => $self->_SingularClass,
     );
     $self->Limit(
-	ALIAS      => $alias,
-	FIELD      => 'Content',
-	OPERATOR   => $args{'OPERATOR'},
-	VALUE      => $args{'VALUE'},
+        ALIAS      => $alias,
+        FIELD      => 'Content',
+        OPERATOR   => $args{'OPERATOR'},
+        VALUE      => $args{'VALUE'},
+    );
+    $self->Limit(
+        ALIAS => $alias,
+        FIELD => 'Disabled',
+        OPERATOR => '=',
+        VALUE => 0,
     );
 }
 
diff --git a/rt/lib/RT/Shredder.pm b/rt/lib/RT/Shredder.pm
index 40c73b3..4f96e16 100644
--- a/rt/lib/RT/Shredder.pm
+++ b/rt/lib/RT/Shredder.pm
@@ -539,9 +539,9 @@ sub WipeoutAll
 {
     my $self = $_[0];
 
-    while ( my ($k, $v) = each %{ $self->{'cache'} } ) {
-        next if $v->{'State'} & (WIPED | IN_WIPING);
-        $self->Wipeout( Object => $v->{'Object'} );
+    foreach my $cache_val ( values %{ $self->{'cache'} } ) {
+        next if $cache_val->{'State'} & (WIPED | IN_WIPING);
+        $self->Wipeout( Object => $cache_val->{'Object'} );
     }
 }
 
diff --git a/rt/lib/RT/Test.pm b/rt/lib/RT/Test.pm
index 7d69dd6..3e7c910 100644
--- a/rt/lib/RT/Test.pm
+++ b/rt/lib/RT/Test.pm
@@ -131,14 +131,14 @@ sub import {
 
     if (RT->Config->Get('DevelMode')) { require Module::Refresh; }
 
-    $class->bootstrap_db( %args );
-
     RT::InitPluginPaths();
+    RT::InitClasses();
+
+    $class->bootstrap_db( %args );
 
     __reconnect_rt()
         unless $args{nodb};
 
-    RT::InitClasses();
     RT::InitLogging();
 
     RT->Plugins;
diff --git a/rt/lib/RT/Ticket.pm b/rt/lib/RT/Ticket.pm
index 00f88b6..577c444 100755
--- a/rt/lib/RT/Ticket.pm
+++ b/rt/lib/RT/Ticket.pm
@@ -1124,7 +1124,7 @@ sub AddWatcher {
         return (0, $self->loc("Couldn't parse address from '[_1]' string", $args{'Email'} ))
             unless $addr;
 
-        if ( lc $self->CurrentUser->UserObj->EmailAddress
+        if ( lc $self->CurrentUser->EmailAddress
             eq lc RT::User->CanonicalizeEmailAddress( $addr->address ) )
         {
             $args{'PrincipalId'} = $self->CurrentUser->id;
@@ -1305,7 +1305,7 @@ sub DeleteWatcher {
             }
         }
         else {
-            $RT::Logger->warn("$self -> DeleteWatcher got passed a bogus type");
+            $RT::Logger->warning("$self -> DeleteWatcher got passed a bogus type");
             return ( 0,
                      $self->loc('Error in parameters to Ticket->DeleteWatcher') );
         }
@@ -1989,6 +1989,31 @@ sub FirstActiveStatus {
     return $next;
 }
 
+=head2 FirstInactiveStatus
+
+Returns the first inactive status that the ticket could transition to,
+according to its current Queue's lifecycle.  May return undef if there
+is no such possible status to transition to, or we are already in it.
+This is used in resolve action in UnsafeEmailCommands, for instance.
+
+=cut
+
+sub FirstInactiveStatus {
+    my $self = shift;
+
+    my $lifecycle = $self->QueueObj->Lifecycle;
+    my $status = $self->Status;
+    my @inactive = $lifecycle->Inactive;
+    # no change if no inactive statuses in the lifecycle
+    return undef unless @inactive;
+
+    # no change if the ticket is already has first status from the list of inactive
+    return undef if lc $status eq lc $inactive[0];
+
+    my ($next) = grep $lifecycle->IsInactive($_), $lifecycle->Transitions($status);
+    return $next;
+}
+
 =head2 SetStarted
 
 Takes a date in ISO format or undef
@@ -2315,7 +2340,9 @@ sub _RecordNote {
     my $msgid = $args{'MIMEObj'}->head->get('Message-ID');
     unless (defined $msgid && $msgid =~ /<(rt-.*?-\d+-\d+)\.(\d+-0-0)\@\Q$org\E>/) {
         $args{'MIMEObj'}->head->set(
-            'RT-Message-ID' => RT::Interface::Email::GenMessageId( Ticket => $self )
+            'RT-Message-ID' => Encode::encode_utf8(
+                RT::Interface::Email::GenMessageId( Ticket => $self )
+            )
         );
     }
 
@@ -3340,6 +3367,28 @@ sub SeenUpTo {
     return $txns->First;
 }
 
+=head2 RanTransactionBatch
+
+Acts as a guard around running TransactionBatch scrips.
+
+Should be false until you enter the code that runs TransactionBatch scrips
+
+Accepts an optional argument to indicate that TransactionBatch Scrips should no longer be run on this object.
+
+=cut
+
+sub RanTransactionBatch {
+    my $self = shift;
+    my $val = shift;
+
+    if ( defined $val ) {
+        return $self->{_RanTransactionBatch} = $val;
+    } else {
+        return $self->{_RanTransactionBatch};
+    }
+
+}
+
 
 =head2 TransactionBatch
 
@@ -3376,6 +3425,22 @@ sub ApplyTransactionBatch {
 
 sub _ApplyTransactionBatch {
     my $self = shift;
+
+    return if $self->RanTransactionBatch;
+    $self->RanTransactionBatch(1);
+
+    my $still_exists = RT::Ticket->new( RT->SystemUser );
+    $still_exists->Load( $self->Id );
+    if (not $still_exists->Id) {
+        # The ticket has been removed from the database, but we still
+        # have pending TransactionBatch txns for it.  Unfortunately,
+        # because it isn't in the DB anymore, attempting to run scrips
+        # on it may produce unpredictable results; simply drop the
+        # batched transactions.
+        $RT::Logger->warning("TransactionBatch was fired on a ticket that no longer exists; unable to run scrips!  Call ->ApplyTransactionBatch before shredding the ticket, for consistent results.");
+        return;
+    }
+
     my $batch = $self->TransactionBatch;
 
     my %seen;
@@ -3423,10 +3488,7 @@ sub DESTROY {
         return;
     }
 
-    my $batch = $self->TransactionBatch;
-    return unless $batch && @$batch;
-
-    return $self->_ApplyTransactionBatch;
+    return $self->ApplyTransactionBatch;
 }
 
 
diff --git a/rt/lib/RT/Tickets.pm b/rt/lib/RT/Tickets.pm
index 485d7df..c9986f4 100755
--- a/rt/lib/RT/Tickets.pm
+++ b/rt/lib/RT/Tickets.pm
@@ -436,6 +436,10 @@ sub _LinkLimit {
     my $is_null = 0;
     $is_null = 1 if !$value || $value =~ /^null$/io;
 
+    unless ($is_null) {
+        $value = RT::URI->new( $sb->CurrentUser )->CanonicalizeURI( $value );
+    }
+
     my $direction = $meta->[1] || '';
     my ($matchfield, $linkfield) = ('', '');
     if ( $direction eq 'To' ) {
@@ -1651,6 +1655,7 @@ sub _CustomFieldLimit {
                 FIELD      => $column,
                 OPERATOR   => $op,
                 VALUE      => $value,
+                CASESENSITIVE => 0,
                 %rest
             ) );
             $self->_CloseParen;
@@ -1713,6 +1718,7 @@ sub _CustomFieldLimit {
                         FIELD    => 'Content',
                         OPERATOR => $op,
                         VALUE    => $value,
+                        CASESENSITIVE => 0,
                         %rest
                     );
                 }
@@ -1739,6 +1745,7 @@ sub _CustomFieldLimit {
                         OPERATOR        => $op,
                         VALUE           => $value,
                         ENTRYAGGREGATOR => 'AND',
+                        CASESENSITIVE => 0,
                     ) );
                 }
             }
@@ -1748,6 +1755,7 @@ sub _CustomFieldLimit {
                     FIELD    => 'Content',
                     OPERATOR => $op,
                     VALUE    => $value,
+                    CASESENSITIVE => 0,
                     %rest
                 );
 
@@ -1774,6 +1782,7 @@ sub _CustomFieldLimit {
                     OPERATOR        => $op,
                     VALUE           => $value,
                     ENTRYAGGREGATOR => 'AND',
+                    CASESENSITIVE => 0,
                 ) );
                 $self->_CloseParen;
             }
@@ -1830,6 +1839,7 @@ sub _CustomFieldLimit {
                 FIELD      => $column,
                 OPERATOR   => $op,
                 VALUE      => $value,
+                CASESENSITIVE => 0,
             ) );
         }
         else {
@@ -1839,6 +1849,7 @@ sub _CustomFieldLimit {
                 FIELD      => 'Content',
                 OPERATOR   => $op,
                 VALUE      => $value,
+                CASESENSITIVE => 0,
             );
         }
         $self->_SQLLimit(
diff --git a/rt/lib/RT/URI.pm b/rt/lib/RT/URI.pm
index fce0459..284a75e 100644
--- a/rt/lib/RT/URI.pm
+++ b/rt/lib/RT/URI.pm
@@ -91,7 +91,26 @@ sub new {
     return ($self);
 }
 
+=head2 CanonicalizeURI <URI>
 
+Returns the canonical form of the given URI by calling L</FromURI> and then L</URI>.
+
+If the URI is unparseable by FromURI the passed in URI is simply returned untouched.
+
+=cut
+
+sub CanonicalizeURI {
+    my $self = shift;
+    my $uri  = shift;
+    if ($self->FromURI($uri)) {
+        my $canonical = $self->URI;
+        if ($canonical and $uri ne $canonical) {
+            RT->Logger->debug("Canonicalizing URI '$uri' to '$canonical'");
+            $uri = $canonical;
+        }
+    }
+    return $uri;
+}
 
 
 =head2 FromObject <Object>
diff --git a/rt/lib/RT/User.pm b/rt/lib/RT/User.pm
index 9b4a826..e7f7c2a 100755
--- a/rt/lib/RT/User.pm
+++ b/rt/lib/RT/User.pm
@@ -932,7 +932,7 @@ sub IsPassword {
         # crypt() output
         return 0 unless crypt(encode_utf8($value), $stored) eq $stored;
     } else {
-        $RT::Logger->warn("Unknown password form");
+        $RT::Logger->warning("Unknown password form");
         return 0;
     }
 
diff --git a/rt/sbin/standalone_httpd b/rt/sbin/standalone_httpd
index 3386cd1..cef0f31 100755
--- a/rt/sbin/standalone_httpd
+++ b/rt/sbin/standalone_httpd
@@ -172,7 +172,7 @@ if (caller) {
 require Plack::Runner;
 
 my $is_fastcgi = $0 =~ m/fcgi$/;
-my $r = Plack::Runner->new( $0 =~ 'standalone' ? ( server => 'Standalone' ) :
+my $r = Plack::Runner->new( $0 =~ /standalone/ ? ( server => 'Standalone' ) :
                             $is_fastcgi        ? ( server => 'FCGI' )
                                                : (),
                             env => 'deployment' );
diff --git a/rt/sbin/standalone_httpd.in b/rt/sbin/standalone_httpd.in
index 45c3770..f84f6c1 100644
--- a/rt/sbin/standalone_httpd.in
+++ b/rt/sbin/standalone_httpd.in
@@ -172,7 +172,7 @@ if (caller) {
 require Plack::Runner;
 
 my $is_fastcgi = $0 =~ m/fcgi$/;
-my $r = Plack::Runner->new( $0 =~ 'standalone' ? ( server => 'Standalone' ) :
+my $r = Plack::Runner->new( $0 =~ /standalone/ ? ( server => 'Standalone' ) :
                             $is_fastcgi        ? ( server => 'FCGI' )
                                                : (),
                             env => 'deployment' );
diff --git a/rt/share/html/Admin/Queues/Modify.html b/rt/share/html/Admin/Queues/Modify.html
index 5682eee..85cd62f 100755
--- a/rt/share/html/Admin/Queues/Modify.html
+++ b/rt/share/html/Admin/Queues/Modify.html
@@ -51,7 +51,7 @@
 
 
 
-<form action="<%RT->Config->Get('WebPath')%>/Admin/Queues/Modify.html" name="ModifyQueue" method="post">
+<form action="<%RT->Config->Get('WebPath')%>/Admin/Queues/Modify.html" name="ModifyQueue" method="post" enctype="multipart/form-data">
 <input type="hidden" class="hidden" name="SetEnabled" value="1" />
 <input type="hidden" class="hidden" name="id" value="<% $Create? 'new': $QueueObj->Id %>" />
 
diff --git a/rt/share/html/Approvals/Elements/PendingMyApproval b/rt/share/html/Approvals/Elements/PendingMyApproval
index d2061da..169c25c 100755
--- a/rt/share/html/Approvals/Elements/PendingMyApproval
+++ b/rt/share/html/Approvals/Elements/PendingMyApproval
@@ -74,7 +74,7 @@ $tickets->LimitOwner( VALUE => $session{'CurrentUser'}->Id );
 
 # also consider AdminCcs as potential approvers.
 my $group_tickets = RT::Tickets->new( $session{'CurrentUser'} );
-$group_tickets->LimitWatcher( VALUE => $session{'CurrentUser'}->UserObj->EmailAddress, TYPE => 'AdminCc' );
+$group_tickets->LimitWatcher( VALUE => $session{'CurrentUser'}->EmailAddress, TYPE => 'AdminCc' );
 
 my $created_before = RT::Date->new( $session{'CurrentUser'} );
 my $created_after = RT::Date->new( $session{'CurrentUser'} );
diff --git a/rt/share/html/Approvals/autohandler b/rt/share/html/Approvals/autohandler
index a057706..3e0f2c6 100644
--- a/rt/share/html/Approvals/autohandler
+++ b/rt/share/html/Approvals/autohandler
@@ -46,8 +46,13 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 <%init>
-$m->call_next(%ARGS) if $session{'CurrentUser'}->UserObj->HasRight(
+if ( $session{'CurrentUser'}->UserObj->HasRight(
     Right => 'ShowApprovalsTab',
     Object => $RT::System,
-);
+) ) {
+    $m->call_next(%ARGS);
+}
+else {
+    Abort("No permission to view approval");
+}
 </%init>
diff --git a/rt/share/html/Dashboards/Subscription.html b/rt/share/html/Dashboards/Subscription.html
index 3669e46..3a57102 100644
--- a/rt/share/html/Dashboards/Subscription.html
+++ b/rt/share/html/Dashboards/Subscription.html
@@ -171,7 +171,7 @@
 <&|/l&>Recipient</&>:
 </td><td class="value">
 <input name="Recipient" id="Recipient" size="30" value="<%$fields{Recipient} ? $fields{Recipient} : ''%>" />
-<div class="hints"><% loc("Leave blank to send to your current email address ([_1])", $session{'CurrentUser'}->UserObj->EmailAddress) %></div>
+<div class="hints"><% loc("Leave blank to send to your current email address ([_1])", $session{'CurrentUser'}->EmailAddress) %></div>
 </td></tr>
 </table>
 </&>
diff --git a/rt/share/html/Elements/ColumnMap b/rt/share/html/Elements/ColumnMap
index b9c3b4b..f268a5d 100644
--- a/rt/share/html/Elements/ColumnMap
+++ b/rt/share/html/Elements/ColumnMap
@@ -118,7 +118,7 @@ my $COLUMN_MAP = {
     CheckBox => {
         title => sub {
             my $name = $_[1] || 'SelectedTickets';
-            my $checked = $m->request_args->{ $name .'All' }? 'checked="checked"': '';
+            my $checked = $DECODED_ARGS->{ $name .'All' }? 'checked="checked"': '';
 
             return \qq{<input type="checkbox" name="}, $name, \qq{All" value="1" $checked
                               onclick="setCheckbox(this.form, },
@@ -130,9 +130,9 @@ my $COLUMN_MAP = {
 
             my $name = $_[2] || 'SelectedTickets';
             return \qq{<input type="checkbox" name="}, $name, \qq{" value="$id" checked="checked" />}
-                if $m->request_args->{ $name . 'All'};
+                if $DECODED_ARGS->{ $name . 'All'};
 
-            my $arg = $m->request_args->{ $name };
+            my $arg = $DECODED_ARGS->{ $name };
             my $checked = '';
             if ( $arg && ref $arg ) {
                 $checked = 'checked="checked"' if grep $_ == $id, @$arg;
@@ -149,7 +149,7 @@ my $COLUMN_MAP = {
             my $id = $_[0]->id;
 
             my $name = $_[2] || 'SelectedTicket';
-            my $arg = $m->request_args->{ $name };
+            my $arg = $DECODED_ARGS->{ $name };
             my $checked = '';
             $checked = 'checked="checked"' if $arg && $arg == $id;
             return \qq{<input type="radio" name="}, $name, \qq{" value="$id" $checked />};
diff --git a/rt/share/html/Elements/EditCustomField b/rt/share/html/Elements/EditCustomField
index b74c484..8b87fd4 100644
--- a/rt/share/html/Elements/EditCustomField
+++ b/rt/share/html/Elements/EditCustomField
@@ -71,7 +71,7 @@ if ( $Object && $Object->id ) {
 
 # Always fill $Default with submited values if it's empty
 if ( ( !defined $Default || !length $Default ) && $DefaultsFromTopArguments ) {
-    my %TOP = $m->request_args;
+    my %TOP = %$DECODED_ARGS;
     $Default = $TOP{ $NamePrefix .$CustomField->Id . '-Values' }
             || $TOP{ $NamePrefix .$CustomField->Id . '-Value' };
 }
diff --git a/rt/share/html/Elements/Header b/rt/share/html/Elements/Header
index 1830c4b..65d06f8 100755
--- a/rt/share/html/Elements/Header
+++ b/rt/share/html/Elements/Header
@@ -130,7 +130,8 @@ if ($m->comp_exists($stylesheet_plugin) ) {
 # $m->callback( %ARGS, CallbackName => 'Head' );
 $head .= $m->scomp( '/Elements/Callback', _CallbackName => 'Head', %ARGS );
 
-my $etc = qq[ class="\L$style" ];
+my $sbs = RT->Config->Get("UseSideBySideLayout", $session{'CurrentUser'}) ? ' sidebyside' : '';
+my $etc = qq[ class="\L$style$sbs" ];
 $etc .= qq[ id="comp-$id"] if $id;
 
 </%INIT>
diff --git a/rt/share/html/Elements/HeaderJavascript b/rt/share/html/Elements/HeaderJavascript
index 28788db..d5741f4 100644
--- a/rt/share/html/Elements/HeaderJavascript
+++ b/rt/share/html/Elements/HeaderJavascript
@@ -67,7 +67,7 @@ $onload => undef
 % }
 
 % if ( $RichText and RT->Config->Get('MessageBoxRichText',  $session{'CurrentUser'})) {
-    jQuery().ready(function ()  { ReplaceAllTextareas(<%$m->request_args->{'CKeditorEncoded'} || 0 |n,j%>) });
+    jQuery().ready(function ()  { ReplaceAllTextareas(<%$DECODED_ARGS->{'CKeditorEncoded'} || 0 |n,j%>) });
 % }
 --></script>
 <%ARGS>
diff --git a/rt/share/html/Elements/ListActions b/rt/share/html/Elements/ListActions
index 999d3fe..8929ff7 100755
--- a/rt/share/html/Elements/ListActions
+++ b/rt/share/html/Elements/ListActions
@@ -65,7 +65,7 @@ if ( ref( $session{'Actions'}{''} ) eq 'ARRAY' ) {
     unshift @actions, @{ delete $session{'Actions'}{''} };
 }
 
-my $actions_pointer = $m->request_args->{'results'};
+my $actions_pointer = $DECODED_ARGS->{'results'};
 
 if ($actions_pointer &&  ref( $session{'Actions'}->{$actions_pointer} ) eq 'ARRAY' ) {
     unshift @actions, @{ delete $session{'Actions'}->{$actions_pointer} };
diff --git a/rt/share/html/Elements/MessageBox b/rt/share/html/Elements/MessageBox
index 61995e0..69227bf 100755
--- a/rt/share/html/Elements/MessageBox
+++ b/rt/share/html/Elements/MessageBox
@@ -46,7 +46,7 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 <textarea autocomplete="off" class="messagebox" <% $width_attr %>="<% $Width %>" rows="<% $Height %>" <% $wrap_type |n %> name="<% $Name %>" id="<% $Name %>">\
-% $m->comp('/Articles/Elements/IncludeArticle', %ARGS);
+% $m->comp('/Articles/Elements/IncludeArticle', %ARGS) if $IncludeArticle;
 % $m->callback( %ARGS, SignatureRef => \$signature );
 <% $Default || '' %><% $message %><% $signature %></textarea>
 % $m->callback( %ARGS, CallbackName => 'AfterTextArea' );
@@ -89,4 +89,5 @@ $Width            => RT->Config->Get('MessageBoxWidth', $session{'CurrentUser'}
 $Height           => RT->Config->Get('MessageBoxHeight', $session{'CurrentUser'} ) || 15
 $Wrap             => RT->Config->Get('MessageBoxWrap', $session{'CurrentUser'} ) || 'SOFT'
 $IncludeSignature => RT->Config->Get('MessageBoxIncludeSignature');
+$IncludeArticle   => 1;
 </%ARGS>
diff --git a/rt/share/html/Elements/QueueSummaryByStatus b/rt/share/html/Elements/QueueSummaryByStatus
index 09f274f..f649d28 100644
--- a/rt/share/html/Elements/QueueSummaryByStatus
+++ b/rt/share/html/Elements/QueueSummaryByStatus
@@ -122,9 +122,13 @@ my $statuses = {};
 
 use RT::Report::Tickets;
 my $report = RT::Report::Tickets->new( RT->SystemUser );
-my $query = @queues
-    ? join(' OR ', map "Queue = ".$_->{id}, @queues)
-    : 'id < 0';
+my $query =
+    "(".
+    join(" OR ", map {s{(['\\])}{\\$1}g; "Status = '$_'"} @statuses) #'
+    .") AND (".
+    join(' OR ', map "Queue = ".$_->{id}, @queues)
+    .")";
+$query = 'id < 0' unless @queues;
 $report->SetupGroupings( Query => $query, GroupBy => [qw(Status Queue)] );
 
 while ( my $entry = $report->Next ) {
diff --git a/rt/share/html/Elements/RT__CustomField/ColumnMap b/rt/share/html/Elements/RT__CustomField/ColumnMap
index ecb219d..b043984 100644
--- a/rt/share/html/Elements/RT__CustomField/ColumnMap
+++ b/rt/share/html/Elements/RT__CustomField/ColumnMap
@@ -118,7 +118,7 @@ my $COLUMN_MAP = {
     RemoveCheckBox => {
         title => sub {
             my $name = 'RemoveCustomField';
-            my $checked = $m->request_args->{ $name .'All' }? 'checked="checked"': '';
+            my $checked = $DECODED_ARGS->{ $name .'All' }? 'checked="checked"': '';
 
             return \qq{<input type="checkbox" name="}, $name, \qq{All" value="1" $checked
                               onclick="setCheckbox(this.form, },
@@ -130,7 +130,7 @@ my $COLUMN_MAP = {
             return '' if $_[0]->IsApplied;
 
             my $name = 'RemoveCustomField';
-            my $arg = $m->request_args->{ $name };
+            my $arg = $DECODED_ARGS->{ $name };
 
             my $checked = '';
             if ( $arg && ref $arg ) {
diff --git a/rt/share/html/Elements/SelectWatcherType b/rt/share/html/Elements/SelectWatcherType
index 44beee0..4f1df60 100755
--- a/rt/share/html/Elements/SelectWatcherType
+++ b/rt/share/html/Elements/SelectWatcherType
@@ -56,7 +56,7 @@
 
 <%INIT>
 my @types;
-if ($Scope =~ 'queue') {
+if ($Scope =~ /queue/) {
    @types = RT::Queue->ManageableRoleGroupTypes;
 }
 else { 
diff --git a/rt/share/html/Elements/Tabs b/rt/share/html/Elements/Tabs
index 3193b48..3aac9d8 100755
--- a/rt/share/html/Elements/Tabs
+++ b/rt/share/html/Elements/Tabs
@@ -845,7 +845,7 @@ my $build_selfservice_nav = sub {
     } elsif ( $queue_id ) {
         Menu->child( new => title => loc('New ticket'), path => '/SelfService/Create.html?Queue=' . $queue_id );
     }
-    my $tickets = Menu->child( tickets => title => loc('Tickets'));
+    my $tickets = Menu->child( tickets => title => loc('Tickets'), path => '/SelfService/' );
     $tickets->child( open   => title => loc('Open tickets'),   path => '/SelfService/' );
     $tickets->child( closed => title => loc('Closed tickets'), path => '/SelfService/Closed.html' );
 
diff --git a/rt/share/html/Helpers/Autocomplete/Users b/rt/share/html/Helpers/Autocomplete/Users
index dbc2d88..c2b92c1 100644
--- a/rt/share/html/Helpers/Autocomplete/Users
+++ b/rt/share/html/Helpers/Autocomplete/Users
@@ -116,6 +116,9 @@ foreach (split /\s*,\s*/, $exclude) {
 
 my @suggestions;
 
+$users->Limit( FIELD => $return, OPERATOR => '!=', VALUE => '' );
+$users->Limit( FIELD => $return, OPERATOR => 'IS NOT', VALUE => 'NULL', ENTRYAGGREGATOR => 'AND'  );
+
 while ( my $user = $users->Next ) {
     next if $user->id == RT->SystemUser->id
          or $user->id == RT->Nobody->id;
diff --git a/rt/share/html/NoAuth/css/aileron/boxes.css b/rt/share/html/NoAuth/css/aileron/boxes.css
index ed6623c..f90ac9f 100644
--- a/rt/share/html/NoAuth/css/aileron/boxes.css
+++ b/rt/share/html/NoAuth/css/aileron/boxes.css
@@ -91,10 +91,6 @@
 
 .titlebox .titlebox-title {
  position: relative;
- /* This is for [rt3 #19044]. Move it to an IE-specific file if it causes
-  * problems. If we remove CSS3PIE, it can also probably go away, although it
-  * probably won't hurt. */
- z-index: 1;
 }
 
 .titlebox .titlebox-title a {
diff --git a/rt/share/html/NoAuth/css/aileron/ticket.css b/rt/share/html/NoAuth/css/aileron/ticket.css
index 4d069d9..7b573f7 100644
--- a/rt/share/html/NoAuth/css/aileron/ticket.css
+++ b/rt/share/html/NoAuth/css/aileron/ticket.css
@@ -87,8 +87,7 @@ div#ticket-history {
  float: left;
  margin: 0.25em 0.70em 0.25em 0.25em;
  width: 1em;
- height: 1.25em;
- padding: 0.75em 0 0 0;
+ padding: 0;
  border-right: 1px solid #999;
  border-bottom: 1px solid #999;
  -moz-border-radius-bottomright: 0.25em;
@@ -100,6 +99,16 @@ div#ticket-history {
 
 div#ticket-history span.type a {
  color: #fff;
+ padding-top: 0.75em;
+ display: block;
+}
+
+#ticket-history a#lasttrans {
+    display: inline;
+    height: 0;
+    width: 0;
+    padding: 0;
+    margin: 0;
 }
 
 
diff --git a/rt/share/html/NoAuth/css/ballard/boxes.css b/rt/share/html/NoAuth/css/ballard/boxes.css
index 912ac55..9610cd5 100644
--- a/rt/share/html/NoAuth/css/ballard/boxes.css
+++ b/rt/share/html/NoAuth/css/ballard/boxes.css
@@ -54,6 +54,7 @@
  margin-left: 1em;
  -moz-border-radius: 0.5em;
  -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
  margin-bottom: 2em;
  border-bottom: 2px solid #aaa;
  border-right: 2px solid #aaa;
@@ -71,6 +72,7 @@
  margin-top: 1em;
  -moz-border-radius: 0.5em;
  -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
  margin-right: 0.25em;
  
 }
@@ -114,6 +116,7 @@
     padding-right: 0.75em;
     -moz-border-radius: 0.5em;
     -webkit-border-radius: 0.5em;
+    border-radius: 0.5em;
     border-bottom: 2px solid #aaa;
     border-right: 2px solid #aaa;
 
@@ -138,10 +141,12 @@
  padding-top: 0.5em;
  -moz-border-radius-bottomleft: 0.25em;
  -webkit-border-bottom-left-radius: 0.25em;
+ border-bottom-left-radius: 0.25em;
  
  
  -moz-border-radius-topright: 0.25em;
  -webkit-border-top-right-radius: 0.25em;
+ border-top-right-radius: 0.25em;
 
 }
 
diff --git a/rt/share/html/NoAuth/css/ballard/layout.css b/rt/share/html/NoAuth/css/ballard/layout.css
index 8dc0cc1..8b600b8 100644
--- a/rt/share/html/NoAuth/css/ballard/layout.css
+++ b/rt/share/html/NoAuth/css/ballard/layout.css
@@ -60,8 +60,10 @@ div#body {
     padding: 1.8em 1em 1em 1em;
     -moz-border-radius-topleft: 0.5em;
     -webkit-border-top-left-radius: 0.5em;
+    border-top-left-radius: 0.5em;
     -moz-border-radius-bottomleft: 0.5em;
     -webkit-border-bottom-left-radius: 0.5em;
+    border-bottom-left-radius: 0.5em;
     margin-left: 10em;
     margin-top: 3em;
     margin-right: 0;
@@ -89,8 +91,10 @@ div#footer {
  border-left: 2px solid #aaa;
  -moz-border-radius-topleft: 0.5em;
  -webkit-border-top-left-radius: 0.5em;
+ border-top-left-radius: 0.5em;
  -moz-border-radius-bottomleft: 0.5em;
  -webkit-border-bottom-left-radius: 0.5em;
+ border-bottom-left-radius: 0.5em;
 }
 
 div#footer #time {
diff --git a/rt/share/html/NoAuth/css/ballard/nav.css b/rt/share/html/NoAuth/css/ballard/nav.css
index 196f0e6..dc29818 100644
--- a/rt/share/html/NoAuth/css/ballard/nav.css
+++ b/rt/share/html/NoAuth/css/ballard/nav.css
@@ -49,8 +49,10 @@
     background-color: #fff;
     -moz-border-radius-bottomright: 0.5em;
     -webkit-border-bottom-right-radius: 0.5em;
+    border-bottom-right-radius: 0.5em;
     -moz-border-radius-topright: 0.5em;
     -webkit-border-top-right-radius: 0.5em;
+    border-top-right-radius: 0.5em;
     width: 10em;
     font-size: 0.85em;
     position: absolute;
@@ -130,6 +132,7 @@
     border: 1px solid #ccc;
     -moz-border-radius-bottomleft: 0.5em;
     -webkit-border-bottom-left-radius: 0.5em;
+    border-bottom-left-radius: 0.5em;
     padding: 0;
     padding-top: 0.5em;
     padding-right: 0.5em;
diff --git a/rt/share/html/NoAuth/css/ballard/ticket-search.css b/rt/share/html/NoAuth/css/ballard/ticket-search.css
index 19ee847..fb252b5 100644
--- a/rt/share/html/NoAuth/css/ballard/ticket-search.css
+++ b/rt/share/html/NoAuth/css/ballard/ticket-search.css
@@ -163,6 +163,7 @@
  border-bottom: 1px solid #999;
  -moz-border-radius-bottomleft: 0.5em;
  -webkit-border-bottom-left-radius: 0.5em;
+ border-bottom-left-radius: 0.5em;
 }
 
 
diff --git a/rt/share/html/NoAuth/css/ballard/ticket.css b/rt/share/html/NoAuth/css/ballard/ticket.css
index 06b6678..4d416e1 100644
--- a/rt/share/html/NoAuth/css/ballard/ticket.css
+++ b/rt/share/html/NoAuth/css/ballard/ticket.css
@@ -77,6 +77,7 @@ div#ticket-history {
  color: #ccc;
  -moz-border-radius-bottomleft: 0.5em;
  -webkit-border-bottom-left-radius: 0.5em;
+ border-bottom-left-radius: 0.5em;
  white-space: nowrap;
 }
 
@@ -91,6 +92,7 @@ div#ticket-history {
  border-bottom: 1px solid #999;
  -moz-border-radius: 0.25em;
  -webkit-border-bottom-right-radius: 0.25em;
+ border-bottom-right-radius: 0.25em;
 }
 
 div#ticket-history span.type a {
@@ -150,6 +152,7 @@ border-bottom: 2px solid #aaa;
 margin-top: 0.5em;
 -moz-border-radius: 0.5em;
 -webkit-border-radius: 0.5em;
+border-radius: 0.5em;
 
 }
 
diff --git a/rt/share/html/NoAuth/css/base/forms.css b/rt/share/html/NoAuth/css/base/forms.css
index eab97b1..19af1b2 100644
--- a/rt/share/html/NoAuth/css/base/forms.css
+++ b/rt/share/html/NoAuth/css/base/forms.css
@@ -87,6 +87,7 @@ input[type=reset], input[type=submit], input[class=button], button {
    padding-right: 0.5em;
    -moz-border-radius: 0.5em;
    -webkit-border-radius: 0.5em;
+   border-radius: 0.5em;
 }
 
 input.button:hover, button:hover, input[type=reset]:hover, input[type=submit]:hover, input[class=button]:hover {
diff --git a/rt/share/html/NoAuth/css/base/jquery-ui-timepicker-addon.css b/rt/share/html/NoAuth/css/base/jquery-ui-timepicker-addon.css
new file mode 100644
index 0000000..7eb8715
--- /dev/null
+++ b/rt/share/html/NoAuth/css/base/jquery-ui-timepicker-addon.css
@@ -0,0 +1,7 @@
+.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
+.ui-timepicker-div dl { text-align: left; }
+.ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
+.ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
+.ui-timepicker-div td { font-size: 90%; }
+.ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
+.ui-datepicker-buttonpane button.ui-datepicker-current { opacity: 1.0; }
diff --git a/rt/share/html/NoAuth/css/base/jquery-ui.css b/rt/share/html/NoAuth/css/base/jquery-ui.css
index 820996e..8fe4f15 100644
--- a/rt/share/html/NoAuth/css/base/jquery-ui.css
+++ b/rt/share/html/NoAuth/css/base/jquery-ui.css
@@ -46,5 +46,3 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 @import "jquery-ui.custom.modified.css";
- at import "ui.timepickr.css";
- at import "ui.timepickr.custom.css";
diff --git a/rt/share/html/NoAuth/css/base/jquery-ui.custom.modified.css b/rt/share/html/NoAuth/css/base/jquery-ui.custom.modified.css
index 7a32322..3b1e1a0 100644
--- a/rt/share/html/NoAuth/css/base/jquery-ui.custom.modified.css
+++ b/rt/share/html/NoAuth/css/base/jquery-ui.custom.modified.css
@@ -452,3 +452,27 @@
     width: 200px; /*must have*/
     height: 200px; /*must have*/
 }
+/*
+ * jQuery UI Slider 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }
diff --git a/rt/share/html/NoAuth/css/base/main.css b/rt/share/html/NoAuth/css/base/main.css
index 9f77c8a..dac733d 100644
--- a/rt/share/html/NoAuth/css/base/main.css
+++ b/rt/share/html/NoAuth/css/base/main.css
@@ -49,6 +49,7 @@
 
 @import "yui-fonts.css";
 @import "jquery-ui.css";
+ at import "jquery-ui-timepicker-addon.css";
 @import "superfish.css";
 @import "superfish-navbar.css";
 @import "superfish-vertical.css";
diff --git a/rt/share/html/NoAuth/css/base/superfish-navbar.css b/rt/share/html/NoAuth/css/base/superfish-navbar.css
index 9a3f24c..459156e 100644
--- a/rt/share/html/NoAuth/css/base/superfish-navbar.css
+++ b/rt/share/html/NoAuth/css/base/superfish-navbar.css
@@ -90,4 +90,6 @@ ul.sf-navbar .current ul ul {
 	-moz-border-radius-topright: 0;
 	-webkit-border-top-right-radius: 0;
 	-webkit-border-bottom-left-radius: 0;
+	border-top-right-radius: 0;
+	border-bottom-left-radius: 0;
 }
diff --git a/rt/share/html/NoAuth/css/base/superfish.css b/rt/share/html/NoAuth/css/base/superfish.css
index 31198e4..7cb3b56 100644
--- a/rt/share/html/NoAuth/css/base/superfish.css
+++ b/rt/share/html/NoAuth/css/base/superfish.css
@@ -130,6 +130,8 @@ li.sfHover > a > .sf-sub-indicator {
 	-moz-border-radius-topright: 17px;
 	-webkit-border-top-right-radius: 17px;
 	-webkit-border-bottom-left-radius: 17px;
+	border-top-right-radius: 17px;
+	border-bottom-left-radius: 17px;
 }
 .sf-shadow ul.sf-shadow-off {
 	background: transparent;
diff --git a/rt/share/html/NoAuth/css/base/ticket-form.css b/rt/share/html/NoAuth/css/base/ticket-form.css
index daab263..869eba7 100644
--- a/rt/share/html/NoAuth/css/base/ticket-form.css
+++ b/rt/share/html/NoAuth/css/base/ticket-form.css
@@ -82,21 +82,17 @@ iframe.richtext-editor {
 .messagebox-container.action-response iframe
 {
     background-color: #fcc !important;
-} 
-
-/*
-% if ( RT->Config->Get("UseSideBySideLayout", $session{'CurrentUser'}) ) {
-*/
+}
 
-#ticket-create-metadata,
-#ticket-update-metadata {
+.sidebyside #ticket-create-metadata,
+.sidebyside #ticket-update-metadata {
     float: right;
     width: 40%;
     clear: right;
 }
 
-#ticket-create-message,
-#ticket-update-message {
+.sidebyside #ticket-create-message,
+.sidebyside #ticket-update-message {
     float: left;
     width: 58%;
     clear: left;
@@ -104,10 +100,10 @@ iframe.richtext-editor {
 
 @media (max-width: 950px) {
     /* Revert to a single column when we're less than 1000px wide */
-    #ticket-create-metadata,
-    #ticket-update-metadata,
-    #ticket-create-message,
-    #ticket-update-message
+    .sidebyside #ticket-create-metadata,
+    .sidebyside #ticket-update-metadata,
+    .sidebyside #ticket-create-message,
+    .sidebyside #ticket-update-message
     {
         float: none;
         width: auto;
@@ -115,15 +111,12 @@ iframe.richtext-editor {
     }
 }
 
-#comp-Ticket-Update #body {
+.sidebyside #comp-Ticket-Update #body {
     padding-top: 3em;
 }
 
-#ticket-create-message .button[name="AddMoreAttach"],
-#ticket-update-message .button[name="AddMoreAttach"] {
+.sidebyside #ticket-create-message .button[name="AddMoreAttach"],
+.sidebyside #ticket-update-message .button[name="AddMoreAttach"] {
     float: right;
 }
 
-/*
-% }
-*/
diff --git a/rt/share/html/NoAuth/css/base/ui.timepickr.css b/rt/share/html/NoAuth/css/base/ui.timepickr.css
deleted file mode 100644
index e2dacf7..0000000
--- a/rt/share/html/NoAuth/css/base/ui.timepickr.css
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-  jQuery ui.timepickr
-  http://code.google.com/p/jquery-utils/
-
-  copyright Maxime Haineault <haineault at gmail.com> 
-  http://haineault.com
-
-  MIT License (http://www.opensource.org/licenses/mit-license.php
-*/
-.ui-timepickr {
-    position:absolute;
-    width:480px; 
-}
-
-.ui-timepickr-row {
-    margin:0;
-    padding:0;
-    margin-top:2px; 
-    display:none;
-    position:relative;
-}
-
-.ui-timepickr-button {
-    float:left;
-    margin:0;
-    padding:0;
-    list-style:none;
-    list-style-type:none;
-}
-
-.ui-timepickr-button span {
-    font-size:.7em;
-    padding:4px 6px 4px 6px;
-    margin-left:2px;
-    text-align:center;
-    cursor:pointer;
-    display:block;
-    text-align:center;
-
-
-    /* system theme (default) */
-    border-width:1px;
-    border-style:solid;
-    /*border-color:ThreeDLightShadow ThreeDShadow ThreeDShadow ThreeDLightShadow;
-    color:ButtonText;
-    background:ButtonFace;*/
-}
-
-.ui-timepickr-button span.ui-state-hover {
-    /*color:HighlightText;
-    background:Highlight;*/
-}
-
-.ui-state-hover span {
-    /*background:#c30;*/
-}
diff --git a/rt/share/html/NoAuth/css/base/ui.timepickr.custom.css b/rt/share/html/NoAuth/css/base/ui.timepickr.custom.css
deleted file mode 100644
index ad2aa66..0000000
--- a/rt/share/html/NoAuth/css/base/ui.timepickr.custom.css
+++ /dev/null
@@ -1,54 +0,0 @@
-%# BEGIN BPS TAGGED BLOCK {{{
-%#
-%# COPYRIGHT:
-%#
-%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
-%#                                          <sales at bestpractical.com>
-%#
-%# (Except where explicitly superseded by other copyright notices)
-%#
-%#
-%# LICENSE:
-%#
-%# This work is made available to you under the terms of Version 2 of
-%# the GNU General Public License. A copy of that license should have
-%# been provided with this software, but in any event can be snarfed
-%# from www.gnu.org.
-%#
-%# This work 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 this program; if not, write to the Free Software
-%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-%# 02110-1301 or visit their web page on the internet at
-%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
-%#
-%#
-%# CONTRIBUTION SUBMISSION POLICY:
-%#
-%# (The following paragraph is not intended to limit the rights granted
-%# to you to modify and distribute this software under the terms of
-%# the GNU General Public License and is only of importance to you if
-%# you choose to contribute your changes and enhancements to the
-%# community by submitting them to Best Practical Solutions, LLC.)
-%#
-%# By intentionally submitting any modifications, corrections or
-%# derivatives to this work, or any other work intended for use with
-%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
-%# you are the copyright holder for those contributions and you grant
-%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
-%# royalty-free, perpetual, license to use, copy, create derivative
-%# works based on those contributions, and sublicense and distribute
-%# those contributions and any derivatives thereof.
-%#
-%# END BPS TAGGED BLOCK }}}
-.ui-timepickr {
-    font-size: 1.1em;
-}
-
-.ui-timepickr-button span {
-    background: white;
-}
diff --git a/rt/share/html/NoAuth/css/web2/nav.css b/rt/share/html/NoAuth/css/web2/nav.css
index be63c59..e404b61 100644
--- a/rt/share/html/NoAuth/css/web2/nav.css
+++ b/rt/share/html/NoAuth/css/web2/nav.css
@@ -239,6 +239,7 @@
     border: 1px solid #ccc;
     -moz-border-radius-bottomleft: 0.5em;
     -webkit-border-bottom-left-radius: 0.5em;
+    border-bottom-left-radius: 0.5em;
     border-right: none;
     border-top: none;
     list-style-type: none;
diff --git a/rt/share/html/NoAuth/js/jquery-ui-1.8.4.custom.min.js b/rt/share/html/NoAuth/js/jquery-ui-1.8.4.custom.min.js
index e90b4fe..0466005 100644
--- a/rt/share/html/NoAuth/js/jquery-ui-1.8.4.custom.min.js
+++ b/rt/share/html/NoAuth/js/jquery-ui-1.8.4.custom.min.js
@@ -222,3 +222,53 @@ c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(t
 function(a){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 L;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.4";window["DP_jQuery_"+y]=d})(jQuery);
 ;
+/*!
+ * jQuery UI Mouse 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * 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(a._preventClickEvent){a._preventClickEvent=false;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);c.browser.safari||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;this._preventClickEvent=a.target==this._mouseDownEvent.target;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 Slider 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ *  jquery.ui.core.js
+ *  jquery.ui.mouse.js
+ *  jquery.ui.widget.js
+ */
+(function(d){d.widget("ui.slider",d.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var a=this,b=this.options;this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");b.disabled&&this.element.addClass("ui-slider-disabled ui-disabled");
+this.range=d([]);if(b.range){if(b.range===true){this.range=d("<div></div>");if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}else this.range=d("<div></div>");this.range.appendTo(this.element).addClass("ui-slider-range");if(b.range==="min"||b.range==="max")this.range.addClass("ui-slider-range-"+b.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");
+if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length<b.values.length;)d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();
+else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),h,g,i;if(!a.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e=
+false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");h=a._start(c,f);if(h===false)return}break}i=a.options.step;h=a.options.values&&a.options.values.length?(g=a.values(f)):(g=a.value());switch(c.keyCode){case d.ui.keyCode.HOME:g=a._valueMin();break;case d.ui.keyCode.END:g=a._valueMax();break;case d.ui.keyCode.PAGE_UP:g=a._trimAlignValue(h+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:g=a._trimAlignValue(h-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(h===
+a._valueMax())return;g=a._trimAlignValue(h+i);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(h===a._valueMin())return;g=a._trimAlignValue(h-i);break}a._slide(c,f,g);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(c,e);a._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");
+this._mouseDestroy();return this},_mouseCapture:function(a){var b=this.options,c,e,f,h,g;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c=this._normValueFromMouse({x:a.pageX,y:a.pageY});e=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(i){var j=Math.abs(c-h.values(i));if(e>j){e=j;f=d(this);g=i}});if(b.range===true&&this.values(1)===b.min){g+=1;f=d(this.handles[g])}if(this._start(a,
+g)===false)return false;this._mouseSliding=true;h._handleIndex=g;f.addClass("ui-state-active").focus();b=f.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-f.width()/2,top:a.pageY-b.top-f.height()/2-(parseInt(f.css("borderTopWidth"),10)||0)-(parseInt(f.css("borderBottomWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0)};this._slide(a,g,c);return this._animateOff=true},_mouseStart:function(){return true},_mouseDrag:function(a){var b=
+this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;if(this.orientation==="horizontal"){b=
+this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);
+c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var e;if(this.options.values&&this.options.values.length){e=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>e||b===1&&c<e))c=e;if(c!==this.values(b)){e=this.values();e[b]=c;a=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e});this.values(b?0:1);a!==false&&this.values(b,c,true)}}else if(c!==this.value()){a=this._trigger("slide",a,{handle:this.handles[b],value:c});
+a!==false&&this.value(c)}},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("change",a,c)}},value:function(a){if(arguments.length){this.options.value=
+this._trimAlignValue(a);this._refreshValue();this._change(null,0)}return this._value()},values:function(a,b){var c,e,f;if(arguments.length>1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;f<c.length;f+=1){c[f]=this._trimAlignValue(e[f]);this._change(null,f)}this._refreshValue()}else return this.options.values&&this.options.values.length?this._values(a):this.value();
+else return this._values()},_setOption:function(a,b){var c,e=0;if(d.isArray(this.options.values))e=this.options.values.length;d.Widget.prototype._setOption.apply(this,arguments);switch(a){case "disabled":if(b){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled");this.element.addClass("ui-disabled")}else{this.handles.removeAttr("disabled");this.element.removeClass("ui-disabled")}break;case "orientation":this._detectOrientation();
+this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue();break;case "value":this._animateOff=true;this._refreshValue();this._change(null,0);this._animateOff=false;break;case "values":this._animateOff=true;this._refreshValue();for(c=0;c<e;c+=1)this._change(null,c);this._animateOff=false;break}},_value:function(){var a=this.options.value;return a=this._trimAlignValue(a)},_values:function(a){var b,c;if(arguments.length){b=this.options.values[a];
+return b=this._trimAlignValue(b)}else{b=this.options.values.slice();for(c=0;c<b.length;c+=1)b[c]=this._trimAlignValue(b[c]);return b}},_trimAlignValue:function(a){if(a<this._valueMin())return this._valueMin();if(a>this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a=
+this.options.range,b=this.options,c=this,e=!this._animateOff?b.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,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(k===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({width:f-
+g+"%"},{queue:false,duration:b.animate})}else{if(k===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({height:f-g+"%"},{queue:false,duration:b.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,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},
+b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.4"})})(jQuery);
diff --git a/rt/share/html/NoAuth/js/jquery-ui-patch-datepicker.js b/rt/share/html/NoAuth/js/jquery-ui-patch-datepicker.js
index 40cc0db..2ac101f 100644
--- a/rt/share/html/NoAuth/js/jquery-ui-patch-datepicker.js
+++ b/rt/share/html/NoAuth/js/jquery-ui-patch-datepicker.js
@@ -58,4 +58,35 @@
 
         return data;
     };
+
+    $.datepicker._checkOffset_orig = $.datepicker._checkOffset;
+    $.datepicker._checkOffset = function(inst, offset, isFixed) {
+        // copied from the original
+        var dpHeight    = inst.dpDiv.outerHeight();
+        var inputHeight = inst.input ? inst.input.outerHeight() : 0;
+        var viewHeight  = document.documentElement.clientHeight + $(document).scrollTop();
+
+        // save the original offset rather than the new offset because the
+        // original function modifies the passed arg as a side-effect
+        var old_offset = { top: offset.top, left: offset.left };
+        offset = $.datepicker._checkOffset_orig(inst, offset, isFixed);
+
+        // Negate any up or down positioning by adding instead of subtracting
+        offset.top += Math.min(old_offset.top, (old_offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
+            Math.abs(dpHeight + inputHeight) : 0);
+
+        return offset;
+    };
+
+
+    $.timepicker._newInst_orig = $.timepicker._newInst;
+    $.timepicker._newInst = function($input, o) {
+        var tp_inst = $.timepicker._newInst_orig($input, o);
+        tp_inst._defaults.onClose = function(dateText, dp_inst) {
+	    if ($.isFunction(o.onClose))
+		o.onClose.call($input[0], dateText, dp_inst, tp_inst);
+        };
+        return tp_inst;
+    };
+
 })(jQuery);
diff --git a/rt/share/html/NoAuth/js/jquery-ui-timepicker-addon.js b/rt/share/html/NoAuth/js/jquery-ui-timepicker-addon.js
new file mode 100644
index 0000000..0a4ff02
--- /dev/null
+++ b/rt/share/html/NoAuth/js/jquery-ui-timepicker-addon.js
@@ -0,0 +1,1326 @@
+/*
+* jQuery timepicker addon
+* By: Trent Richardson [http://trentrichardson.com]
+* Version 1.0.0
+* Last Modified: 02/05/2012
+*
+* Copyright 2012 Trent Richardson
+* Dual licensed under the MIT and GPL licenses.
+* http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
+* http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
+*
+* HERES THE CSS:
+* .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
+* .ui-timepicker-div dl { text-align: left; }
+* .ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
+* .ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
+* .ui-timepicker-div td { font-size: 90%; }
+* .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
+*/
+
+(function($) {
+
+// Prevent "Uncaught RangeError: Maximum call stack size exceeded"
+$.ui.timepicker = $.ui.timepicker || {};
+if ($.ui.timepicker.version) {
+	return;
+}
+
+$.extend($.ui, { timepicker: { version: "1.0.0" } });
+
+/* Time picker manager.
+   Use the singleton instance of this class, $.timepicker, to interact with the time picker.
+   Settings for (groups of) time pickers are maintained in an instance object,
+   allowing multiple different settings on the same page. */
+
+function Timepicker() {
+	this.regional = []; // Available regional settings, indexed by language code
+	this.regional[''] = { // Default regional settings
+		currentText: 'Now',
+		closeText: 'Done',
+		ampm: false,
+		amNames: ['AM', 'A'],
+		pmNames: ['PM', 'P'],
+		timeFormat: 'hh:mm tt',
+		timeSuffix: '',
+		timeOnlyTitle: 'Choose Time',
+		timeText: 'Time',
+		hourText: 'Hour',
+		minuteText: 'Minute',
+		secondText: 'Second',
+		millisecText: 'Millisecond',
+		timezoneText: 'Time Zone'
+	};
+	this._defaults = { // Global defaults for all the datetime picker instances
+		showButtonPanel: true,
+		timeOnly: false,
+		showHour: true,
+		showMinute: true,
+		showSecond: false,
+		showMillisec: false,
+		showTimezone: false,
+		showTime: true,
+		stepHour: 1,
+		stepMinute: 1,
+		stepSecond: 1,
+		stepMillisec: 1,
+		hour: 0,
+		minute: 0,
+		second: 0,
+		millisec: 0,
+		timezone: '+0000',
+		hourMin: 0,
+		minuteMin: 0,
+		secondMin: 0,
+		millisecMin: 0,
+		hourMax: 23,
+		minuteMax: 59,
+		secondMax: 59,
+		millisecMax: 999,
+		minDateTime: null,
+		maxDateTime: null,
+		onSelect: null,
+		hourGrid: 0,
+		minuteGrid: 0,
+		secondGrid: 0,
+		millisecGrid: 0,
+		alwaysSetTime: true,
+		separator: ' ',
+		altFieldTimeOnly: true,
+		showTimepicker: true,
+		timezoneIso8609: false,
+		timezoneList: null,
+		addSliderAccess: false,
+		sliderAccessArgs: null
+	};
+	$.extend(this._defaults, this.regional['']);
+};
+
+$.extend(Timepicker.prototype, {
+	$input: null,
+	$altInput: null,
+	$timeObj: null,
+	inst: null,
+	hour_slider: null,
+	minute_slider: null,
+	second_slider: null,
+	millisec_slider: null,
+	timezone_select: null,
+	hour: 0,
+	minute: 0,
+	second: 0,
+	millisec: 0,
+	timezone: '+0000',
+	hourMinOriginal: null,
+	minuteMinOriginal: null,
+	secondMinOriginal: null,
+	millisecMinOriginal: null,
+	hourMaxOriginal: null,
+	minuteMaxOriginal: null,
+	secondMaxOriginal: null,
+	millisecMaxOriginal: null,
+	ampm: '',
+	formattedDate: '',
+	formattedTime: '',
+	formattedDateTime: '',
+	timezoneList: null,
+
+	/* Override the default settings for all instances of the time picker.
+	   @param  settings  object - the new settings to use as defaults (anonymous object)
+	   @return the manager object */
+	setDefaults: function(settings) {
+		extendRemove(this._defaults, settings || {});
+		return this;
+	},
+
+	//########################################################################
+	// Create a new Timepicker instance
+	//########################################################################
+	_newInst: function($input, o) {
+		var tp_inst = new Timepicker(),
+			inlineSettings = {};
+
+		for (var attrName in this._defaults) {
+			var attrValue = $input.attr('time:' + attrName);
+			if (attrValue) {
+				try {
+					inlineSettings[attrName] = eval(attrValue);
+				} catch (err) {
+					inlineSettings[attrName] = attrValue;
+				}
+			}
+		}
+		tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, {
+			beforeShow: function(input, dp_inst) {
+				if ($.isFunction(o.beforeShow))
+					return o.beforeShow(input, dp_inst, tp_inst);
+			},
+			onChangeMonthYear: function(year, month, dp_inst) {
+				// Update the time as well : this prevents the time from disappearing from the $input field.
+				tp_inst._updateDateTime(dp_inst);
+				if ($.isFunction(o.onChangeMonthYear))
+					o.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);
+			},
+			onClose: function(dateText, dp_inst) {
+				if (tp_inst.timeDefined === true && $input.val() != '')
+					tp_inst._updateDateTime(dp_inst);
+				if ($.isFunction(o.onClose))
+					o.onClose.call($input[0], dateText, dp_inst, tp_inst);
+			},
+			timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
+		});
+		tp_inst.amNames = $.map(tp_inst._defaults.amNames, function(val) { return val.toUpperCase(); });
+		tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function(val) { return val.toUpperCase(); });
+
+		if (tp_inst._defaults.timezoneList === null) {
+			var timezoneList = [];
+			for (var i = -11; i <= 12; i++)
+				timezoneList.push((i >= 0 ? '+' : '-') + ('0' + Math.abs(i).toString()).slice(-2) + '00');
+			if (tp_inst._defaults.timezoneIso8609)
+				timezoneList = $.map(timezoneList, function(val) {
+					return val == '+0000' ? 'Z' : (val.substring(0, 3) + ':' + val.substring(3));
+				});
+			tp_inst._defaults.timezoneList = timezoneList;
+		}
+
+		tp_inst.hour = tp_inst._defaults.hour;
+		tp_inst.minute = tp_inst._defaults.minute;
+		tp_inst.second = tp_inst._defaults.second;
+		tp_inst.millisec = tp_inst._defaults.millisec;
+		tp_inst.ampm = '';
+		tp_inst.$input = $input;
+
+		if (o.altField)
+			tp_inst.$altInput = $(o.altField)
+				.css({ cursor: 'pointer' })
+				.focus(function(){ $input.trigger("focus"); });
+
+		if(tp_inst._defaults.minDate==0 || tp_inst._defaults.minDateTime==0)
+		{
+			tp_inst._defaults.minDate=new Date();
+		}
+		if(tp_inst._defaults.maxDate==0 || tp_inst._defaults.maxDateTime==0)
+		{
+			tp_inst._defaults.maxDate=new Date();
+		}
+
+		// datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..
+		if(tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date)
+			tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());
+		if(tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date)
+			tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());
+		if(tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date)
+			tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());
+		if(tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date)
+			tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());
+		return tp_inst;
+	},
+
+	//########################################################################
+	// add our sliders to the calendar
+	//########################################################################
+	_addTimePicker: function(dp_inst) {
+		var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ?
+				this.$input.val() + ' ' + this.$altInput.val() :
+				this.$input.val();
+
+		this.timeDefined = this._parseTime(currDT);
+		this._limitMinMaxDateTime(dp_inst, false);
+		this._injectTimePicker();
+	},
+
+	//########################################################################
+	// parse the time string from input value or _setTime
+	//########################################################################
+	_parseTime: function(timeString, withDate) {
+		var regstr = this._defaults.timeFormat.toString()
+				.replace(/h{1,2}/ig, '(\\d?\\d)')
+				.replace(/m{1,2}/ig, '(\\d?\\d)')
+				.replace(/s{1,2}/ig, '(\\d?\\d)')
+				.replace(/l{1}/ig, '(\\d?\\d?\\d)')
+				.replace(/t{1,2}/ig, this._getPatternAmpm())
+				.replace(/z{1}/ig, '(z|[-+]\\d\\d:?\\d\\d)?')
+				.replace(/\s/g, '\\s?') + this._defaults.timeSuffix + '$',
+			order = this._getFormatPositions(),
+			ampm = '',
+			treg;
+
+		if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]);
+
+		if (withDate || !this._defaults.timeOnly) {
+			// the time should come after x number of characters and a space.
+			// x = at least the length of text specified by the date format
+			var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');
+			// escape special regex characters in the seperator
+			var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g");
+			regstr = '^.{' + dp_dateFormat.length + ',}?' + this._defaults.separator.replace(specials, "\\$&") + regstr;
+		}
+
+		treg = timeString.match(new RegExp(regstr, 'i'));
+
+		if (treg) {
+			if (order.t !== -1) {
+				if (treg[order.t] === undefined || treg[order.t].length === 0) {
+					ampm = '';
+					this.ampm = '';
+				} else {
+					ampm = $.inArray(treg[order.t].toUpperCase(), this.amNames) !== -1 ? 'AM' : 'PM';
+					this.ampm = this._defaults[ampm == 'AM' ? 'amNames' : 'pmNames'][0];
+				}
+			}
+
+			if (order.h !== -1) {
+				if (ampm == 'AM' && treg[order.h] == '12')
+					this.hour = 0; // 12am = 0 hour
+				else if (ampm == 'PM' && treg[order.h] != '12')
+					this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0); // 12pm = 12 hour, any other pm = hour + 12
+				else this.hour = Number(treg[order.h]);
+			}
+
+			if (order.m !== -1) this.minute = Number(treg[order.m]);
+			if (order.s !== -1) this.second = Number(treg[order.s]);
+			if (order.l !== -1) this.millisec = Number(treg[order.l]);
+			if (order.z !== -1 && treg[order.z] !== undefined) {
+				var tz = treg[order.z].toUpperCase();
+				switch (tz.length) {
+				case 1:	// Z
+					tz = this._defaults.timezoneIso8609 ? 'Z' : '+0000';
+					break;
+				case 5:	// +hhmm
+					if (this._defaults.timezoneIso8609)
+						tz = tz.substring(1) == '0000'
+						   ? 'Z'
+						   : tz.substring(0, 3) + ':' + tz.substring(3);
+					break;
+				case 6:	// +hh:mm
+					if (!this._defaults.timezoneIso8609)
+						tz = tz == 'Z' || tz.substring(1) == '00:00'
+						   ? '+0000'
+						   : tz.replace(/:/, '');
+					else if (tz.substring(1) == '00:00')
+						tz = 'Z';
+					break;
+				}
+				this.timezone = tz;
+			}
+
+			return true;
+
+		}
+		return false;
+	},
+
+	//########################################################################
+	// pattern for standard and localized AM/PM markers
+	//########################################################################
+	_getPatternAmpm: function() {
+		var markers = [],
+			o = this._defaults;
+		if (o.amNames)
+			$.merge(markers, o.amNames);
+		if (o.pmNames)
+			$.merge(markers, o.pmNames);
+		markers = $.map(markers, function(val) { return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&'); });
+		return '(' + markers.join('|') + ')?';
+	},
+
+	//########################################################################
+	// figure out position of time elements.. cause js cant do named captures
+	//########################################################################
+	_getFormatPositions: function() {
+		var finds = this._defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z)/g),
+			orders = { h: -1, m: -1, s: -1, l: -1, t: -1, z: -1 };
+
+		if (finds)
+			for (var i = 0; i < finds.length; i++)
+				if (orders[finds[i].toString().charAt(0)] == -1)
+					orders[finds[i].toString().charAt(0)] = i + 1;
+
+		return orders;
+	},
+
+	//########################################################################
+	// generate and inject html for timepicker into ui datepicker
+	//########################################################################
+	_injectTimePicker: function() {
+		var $dp = this.inst.dpDiv,
+			o = this._defaults,
+			tp_inst = this,
+			// Added by Peter Medeiros:
+			// - Figure out what the hour/minute/second max should be based on the step values.
+			// - Example: if stepMinute is 15, then minMax is 45.
+			hourMax = parseInt((o.hourMax - ((o.hourMax - o.hourMin) % o.stepHour)) ,10),
+			minMax  = parseInt((o.minuteMax - ((o.minuteMax - o.minuteMin) % o.stepMinute)) ,10),
+			secMax  = parseInt((o.secondMax - ((o.secondMax - o.secondMin) % o.stepSecond)) ,10),
+			millisecMax  = parseInt((o.millisecMax - ((o.millisecMax - o.millisecMin) % o.stepMillisec)) ,10),
+			dp_id = this.inst.id.toString().replace(/([^A-Za-z0-9_])/g, '');
+
+		// Prevent displaying twice
+		//if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0) {
+		if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0 && o.showTimepicker) {
+			var noDisplay = ' style="display:none;"',
+				html =	'<div class="ui-timepicker-div" id="ui-timepicker-div-' + dp_id + '"><dl>' +
+						'<dt class="ui_tpicker_time_label" id="ui_tpicker_time_label_' + dp_id + '"' +
+						((o.showTime) ? '' : noDisplay) + '>' + o.timeText + '</dt>' +
+						'<dd class="ui_tpicker_time" id="ui_tpicker_time_' + dp_id + '"' +
+						((o.showTime) ? '' : noDisplay) + '></dd>' +
+						'<dt class="ui_tpicker_hour_label" id="ui_tpicker_hour_label_' + dp_id + '"' +
+						((o.showHour) ? '' : noDisplay) + '>' + o.hourText + '</dt>',
+				hourGridSize = 0,
+				minuteGridSize = 0,
+				secondGridSize = 0,
+				millisecGridSize = 0,
+				size = null;
+
+ 			// Hours
+			html += '<dd class="ui_tpicker_hour"><div id="ui_tpicker_hour_' + dp_id + '"' +
+						((o.showHour) ? '' : noDisplay) + '></div>';
+			if (o.showHour && o.hourGrid > 0) {
+				html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
+
+				for (var h = o.hourMin; h <= hourMax; h += parseInt(o.hourGrid,10)) {
+					hourGridSize++;
+					var tmph = (o.ampm && h > 12) ? h-12 : h;
+					if (tmph < 10) tmph = '0' + tmph;
+					if (o.ampm) {
+						if (h == 0) tmph = 12 +'a';
+						else if (h < 12) tmph += 'a';
+						else tmph += 'p';
+					}
+					html += '<td>' + tmph + '</td>';
+				}
+
+				html += '</tr></table></div>';
+			}
+			html += '</dd>';
+
+			// Minutes
+			html += '<dt class="ui_tpicker_minute_label" id="ui_tpicker_minute_label_' + dp_id + '"' +
+					((o.showMinute) ? '' : noDisplay) + '>' + o.minuteText + '</dt>'+
+					'<dd class="ui_tpicker_minute"><div id="ui_tpicker_minute_' + dp_id + '"' +
+							((o.showMinute) ? '' : noDisplay) + '></div>';
+
+			if (o.showMinute && o.minuteGrid > 0) {
+				html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
+
+				for (var m = o.minuteMin; m <= minMax; m += parseInt(o.minuteGrid,10)) {
+					minuteGridSize++;
+					html += '<td>' + ((m < 10) ? '0' : '') + m + '</td>';
+				}
+
+				html += '</tr></table></div>';
+			}
+			html += '</dd>';
+
+			// Seconds
+			html += '<dt class="ui_tpicker_second_label" id="ui_tpicker_second_label_' + dp_id + '"' +
+					((o.showSecond) ? '' : noDisplay) + '>' + o.secondText + '</dt>'+
+					'<dd class="ui_tpicker_second"><div id="ui_tpicker_second_' + dp_id + '"'+
+							((o.showSecond) ? '' : noDisplay) + '></div>';
+
+			if (o.showSecond && o.secondGrid > 0) {
+				html += '<div style="padding-left: 1px"><table><tr>';
+
+				for (var s = o.secondMin; s <= secMax; s += parseInt(o.secondGrid,10)) {
+					secondGridSize++;
+					html += '<td>' + ((s < 10) ? '0' : '') + s + '</td>';
+				}
+
+				html += '</tr></table></div>';
+			}
+			html += '</dd>';
+
+			// Milliseconds
+			html += '<dt class="ui_tpicker_millisec_label" id="ui_tpicker_millisec_label_' + dp_id + '"' +
+					((o.showMillisec) ? '' : noDisplay) + '>' + o.millisecText + '</dt>'+
+					'<dd class="ui_tpicker_millisec"><div id="ui_tpicker_millisec_' + dp_id + '"'+
+							((o.showMillisec) ? '' : noDisplay) + '></div>';
+
+			if (o.showMillisec && o.millisecGrid > 0) {
+				html += '<div style="padding-left: 1px"><table><tr>';
+
+				for (var l = o.millisecMin; l <= millisecMax; l += parseInt(o.millisecGrid,10)) {
+					millisecGridSize++;
+					html += '<td>' + ((l < 10) ? '0' : '') + l + '</td>';
+				}
+
+				html += '</tr></table></div>';
+			}
+			html += '</dd>';
+
+			// Timezone
+			html += '<dt class="ui_tpicker_timezone_label" id="ui_tpicker_timezone_label_' + dp_id + '"' +
+					((o.showTimezone) ? '' : noDisplay) + '>' + o.timezoneText + '</dt>';
+			html += '<dd class="ui_tpicker_timezone" id="ui_tpicker_timezone_' + dp_id + '"'	+
+							((o.showTimezone) ? '' : noDisplay) + '></dd>';
+
+			html += '</dl></div>';
+			$tp = $(html);
+
+				// if we only want time picker...
+			if (o.timeOnly === true) {
+				$tp.prepend(
+					'<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' +
+						'<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' +
+					'</div>');
+				$dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
+			}
+
+			this.hour_slider = $tp.find('#ui_tpicker_hour_'+ dp_id).slider({
+				orientation: "horizontal",
+				value: this.hour,
+				min: o.hourMin,
+				max: hourMax,
+				step: o.stepHour,
+				slide: function(event, ui) {
+					tp_inst.hour_slider.slider( "option", "value", ui.value);
+					tp_inst._onTimeChange();
+				}
+			});
+
+
+			// Updated by Peter Medeiros:
+			// - Pass in Event and UI instance into slide function
+			this.minute_slider = $tp.find('#ui_tpicker_minute_'+ dp_id).slider({
+				orientation: "horizontal",
+				value: this.minute,
+				min: o.minuteMin,
+				max: minMax,
+				step: o.stepMinute,
+				slide: function(event, ui) {
+					tp_inst.minute_slider.slider( "option", "value", ui.value);
+					tp_inst._onTimeChange();
+				}
+			});
+
+			this.second_slider = $tp.find('#ui_tpicker_second_'+ dp_id).slider({
+				orientation: "horizontal",
+				value: this.second,
+				min: o.secondMin,
+				max: secMax,
+				step: o.stepSecond,
+				slide: function(event, ui) {
+					tp_inst.second_slider.slider( "option", "value", ui.value);
+					tp_inst._onTimeChange();
+				}
+			});
+
+			this.millisec_slider = $tp.find('#ui_tpicker_millisec_'+ dp_id).slider({
+				orientation: "horizontal",
+				value: this.millisec,
+				min: o.millisecMin,
+				max: millisecMax,
+				step: o.stepMillisec,
+				slide: function(event, ui) {
+					tp_inst.millisec_slider.slider( "option", "value", ui.value);
+					tp_inst._onTimeChange();
+				}
+			});
+
+			this.timezone_select = $tp.find('#ui_tpicker_timezone_'+ dp_id).append('<select></select>').find("select");
+			$.fn.append.apply(this.timezone_select,
+				$.map(o.timezoneList, function(val, idx) {
+					return $("<option />")
+						.val(typeof val == "object" ? val.value : val)
+						.text(typeof val == "object" ? val.label : val);
+				})
+			);
+			this.timezone_select.val((typeof this.timezone != "undefined" && this.timezone != null && this.timezone != "") ? this.timezone : o.timezone);
+			this.timezone_select.change(function() {
+				tp_inst._onTimeChange();
+			});
+
+			// Add grid functionality
+			if (o.showHour && o.hourGrid > 0) {
+				size = 100 * hourGridSize * o.hourGrid / (hourMax - o.hourMin);
+
+				$tp.find(".ui_tpicker_hour table").css({
+					width: size + "%",
+					marginLeft: (size / (-2 * hourGridSize)) + "%",
+					borderCollapse: 'collapse'
+				}).find("td").each( function(index) {
+					$(this).click(function() {
+						var h = $(this).html();
+						if(o.ampm)	{
+							var ap = h.substring(2).toLowerCase(),
+								aph = parseInt(h.substring(0,2), 10);
+							if (ap == 'a') {
+								if (aph == 12) h = 0;
+								else h = aph;
+							} else if (aph == 12) h = 12;
+							else h = aph + 12;
+						}
+						tp_inst.hour_slider.slider("option", "value", h);
+						tp_inst._onTimeChange();
+						tp_inst._onSelectHandler();
+					}).css({
+						cursor: 'pointer',
+						width: (100 / hourGridSize) + '%',
+						textAlign: 'center',
+						overflow: 'hidden'
+					});
+				});
+			}
+
+			if (o.showMinute && o.minuteGrid > 0) {
+				size = 100 * minuteGridSize * o.minuteGrid / (minMax - o.minuteMin);
+				$tp.find(".ui_tpicker_minute table").css({
+					width: size + "%",
+					marginLeft: (size / (-2 * minuteGridSize)) + "%",
+					borderCollapse: 'collapse'
+				}).find("td").each(function(index) {
+					$(this).click(function() {
+						tp_inst.minute_slider.slider("option", "value", $(this).html());
+						tp_inst._onTimeChange();
+						tp_inst._onSelectHandler();
+					}).css({
+						cursor: 'pointer',
+						width: (100 / minuteGridSize) + '%',
+						textAlign: 'center',
+						overflow: 'hidden'
+					});
+				});
+			}
+
+			if (o.showSecond && o.secondGrid > 0) {
+				$tp.find(".ui_tpicker_second table").css({
+					width: size + "%",
+					marginLeft: (size / (-2 * secondGridSize)) + "%",
+					borderCollapse: 'collapse'
+				}).find("td").each(function(index) {
+					$(this).click(function() {
+						tp_inst.second_slider.slider("option", "value", $(this).html());
+						tp_inst._onTimeChange();
+						tp_inst._onSelectHandler();
+					}).css({
+						cursor: 'pointer',
+						width: (100 / secondGridSize) + '%',
+						textAlign: 'center',
+						overflow: 'hidden'
+					});
+				});
+			}
+
+			if (o.showMillisec && o.millisecGrid > 0) {
+				$tp.find(".ui_tpicker_millisec table").css({
+					width: size + "%",
+					marginLeft: (size / (-2 * millisecGridSize)) + "%",
+					borderCollapse: 'collapse'
+				}).find("td").each(function(index) {
+					$(this).click(function() {
+						tp_inst.millisec_slider.slider("option", "value", $(this).html());
+						tp_inst._onTimeChange();
+						tp_inst._onSelectHandler();
+					}).css({
+						cursor: 'pointer',
+						width: (100 / millisecGridSize) + '%',
+						textAlign: 'center',
+						overflow: 'hidden'
+					});
+				});
+			}
+
+			var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');
+			if ($buttonPanel.length) $buttonPanel.before($tp);
+			else $dp.append($tp);
+
+			this.$timeObj = $tp.find('#ui_tpicker_time_'+ dp_id);
+
+			if (this.inst !== null) {
+				var timeDefined = this.timeDefined;
+				this._onTimeChange();
+				this.timeDefined = timeDefined;
+			}
+
+			//Emulate datepicker onSelect behavior. Call on slidestop.
+			var onSelectDelegate = function() {
+				tp_inst._onSelectHandler();
+			};
+			this.hour_slider.bind('slidestop',onSelectDelegate);
+			this.minute_slider.bind('slidestop',onSelectDelegate);
+			this.second_slider.bind('slidestop',onSelectDelegate);
+			this.millisec_slider.bind('slidestop',onSelectDelegate);
+
+			// slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/
+			if (this._defaults.addSliderAccess){
+				var sliderAccessArgs = this._defaults.sliderAccessArgs;
+				setTimeout(function(){ // fix for inline mode
+					if($tp.find('.ui-slider-access').length == 0){
+						$tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);
+
+						// fix any grids since sliders are shorter
+						var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);
+						if(sliderAccessWidth){
+							$tp.find('table:visible').each(function(){
+								var $g = $(this),
+									oldWidth = $g.outerWidth(),
+									oldMarginLeft = $g.css('marginLeft').toString().replace('%',''),
+									newWidth = oldWidth - sliderAccessWidth,
+									newMarginLeft = ((oldMarginLeft * newWidth)/oldWidth) + '%';
+
+								$g.css({ width: newWidth, marginLeft: newMarginLeft });
+							});
+						}
+					}
+				},0);
+			}
+			// end slideAccess integration
+
+		}
+	},
+
+	//########################################################################
+	// This function tries to limit the ability to go outside the
+	// min/max date range
+	//########################################################################
+	_limitMinMaxDateTime: function(dp_inst, adjustSliders){
+		var o = this._defaults,
+			dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);
+
+		if(!this._defaults.showTimepicker) return; // No time so nothing to check here
+
+		if($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date){
+			var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),
+				minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);
+
+			if(this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null){
+				this.hourMinOriginal = o.hourMin;
+				this.minuteMinOriginal = o.minuteMin;
+				this.secondMinOriginal = o.secondMin;
+				this.millisecMinOriginal = o.millisecMin;
+			}
+
+			if(dp_inst.settings.timeOnly || minDateTimeDate.getTime() == dp_date.getTime()) {
+				this._defaults.hourMin = minDateTime.getHours();
+				if (this.hour <= this._defaults.hourMin) {
+					this.hour = this._defaults.hourMin;
+					this._defaults.minuteMin = minDateTime.getMinutes();
+					if (this.minute <= this._defaults.minuteMin) {
+						this.minute = this._defaults.minuteMin;
+						this._defaults.secondMin = minDateTime.getSeconds();
+					} else if (this.second <= this._defaults.secondMin){
+						this.second = this._defaults.secondMin;
+						this._defaults.millisecMin = minDateTime.getMilliseconds();
+					} else {
+						if(this.millisec < this._defaults.millisecMin)
+							this.millisec = this._defaults.millisecMin;
+						this._defaults.millisecMin = this.millisecMinOriginal;
+					}
+				} else {
+					this._defaults.minuteMin = this.minuteMinOriginal;
+					this._defaults.secondMin = this.secondMinOriginal;
+					this._defaults.millisecMin = this.millisecMinOriginal;
+				}
+			}else{
+				this._defaults.hourMin = this.hourMinOriginal;
+				this._defaults.minuteMin = this.minuteMinOriginal;
+				this._defaults.secondMin = this.secondMinOriginal;
+				this._defaults.millisecMin = this.millisecMinOriginal;
+			}
+		}
+
+		if($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date){
+			var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),
+				maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);
+
+			if(this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null){
+				this.hourMaxOriginal = o.hourMax;
+				this.minuteMaxOriginal = o.minuteMax;
+				this.secondMaxOriginal = o.secondMax;
+				this.millisecMaxOriginal = o.millisecMax;
+			}
+
+			if(dp_inst.settings.timeOnly || maxDateTimeDate.getTime() == dp_date.getTime()){
+				this._defaults.hourMax = maxDateTime.getHours();
+				if (this.hour >= this._defaults.hourMax) {
+					this.hour = this._defaults.hourMax;
+					this._defaults.minuteMax = maxDateTime.getMinutes();
+					if (this.minute >= this._defaults.minuteMax) {
+						this.minute = this._defaults.minuteMax;
+						this._defaults.secondMax = maxDateTime.getSeconds();
+					} else if (this.second >= this._defaults.secondMax) {
+						this.second = this._defaults.secondMax;
+						this._defaults.millisecMax = maxDateTime.getMilliseconds();
+					} else {
+						if(this.millisec > this._defaults.millisecMax) this.millisec = this._defaults.millisecMax;
+						this._defaults.millisecMax = this.millisecMaxOriginal;
+					}
+				} else {
+					this._defaults.minuteMax = this.minuteMaxOriginal;
+					this._defaults.secondMax = this.secondMaxOriginal;
+					this._defaults.millisecMax = this.millisecMaxOriginal;
+				}
+			}else{
+				this._defaults.hourMax = this.hourMaxOriginal;
+				this._defaults.minuteMax = this.minuteMaxOriginal;
+				this._defaults.secondMax = this.secondMaxOriginal;
+				this._defaults.millisecMax = this.millisecMaxOriginal;
+			}
+		}
+
+		if(adjustSliders !== undefined && adjustSliders === true){
+			var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)) ,10),
+                minMax  = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)) ,10),
+                secMax  = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)) ,10),
+				millisecMax  = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)) ,10);
+
+			if(this.hour_slider)
+				this.hour_slider.slider("option", { min: this._defaults.hourMin, max: hourMax }).slider('value', this.hour);
+			if(this.minute_slider)
+				this.minute_slider.slider("option", { min: this._defaults.minuteMin, max: minMax }).slider('value', this.minute);
+			if(this.second_slider)
+				this.second_slider.slider("option", { min: this._defaults.secondMin, max: secMax }).slider('value', this.second);
+			if(this.millisec_slider)
+				this.millisec_slider.slider("option", { min: this._defaults.millisecMin, max: millisecMax }).slider('value', this.millisec);
+		}
+
+	},
+
+
+	//########################################################################
+	// when a slider moves, set the internal time...
+	// on time change is also called when the time is updated in the text field
+	//########################################################################
+	_onTimeChange: function() {
+		var hour   = (this.hour_slider) ? this.hour_slider.slider('value') : false,
+			minute = (this.minute_slider) ? this.minute_slider.slider('value') : false,
+			second = (this.second_slider) ? this.second_slider.slider('value') : false,
+			millisec = (this.millisec_slider) ? this.millisec_slider.slider('value') : false,
+			timezone = (this.timezone_select) ? this.timezone_select.val() : false,
+			o = this._defaults;
+
+		if (typeof(hour) == 'object') hour = false;
+		if (typeof(minute) == 'object') minute = false;
+		if (typeof(second) == 'object') second = false;
+		if (typeof(millisec) == 'object') millisec = false;
+		if (typeof(timezone) == 'object') timezone = false;
+
+		if (hour !== false) hour = parseInt(hour,10);
+		if (minute !== false) minute = parseInt(minute,10);
+		if (second !== false) second = parseInt(second,10);
+		if (millisec !== false) millisec = parseInt(millisec,10);
+
+		var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];
+
+		// If the update was done in the input field, the input field should not be updated.
+		// If the update was done using the sliders, update the input field.
+		var hasChanged = (hour != this.hour || minute != this.minute
+				|| second != this.second || millisec != this.millisec
+				|| (this.ampm.length > 0
+				    && (hour < 12) != ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1))
+				|| timezone != this.timezone);
+
+		if (hasChanged) {
+
+			if (hour !== false)this.hour = hour;
+			if (minute !== false) this.minute = minute;
+			if (second !== false) this.second = second;
+			if (millisec !== false) this.millisec = millisec;
+			if (timezone !== false) this.timezone = timezone;
+
+			if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]);
+
+			this._limitMinMaxDateTime(this.inst, true);
+		}
+		if (o.ampm) this.ampm = ampm;
+
+		//this._formatTime();
+		this.formattedTime = $.datepicker.formatTime(this._defaults.timeFormat, this, this._defaults);
+		if (this.$timeObj) this.$timeObj.text(this.formattedTime + o.timeSuffix);
+		this.timeDefined = true;
+		if (hasChanged) this._updateDateTime();
+	},
+
+	//########################################################################
+	// call custom onSelect.
+	// bind to sliders slidestop, and grid click.
+	//########################################################################
+	_onSelectHandler: function() {
+		var onSelect = this._defaults.onSelect;
+		var inputEl = this.$input ? this.$input[0] : null;
+		if (onSelect && inputEl) {
+			onSelect.apply(inputEl, [this.formattedDateTime, this]);
+		}
+	},
+
+	//########################################################################
+	// left for any backwards compatibility
+	//########################################################################
+	_formatTime: function(time, format) {
+		time = time || { hour: this.hour, minute: this.minute, second: this.second, millisec: this.millisec, ampm: this.ampm, timezone: this.timezone };
+		var tmptime = (format || this._defaults.timeFormat).toString();
+
+		tmptime = $.datepicker.formatTime(tmptime, time, this._defaults);
+
+		if (arguments.length) return tmptime;
+		else this.formattedTime = tmptime;
+	},
+
+	//########################################################################
+	// update our input with the new date time..
+	//########################################################################
+	_updateDateTime: function(dp_inst) {
+		dp_inst = this.inst || dp_inst;
+		var dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),
+			dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),
+			formatCfg = $.datepicker._getFormatConfig(dp_inst),
+			timeAvailable = dt !== null && this.timeDefined;
+		this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
+		var formattedDateTime = this.formattedDate;
+		if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0))
+			return;
+
+		if (this._defaults.timeOnly === true) {
+			formattedDateTime = this.formattedTime;
+		} else if (this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) {
+			formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;
+		}
+
+		this.formattedDateTime = formattedDateTime;
+
+		if(!this._defaults.showTimepicker) {
+			this.$input.val(this.formattedDate);
+		} else if (this.$altInput && this._defaults.altFieldTimeOnly === true) {
+			this.$altInput.val(this.formattedTime);
+			this.$input.val(this.formattedDate);
+		} else if(this.$altInput) {
+			this.$altInput.val(formattedDateTime);
+			this.$input.val(formattedDateTime);
+		} else {
+			this.$input.val(formattedDateTime);
+		}
+
+		this.$input.trigger("change");
+	}
+
+});
+
+$.fn.extend({
+	//########################################################################
+	// shorthand just to use timepicker..
+	//########################################################################
+	timepicker: function(o) {
+		o = o || {};
+		var tmp_args = arguments;
+
+		if (typeof o == 'object') tmp_args[0] = $.extend(o, { timeOnly: true });
+
+		return $(this).each(function() {
+			$.fn.datetimepicker.apply($(this), tmp_args);
+		});
+	},
+
+	//########################################################################
+	// extend timepicker to datepicker
+	//########################################################################
+	datetimepicker: function(o) {
+		o = o || {};
+		tmp_args = arguments;
+
+		if (typeof(o) == 'string'){
+			if(o == 'getDate')
+				return $.fn.datepicker.apply($(this[0]), tmp_args);
+			else
+				return this.each(function() {
+					var $t = $(this);
+					$t.datepicker.apply($t, tmp_args);
+				});
+		}
+		else
+			return this.each(function() {
+				var $t = $(this);
+				$t.datepicker($.timepicker._newInst($t, o)._defaults);
+			});
+	}
+});
+
+//########################################################################
+// format the time all pretty...
+// format = string format of the time
+// time = a {}, not a Date() for timezones
+// options = essentially the regional[].. amNames, pmNames, ampm
+//########################################################################
+$.datepicker.formatTime = function(format, time, options) {
+	options = options || {};
+	options = $.extend($.timepicker._defaults, options);
+	time = $.extend({hour:0, minute:0, second:0, millisec:0, timezone:'+0000'}, time);
+
+	var tmptime = format;
+	var ampmName = options['amNames'][0];
+
+	var hour = parseInt(time.hour, 10);
+	if (options.ampm) {
+		if (hour > 11){
+			ampmName = options['pmNames'][0];
+			if(hour > 12)
+				hour = hour % 12;
+		}
+		if (hour === 0)
+			hour = 12;
+	}
+	tmptime = tmptime.replace(/(?:hh?|mm?|ss?|[tT]{1,2}|[lz])/g, function(match) {
+		switch (match.toLowerCase()) {
+			case 'hh': return ('0' + hour).slice(-2);
+			case 'h':  return hour;
+			case 'mm': return ('0' + time.minute).slice(-2);
+			case 'm':  return time.minute;
+			case 'ss': return ('0' + time.second).slice(-2);
+			case 's':  return time.second;
+			case 'l':  return ('00' + time.millisec).slice(-3);
+			case 'z':  return time.timezone;
+			case 't': case 'tt':
+				if (options.ampm) {
+					if (match.length == 1)
+						ampmName = ampmName.charAt(0);
+					return match.charAt(0) == 'T' ? ampmName.toUpperCase() : ampmName.toLowerCase();
+				}
+				return '';
+		}
+	});
+
+	tmptime = $.trim(tmptime);
+	return tmptime;
+};
+
+//########################################################################
+// the bad hack :/ override datepicker so it doesnt close on select
+// inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
+//########################################################################
+$.datepicker._base_selectDate = $.datepicker._selectDate;
+$.datepicker._selectDate = function (id, dateStr) {
+	var inst = this._getInst($(id)[0]),
+		tp_inst = this._get(inst, 'timepicker');
+
+	if (tp_inst) {
+		tp_inst._limitMinMaxDateTime(inst, true);
+		inst.inline = inst.stay_open = true;
+		//This way the onSelect handler called from calendarpicker get the full dateTime
+		this._base_selectDate(id, dateStr);
+		inst.inline = inst.stay_open = false;
+		this._notifyChange(inst);
+		this._updateDatepicker(inst);
+	}
+	else this._base_selectDate(id, dateStr);
+};
+
+//#############################################################################################
+// second bad hack :/ override datepicker so it triggers an event when changing the input field
+// and does not redraw the datepicker on every selectDate event
+//#############################################################################################
+$.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
+$.datepicker._updateDatepicker = function(inst) {
+
+	// don't popup the datepicker if there is another instance already opened
+	var input = inst.input[0];
+	if($.datepicker._curInst &&
+	   $.datepicker._curInst != inst &&
+	   $.datepicker._datepickerShowing &&
+	   $.datepicker._lastInput != input) {
+		return;
+	}
+
+	if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
+
+		this._base_updateDatepicker(inst);
+
+		// Reload the time control when changing something in the input text field.
+		var tp_inst = this._get(inst, 'timepicker');
+		if(tp_inst) tp_inst._addTimePicker(inst);
+	}
+};
+
+//#######################################################################################
+// third bad hack :/ override datepicker so it allows spaces and colon in the input field
+//#######################################################################################
+$.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
+$.datepicker._doKeyPress = function(event) {
+	var inst = $.datepicker._getInst(event.target),
+		tp_inst = $.datepicker._get(inst, 'timepicker');
+
+	if (tp_inst) {
+		if ($.datepicker._get(inst, 'constrainInput')) {
+			var ampm = tp_inst._defaults.ampm,
+				dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),
+				datetimeChars = tp_inst._defaults.timeFormat.toString()
+								.replace(/[hms]/g, '')
+								.replace(/TT/g, ampm ? 'APM' : '')
+								.replace(/Tt/g, ampm ? 'AaPpMm' : '')
+								.replace(/tT/g, ampm ? 'AaPpMm' : '')
+								.replace(/T/g, ampm ? 'AP' : '')
+								.replace(/tt/g, ampm ? 'apm' : '')
+								.replace(/t/g, ampm ? 'ap' : '') +
+								" " +
+								tp_inst._defaults.separator +
+								tp_inst._defaults.timeSuffix +
+								(tp_inst._defaults.showTimezone ? tp_inst._defaults.timezoneList.join('') : '') +
+								(tp_inst._defaults.amNames.join('')) +
+								(tp_inst._defaults.pmNames.join('')) +
+								dateChars,
+				chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
+			return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);
+		}
+	}
+
+	return $.datepicker._base_doKeyPress(event);
+};
+
+//#######################################################################################
+// Override key up event to sync manual input changes.
+//#######################################################################################
+$.datepicker._base_doKeyUp = $.datepicker._doKeyUp;
+$.datepicker._doKeyUp = function (event) {
+	var inst = $.datepicker._getInst(event.target),
+		tp_inst = $.datepicker._get(inst, 'timepicker');
+
+	if (tp_inst) {
+		if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) {
+			try {
+				$.datepicker._updateDatepicker(inst);
+			}
+			catch (err) {
+				$.datepicker.log(err);
+			}
+		}
+	}
+
+	return $.datepicker._base_doKeyUp(event);
+};
+
+//#######################################################################################
+// override "Today" button to also grab the time.
+//#######################################################################################
+$.datepicker._base_gotoToday = $.datepicker._gotoToday;
+$.datepicker._gotoToday = function(id) {
+	var inst = this._getInst($(id)[0]),
+		$dp = inst.dpDiv;
+	this._base_gotoToday(id);
+	var now = new Date();
+	var tp_inst = this._get(inst, 'timepicker');
+	if (tp_inst && tp_inst._defaults.showTimezone && tp_inst.timezone_select) {
+		var tzoffset = now.getTimezoneOffset(); // If +0100, returns -60
+		var tzsign = tzoffset > 0 ? '-' : '+';
+		tzoffset = Math.abs(tzoffset);
+		var tzmin = tzoffset % 60;
+		tzoffset = tzsign + ('0' + (tzoffset - tzmin) / 60).slice(-2) + ('0' + tzmin).slice(-2);
+		if (tp_inst._defaults.timezoneIso8609)
+			tzoffset = tzoffset.substring(0, 3) + ':' + tzoffset.substring(3);
+		tp_inst.timezone_select.val(tzoffset);
+	}
+	this._setTime(inst, now);
+	$( '.ui-datepicker-today', $dp).click();
+};
+
+//#######################################################################################
+// Disable & enable the Time in the datetimepicker
+//#######################################################################################
+$.datepicker._disableTimepickerDatepicker = function(target, date, withDate) {
+	var inst = this._getInst(target),
+	tp_inst = this._get(inst, 'timepicker');
+	$(target).datepicker('getDate'); // Init selected[Year|Month|Day]
+	if (tp_inst) {
+		tp_inst._defaults.showTimepicker = false;
+		tp_inst._updateDateTime(inst);
+	}
+};
+
+$.datepicker._enableTimepickerDatepicker = function(target, date, withDate) {
+	var inst = this._getInst(target),
+	tp_inst = this._get(inst, 'timepicker');
+	$(target).datepicker('getDate'); // Init selected[Year|Month|Day]
+	if (tp_inst) {
+		tp_inst._defaults.showTimepicker = true;
+		tp_inst._addTimePicker(inst); // Could be disabled on page load
+		tp_inst._updateDateTime(inst);
+	}
+};
+
+//#######################################################################################
+// Create our own set time function
+//#######################################################################################
+$.datepicker._setTime = function(inst, date) {
+	var tp_inst = this._get(inst, 'timepicker');
+	if (tp_inst) {
+		var defaults = tp_inst._defaults,
+			// calling _setTime with no date sets time to defaults
+			hour = date ? date.getHours() : defaults.hour,
+			minute = date ? date.getMinutes() : defaults.minute,
+			second = date ? date.getSeconds() : defaults.second,
+			millisec = date ? date.getMilliseconds() : defaults.millisec;
+
+		//check if within min/max times..
+		if ((hour < defaults.hourMin || hour > defaults.hourMax) || (minute < defaults.minuteMin || minute > defaults.minuteMax) || (second < defaults.secondMin || second > defaults.secondMax) || (millisec < defaults.millisecMin || millisec > defaults.millisecMax)) {
+			hour = defaults.hourMin;
+			minute = defaults.minuteMin;
+			second = defaults.secondMin;
+			millisec = defaults.millisecMin;
+		}
+
+		tp_inst.hour = hour;
+		tp_inst.minute = minute;
+		tp_inst.second = second;
+		tp_inst.millisec = millisec;
+
+		if (tp_inst.hour_slider) tp_inst.hour_slider.slider('value', hour);
+		if (tp_inst.minute_slider) tp_inst.minute_slider.slider('value', minute);
+		if (tp_inst.second_slider) tp_inst.second_slider.slider('value', second);
+		if (tp_inst.millisec_slider) tp_inst.millisec_slider.slider('value', millisec);
+
+		tp_inst._onTimeChange();
+		tp_inst._updateDateTime(inst);
+	}
+};
+
+//#######################################################################################
+// Create new public method to set only time, callable as $().datepicker('setTime', date)
+//#######################################################################################
+$.datepicker._setTimeDatepicker = function(target, date, withDate) {
+	var inst = this._getInst(target),
+		tp_inst = this._get(inst, 'timepicker');
+
+	if (tp_inst) {
+		this._setDateFromField(inst);
+		var tp_date;
+		if (date) {
+			if (typeof date == "string") {
+				tp_inst._parseTime(date, withDate);
+				tp_date = new Date();
+				tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
+			}
+			else tp_date = new Date(date.getTime());
+			if (tp_date.toString() == 'Invalid Date') tp_date = undefined;
+			this._setTime(inst, tp_date);
+		}
+	}
+
+};
+
+//#######################################################################################
+// override setDate() to allow setting time too within Date object
+//#######################################################################################
+$.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;
+$.datepicker._setDateDatepicker = function(target, date) {
+	var inst = this._getInst(target),
+	tp_date = (date instanceof Date) ? new Date(date.getTime()) : date;
+
+	this._updateDatepicker(inst);
+	this._base_setDateDatepicker.apply(this, arguments);
+	this._setTimeDatepicker(target, tp_date, true);
+};
+
+//#######################################################################################
+// override getDate() to allow getting time too within Date object
+//#######################################################################################
+$.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;
+$.datepicker._getDateDatepicker = function(target, noDefault) {
+	var inst = this._getInst(target),
+		tp_inst = this._get(inst, 'timepicker');
+
+	if (tp_inst) {
+		this._setDateFromField(inst, noDefault);
+		var date = this._getDate(inst);
+		if (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
+		return date;
+	}
+	return this._base_getDateDatepicker(target, noDefault);
+};
+
+//#######################################################################################
+// override parseDate() because UI 1.8.14 throws an error about "Extra characters"
+// An option in datapicker to ignore extra format characters would be nicer.
+//#######################################################################################
+$.datepicker._base_parseDate = $.datepicker.parseDate;
+$.datepicker.parseDate = function(format, value, settings) {
+	var date;
+	try {
+		date = this._base_parseDate(format, value, settings);
+	} catch (err) {
+		if (err.indexOf(":") >= 0) {
+			// Hack!  The error message ends with a colon, a space, and
+			// the "extra" characters.  We rely on that instead of
+			// attempting to perfectly reproduce the parsing algorithm.
+			date = this._base_parseDate(format, value.substring(0,value.length-(err.length-err.indexOf(':')-2)), settings);
+		} else {
+			// The underlying error was not related to the time
+			throw err;
+		}
+	}
+	return date;
+};
+
+//#######################################################################################
+// override formatDate to set date with time to the input
+//#######################################################################################
+$.datepicker._base_formatDate = $.datepicker._formatDate;
+$.datepicker._formatDate = function(inst, day, month, year){
+	var tp_inst = this._get(inst, 'timepicker');
+	if(tp_inst) {
+		tp_inst._updateDateTime(inst);
+		return tp_inst.$input.val();
+	}
+	return this._base_formatDate(inst);
+};
+
+//#######################################################################################
+// override options setter to add time to maxDate(Time) and minDate(Time). MaxDate
+//#######################################################################################
+$.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;
+$.datepicker._optionDatepicker = function(target, name, value) {
+	var inst = this._getInst(target),
+		tp_inst = this._get(inst, 'timepicker');
+	if (tp_inst) {
+		var min = null, max = null, onselect = null;
+		if (typeof name == 'string') { // if min/max was set with the string
+			if (name === 'minDate' || name === 'minDateTime' )
+				min = value;
+			else if (name === 'maxDate' || name === 'maxDateTime')
+				max = value;
+			else if (name === 'onSelect')
+				onselect = value;
+		} else if (typeof name == 'object') { //if min/max was set with the JSON
+			if (name.minDate)
+				min = name.minDate;
+			else if (name.minDateTime)
+				min = name.minDateTime;
+			else if (name.maxDate)
+				max = name.maxDate;
+			else if (name.maxDateTime)
+				max = name.maxDateTime;
+		}
+		if(min) { //if min was set
+			if (min == 0)
+				min = new Date();
+			else
+				min = new Date(min);
+
+			tp_inst._defaults.minDate = min;
+			tp_inst._defaults.minDateTime = min;
+		} else if (max) { //if max was set
+			if(max==0)
+				max=new Date();
+			else
+				max= new Date(max);
+			tp_inst._defaults.maxDate = max;
+			tp_inst._defaults.maxDateTime = max;
+		} else if (onselect)
+			tp_inst._defaults.onSelect = onselect;
+	}
+	if (value === undefined)
+		return this._base_optionDatepicker(target, name);
+	return this._base_optionDatepicker(target, name, value);
+};
+
+//#######################################################################################
+// jQuery extend now ignores nulls!
+//#######################################################################################
+function extendRemove(target, props) {
+	$.extend(target, props);
+	for (var name in props)
+		if (props[name] === null || props[name] === undefined)
+			target[name] = props[name];
+	return target;
+};
+
+$.timepicker = new Timepicker(); // singleton instance
+$.timepicker.version = "1.0.0";
+
+})(jQuery);
diff --git a/rt/share/html/NoAuth/js/ui.timepickr.js b/rt/share/html/NoAuth/js/ui.timepickr.js
deleted file mode 100644
index 3b2040a..0000000
--- a/rt/share/html/NoAuth/js/ui.timepickr.js
+++ /dev/null
@@ -1,941 +0,0 @@
-/*
-  jQuery utils - @VERSION
-  http://code.google.com/p/jquery-utils/
-
-  (c) Maxime Haineault <haineault at gmail.com> 
-  http://haineault.com
-
-  MIT License (http://www.opensource.org/licenses/mit-license.php
-
-*/
-
-(function($){
-     $.extend($.expr[':'], {
-        // case insensitive version of :contains
-        icontains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").toLowerCase().indexOf(m[3].toLowerCase())>=0;}
-    });
-
-    $.iterators = {
-        getText:  function() { return $(this).text(); },
-        parseInt: function(v){ return parseInt(v, 10); }
-    };
-
-	$.extend({ 
-
-        // Returns a range object
-        // Author: Matthias Miller
-        // Site:   http://blog.outofhanwell.com/2006/03/29/javascript-range-function/
-        range:  function() {
-            if (!arguments.length) { return []; }
-            var min, max, step;
-            if (arguments.length == 1) {
-                min  = 0;
-                max  = arguments[0]-1;
-                step = 1;
-            }
-            else {
-                // default step to 1 if it's zero or undefined
-                min  = arguments[0];
-                max  = arguments[1]-1;
-                step = arguments[2] || 1;
-            }
-            // convert negative steps to positive and reverse min/max
-            if (step < 0 && min >= max) {
-                step *= -1;
-                var tmp = min;
-                min = max;
-                max = tmp;
-                min += ((max-min) % step);
-            }
-            var a = [];
-            for (var i = min; i <= max; i += step) { a.push(i); }
-            return a;
-        },
-
-        // Taken from ui.core.js. 
-        // Why are you keeping this gem for yourself guys ? :|
-        keyCode: {
-            BACKSPACE: 8, CAPS_LOCK: 20, COMMA: 188, CONTROL: 17, DELETE: 46, DOWN: 40,
-            END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, INSERT:  45, LEFT: 37,
-            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
-        },
-        
-        // Takes a keyboard event and return true if the keycode match the specified keycode
-        keyIs: function(k, e) {
-            return parseInt($.keyCode[k.toUpperCase()], 10) == parseInt((typeof(e) == 'number' )? e: e.keyCode, 10);
-        },
-        
-        // Returns the key of an array
-        keys: function(arr) {
-            var o = [];
-            for (k in arr) { o.push(k); }
-            return o;
-        },
-
-        // Redirect to a specified url
-        redirect: function(url) {
-            window.location.href = url;
-            return url;
-        },
-
-        // Stop event shorthand
-        stop: function(e, preventDefault, stopPropagation) {
-            if (preventDefault)  { e.preventDefault(); }
-            if (stopPropagation) { e.stopPropagation(); }
-            return preventDefault && false || true;
-        },
-
-        // Returns the basename of a path
-        basename: function(path) {
-            var t = path.split('/');
-            return t[t.length] === '' && s || t.slice(0, t.length).join('/');
-        },
-
-        // Returns the filename of a path
-        filename: function(path) {
-            return path.split('/').pop();
-        }, 
-
-        // Returns a formated file size
-        filesizeformat: function(bytes, suffixes){
-            var b = parseInt(bytes, 10);
-            var s = suffixes || ['byte', 'bytes', 'KB', 'MB', 'GB'];
-            if (isNaN(b) || b === 0) { return '0 ' + s[0]; }
-            if (b == 1)              { return '1 ' + s[0]; }
-            if (b < 1024)            { return  b.toFixed(2) + ' ' + s[1]; }
-            if (b < 1048576)         { return (b / 1024).toFixed(2) + ' ' + s[2]; }
-            if (b < 1073741824)      { return (b / 1048576).toFixed(2) + ' '+ s[3]; }
-            else                     { return (b / 1073741824).toFixed(2) + ' '+ s[4]; }
-        },
-
-        fileExtension: function(s) {
-            var tokens = s.split('.');
-            return tokens[tokens.length-1] || false;
-        },
-        
-        // Returns true if an object is a String
-        isString: function(o) {
-            return typeof(o) == 'string' && true || false;
-        },
-        
-        // Returns true if an object is a RegExp
-		isRegExp: function(o) {
-			return o && o.constructor.toString().indexOf('RegExp()') != -1 || false;
-		},
-
-        isObject: function(o) {
-            return (typeof(o) == 'object');
-        },
-        
-        // Convert input to currency (two decimal fixed number)
-		toCurrency: function(i) {
-			i = parseFloat(i, 10).toFixed(2);
-			return (i=='NaN') ? '0.00' : i;
-		},
-
-        /*-------------------------------------------------------------------- 
-         * javascript method: "pxToEm"
-         * by:
-           Scott Jehl (scott at filamentgroup.com) 
-           Maggie Wachs (maggie at filamentgroup.com)
-           http://www.filamentgroup.com
-         *
-         * Copyright (c) 2008 Filament Group
-         * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
-         *
-         * Description: pxToEm converts a pixel value to ems depending on inherited font size.  
-         * Article: http://www.filamentgroup.com/lab/retaining_scalable_interfaces_with_pixel_to_em_conversion/
-         * Demo: http://www.filamentgroup.com/examples/pxToEm/	 	
-         *							
-         * Options:  	 								
-                scope: string or jQuery selector for font-size scoping
-                reverse: Boolean, true reverses the conversion to em-px
-         * Dependencies: jQuery library						  
-         * Usage Example: myPixelValue.pxToEm(); or myPixelValue.pxToEm({'scope':'#navigation', reverse: true});
-         *
-         * Version: 2.1, 18.12.2008
-         * Changelog:
-         *		08.02.2007 initial Version 1.0
-         *		08.01.2008 - fixed font-size calculation for IE
-         *		18.12.2008 - removed native object prototyping to stay in jQuery's spirit, jsLinted (Maxime Haineault <haineault at gmail.com>)
-        --------------------------------------------------------------------*/
-
-        pxToEm: function(i, settings){
-            //set defaults
-            settings = jQuery.extend({
-                scope: 'body',
-                reverse: false
-            }, settings);
-            
-            var pxVal = (i === '') ? 0 : parseFloat(i);
-            var scopeVal;
-            var getWindowWidth = function(){
-                var de = document.documentElement;
-                return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
-            };	
-            
-            /* When a percentage-based font-size is set on the body, IE returns that percent of the window width as the font-size. 
-                For example, if the body font-size is 62.5% and the window width is 1000px, IE will return 625px as the font-size. 	
-                When this happens, we calculate the correct body font-size (%) and multiply it by 16 (the standard browser font size) 
-                to get an accurate em value. */
-                        
-            if (settings.scope == 'body' && $.browser.msie && (parseFloat($('body').css('font-size')) / getWindowWidth()).toFixed(1) > 0.0) {
-                var calcFontSize = function(){		
-                    return (parseFloat($('body').css('font-size'))/getWindowWidth()).toFixed(3) * 16;
-                };
-                scopeVal = calcFontSize();
-            }
-            else { scopeVal = parseFloat(jQuery(settings.scope).css("font-size")); }
-                    
-            var result = (settings.reverse === true) ? (pxVal * scopeVal).toFixed(2) + 'px' : (pxVal / scopeVal).toFixed(2) + 'em';
-            return result;
-        }
-	});
-
-	$.extend($.fn, { 
-        type: function() {
-            try { return $(this).get(0).nodeName.toLowerCase(); }
-            catch(e) { return false; }
-        },
-        // Select a text range in a textarea
-        selectRange: function(start, end){
-            // use only the first one since only one input can be focused
-            if ($(this).get(0).createTextRange) {
-                var range = $(this).get(0).createTextRange();
-                range.collapse(true);
-                range.moveEnd('character',   end);
-                range.moveStart('character', start);
-                range.select();
-            }
-            else if ($(this).get(0).setSelectionRange) {
-                $(this).bind('focus', function(e){
-                    e.preventDefault();
-                }).get(0).setSelectionRange(start, end);
-            }
-            return $(this);
-        },
-
-        /*-------------------------------------------------------------------- 
-         * JQuery Plugin: "EqualHeights"
-         * by:	Scott Jehl, Todd Parker, Maggie Costello Wachs (http://www.filamentgroup.com)
-         *
-         * Copyright (c) 2008 Filament Group
-         * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php)
-         *
-         * Description: Compares the heights or widths of the top-level children of a provided element 
-                and sets their min-height to the tallest height (or width to widest width). Sets in em units 
-                by default if pxToEm() method is available.
-         * Dependencies: jQuery library, pxToEm method	(article: 
-                http://www.filamentgroup.com/lab/retaining_scalable_interfaces_with_pixel_to_em_conversion/)							  
-         * Usage Example: $(element).equalHeights();
-                Optional: to set min-height in px, pass a true argument: $(element).equalHeights(true);
-         * Version: 2.1, 18.12.2008
-         *
-         * Note: Changed pxToEm call to call $.pxToEm instead, jsLinted (Maxime Haineault <haineault at gmail.com>)
-        --------------------------------------------------------------------*/
-
-        equalHeights: function(px){
-            $(this).each(function(){
-                var currentTallest = 0;
-                $(this).children().each(function(i){
-                    if ($(this).height() > currentTallest) { currentTallest = $(this).height(); }
-                });
-                if (!px || !$.pxToEm) { currentTallest = $.pxToEm(currentTallest); } //use ems unless px is specified
-                // for ie6, set height since min-height isn't supported
-                if ($.browser.msie && $.browser.version == 6.0) { $(this).children().css({'height': currentTallest}); }
-                $(this).children().css({'min-height': currentTallest}); 
-            });
-            return this;
-        },
-
-        // Copyright (c) 2009 James Padolsey
-        // http://james.padolsey.com/javascript/jquery-delay-plugin/
-        delay: function(time, callback){
-            jQuery.fx.step.delay = function(){};
-            return this.animate({delay:1}, time, callback);
-        }        
-	});
-})(jQuery);
-
-/*
-  jQuery strings - 0.4
-  http://code.google.com/p/jquery-utils/
-  
-  (c) Maxime Haineault <haineault at gmail.com>
-  http://haineault.com   
-
-  MIT License (http://www.opensource.org/licenses/mit-license.php)
-
-  Implementation of Python3K advanced string formatting
-  http://www.python.org/dev/peps/pep-3101/
-
-  Documentation: http://code.google.com/p/jquery-utils/wiki/StringFormat
-  
-*/
-(function($){
-    var strings = {
-        strConversion: {
-            // tries to translate any objects type into string gracefully
-            __repr: function(i){
-                switch(this.__getType(i)) {
-                    case 'array':case 'date':case 'number':
-                        return i.toString();
-                    case 'object': // Thanks to Richard Paul Lewis for the fix
-                        var o = []; 
-                        var l = i.length;
-                        for(var x=0;x<l;x++) {
-                          o.push(x+': '+this.__repr(i[x]));
-                        } 
-                        return o.join(', ');                        
-                    case 'string': 
-                        return i;
-                    default: 
-                        return i;
-                }
-            },
-            // like typeof but less vague
-            __getType: function(i) {
-                if (!i || !i.constructor) { return typeof(i); }
-                var match = i.constructor.toString().match(/Array|Number|String|Object|Date/);
-                return match && match[0].toLowerCase() || typeof(i);
-            },
-            // Jonas Raoni Soares Silva (http://jsfromhell.com/string/pad)
-            __pad: function(str, l, s, t){
-                var p = s || ' ';
-                var o = str;
-                if (l - str.length > 0) {
-                    o = new Array(Math.ceil(l / p.length)).join(p).substr(0, t = !t ? l : t == 1 ? 0 : Math.ceil(l / 2)) + str + p.substr(0, l - t);
-                }
-                return o;
-            },
-            __getInput: function(arg, args) {
-                 var key = arg.getKey();
-                switch(this.__getType(args)){
-                    case 'object': // Thanks to Jonathan Works for the patch
-                        var keys = key.split('.');
-                        var obj = args;
-                        for(var subkey = 0; subkey < keys.length; subkey++){
-                            obj = obj[keys[subkey]];
-                        }
-                        if (typeof(obj) != 'undefined') {
-                            if (strings.strConversion.__getType(obj) == 'array') {
-                                return arg.getFormat().match(/\.\*/) && obj[1] || obj;
-                            }
-                            return obj;
-                        }
-                        else {
-                            // TODO: try by numerical index                    
-                        }
-                    break;
-                    case 'array': 
-                        key = parseInt(key, 10);
-                        if (arg.getFormat().match(/\.\*/) && typeof args[key+1] != 'undefined') { return args[key+1]; }
-                        else if (typeof args[key] != 'undefined') { return args[key]; }
-                        else { return key; }
-                    break;
-                }
-                return '{'+key+'}';
-            },
-            __formatToken: function(token, args) {
-                var arg   = new Argument(token, args);
-                return strings.strConversion[arg.getFormat().slice(-1)](this.__getInput(arg, args), arg);
-            },
-
-            // Signed integer decimal.
-            d: function(input, arg){
-                var o = parseInt(input, 10); // enforce base 10
-                var p = arg.getPaddingLength();
-                if (p) { return this.__pad(o.toString(), p, arg.getPaddingString(), 0); }
-                else   { return o; }
-            },
-            // Signed integer decimal.
-            i: function(input, args){ 
-                return this.d(input, args);
-            },
-            // Unsigned octal
-            o: function(input, arg){ 
-                var o = input.toString(8);
-                if (arg.isAlternate()) { o = this.__pad(o, o.length+1, '0', 0); }
-                return this.__pad(o, arg.getPaddingLength(), arg.getPaddingString(), 0);
-            },
-            // Unsigned decimal
-            u: function(input, args) {
-                return Math.abs(this.d(input, args));
-            },
-            // Unsigned hexadecimal (lowercase)
-            x: function(input, arg){
-                var o = parseInt(input, 10).toString(16);
-                o = this.__pad(o, arg.getPaddingLength(), arg.getPaddingString(),0);
-                return arg.isAlternate() ? '0x'+o : o;
-            },
-            // Unsigned hexadecimal (uppercase)
-            X: function(input, arg){
-                return this.x(input, arg).toUpperCase();
-            },
-            // Floating point exponential format (lowercase)
-            e: function(input, arg){
-                return parseFloat(input, 10).toExponential(arg.getPrecision());
-            },
-            // Floating point exponential format (uppercase)
-            E: function(input, arg){
-                return this.e(input, arg).toUpperCase();
-            },
-            // Floating point decimal format
-            f: function(input, arg){
-                return this.__pad(parseFloat(input, 10).toFixed(arg.getPrecision()), arg.getPaddingLength(), arg.getPaddingString(),0);
-            },
-            // Floating point decimal format (alias)
-            F: function(input, args){
-                return this.f(input, args);
-            },
-            // Floating point format. Uses exponential format if exponent is greater than -4 or less than precision, decimal format otherwise
-            g: function(input, arg){
-                var o = parseFloat(input, 10);
-                return (o.toString().length > 6) ? Math.round(o.toExponential(arg.getPrecision())): o;
-            },
-            // Floating point format. Uses exponential format if exponent is greater than -4 or less than precision, decimal format otherwise
-            G: function(input, args){
-                return this.g(input, args);
-            },
-            // Single character (accepts integer or single character string). 	
-            c: function(input, args) {
-                var match = input.match(/\w|\d/);
-                return match && match[0] || '';
-            },
-            // String (converts any JavaScript object to anotated format)
-            r: function(input, args) {
-                return this.__repr(input);
-            },
-            // String (converts any JavaScript object using object.toString())
-            s: function(input, args) {
-                return input.toString && input.toString() || ''+input;
-            }
-        },
-
-        format: function(str, args) {
-            var end    = 0;
-            var start  = 0;
-            var match  = false;
-            var buffer = [];
-            var token  = '';
-            var tmp    = (str||'').split('');
-            for(start=0; start < tmp.length; start++) {
-                if (tmp[start] == '{' && tmp[start+1] !='{') {
-                    end   = str.indexOf('}', start);
-                    token = tmp.slice(start+1, end).join('');
-                    if (tmp[start-1] != '{' && tmp[end+1] != '}') {
-                        var tokenArgs = (typeof arguments[1] != 'object')? arguments2Array(arguments, 2): args || [];
-                        buffer.push(strings.strConversion.__formatToken(token, tokenArgs));
-                    }
-                    else {
-                        buffer.push(token);
-                    }
-                }
-                else if (start > end || buffer.length < 1) { buffer.push(tmp[start]); }
-            }
-            return (buffer.length > 1)? buffer.join(''): buffer[0];
-        },
-
-        calc: function(str, args) {
-            return eval(format(str, args));
-        },
-
-        repeat: function(s, n) { 
-            return new Array(n+1).join(s); 
-        },
-
-        UTF8encode: function(s) { 
-            return unescape(encodeURIComponent(s)); 
-        },
-
-        UTF8decode: function(s) { 
-            return decodeURIComponent(escape(s)); 
-        },
-
-        tpl: function() {
-            var out = '';
-            var render = true;
-            // Set
-            // $.tpl('ui.test', ['<span>', helloWorld ,'</span>']);
-            if (arguments.length == 2 && $.isArray(arguments[1])) {
-                this[arguments[0]] = arguments[1].join('');
-                return $(this[arguments[0]]);
-            }
-            // $.tpl('ui.test', '<span>hello world</span>');
-            if (arguments.length == 2 && $.isString(arguments[1])) {
-                this[arguments[0]] = arguments[1];
-                return $(this[arguments[0]]);
-            }
-            // Call
-            // $.tpl('ui.test');
-            if (arguments.length == 1) {
-                return $(this[arguments[0]]);
-            }
-            // $.tpl('ui.test', false);
-            if (arguments.length == 2 && arguments[1] == false) {
-                return this[arguments[0]];
-            }
-            // $.tpl('ui.test', {value:blah});
-            if (arguments.length == 2 && $.isObject(arguments[1])) {
-                return $($.format(this[arguments[0]], arguments[1]));
-            }
-            // $.tpl('ui.test', {value:blah}, false);
-            if (arguments.length == 3 && $.isObject(arguments[1])) {
-                return (arguments[2] == true) 
-                    ? $.format(this[arguments[0]], arguments[1])
-                    : $($.format(this[arguments[0]], arguments[1]));
-            }
-        }
-    };
-
-    var Argument = function(arg, args) {
-        this.__arg  = arg;
-        this.__args = args;
-        this.__max_precision = parseFloat('1.'+ (new Array(32)).join('1'), 10).toString().length-3;
-        this.__def_precision = 6;
-        this.getString = function(){
-            return this.__arg;
-        };
-        this.getKey = function(){
-            return this.__arg.split(':')[0];
-        };
-        this.getFormat = function(){
-            var match = this.getString().split(':');
-            return (match && match[1])? match[1]: 's';
-        };
-        this.getPrecision = function(){
-            var match = this.getFormat().match(/\.(\d+|\*)/g);
-            if (!match) { return this.__def_precision; }
-            else {
-                match = match[0].slice(1);
-                if (match != '*') { return parseInt(match, 10); }
-                else if(strings.strConversion.__getType(this.__args) == 'array') {
-                    return this.__args[1] && this.__args[0] || this.__def_precision;
-                }
-                else if(strings.strConversion.__getType(this.__args) == 'object') {
-                    return this.__args[this.getKey()] && this.__args[this.getKey()][0] || this.__def_precision;
-                }
-                else { return this.__def_precision; }
-            }
-        };
-        this.getPaddingLength = function(){
-            var match = false;
-            if (this.isAlternate()) {
-                match = this.getString().match(/0?#0?(\d+)/);
-                if (match && match[1]) { return parseInt(match[1], 10); }
-            }
-            match = this.getString().match(/(0|\.)(\d+|\*)/g);
-            return match && parseInt(match[0].slice(1), 10) || 0;
-        };
-        this.getPaddingString = function(){
-            var o = '';
-            if (this.isAlternate()) { o = ' '; }
-            // 0 take precedence on alternate format
-            if (this.getFormat().match(/#0|0#|^0|\.\d+/)) { o = '0'; }
-            return o;
-        };
-        this.getFlags = function(){
-            var match = this.getString().matc(/^(0|\#|\-|\+|\s)+/);
-            return match && match[0].split('') || [];
-        };
-        this.isAlternate = function() {
-            return !!this.getFormat().match(/^0?#/);
-        };
-    };
-
-    var arguments2Array = function(args, shift) {
-        var o = [];
-        for (l=args.length, x=(shift || 0)-1; x<l;x++) { o.push(args[x]); }
-        return o;
-    };
-    $.extend(strings);
-})(jQuery);
-
-/*
-  jQuery ui.timepickr - @VERSION
-  http://code.google.com/p/jquery-utils/
-
-  (c) Maxime Haineault <haineault at gmail.com> 
-  http://haineault.com
-
-  MIT License (http://www.opensource.org/licenses/mit-license.php
-
-  Note: if you want the original experimental plugin checkout the rev 224 
-
-  Dependencies
-  ------------
-  - jquery.utils.js
-  - jquery.strings.js
-  - jquery.ui.js
-  
-*/
-
-(function($) {
-
-$.tpl('timepickr.menu',   '<div class="ui-helper-reset ui-timepickr ui-widget" />');
-$.tpl('timepickr.row',    '<ol class="ui-timepickr-row ui-helper-clearfix" />');
-$.tpl('timepickr.button', '<li class="{className:s}"><span class="ui-state-default">{label:s}</span></li>');
-
-$.widget('ui.timepickr', {
-    plugins: {},
-    _create: function() {
-        this._dom = {
-            menu: $.tpl('timepickr.menu'),
-            row:  $.tpl('timepickr.menu')
-        };
-        this._trigger('initialize');
-        this._trigger('initialized');
-    },
-
-    _trigger: function(type, e, ui) {
-        var ui = ui || this;
-        $.ui.plugin.call(this, type, [e, ui]);
-        return $.Widget.prototype._trigger.call(this, type, e, ui);
-    },
-
-    _createButton: function(i, format, className) {
-        var o  = format && $.format(format, i) || i;
-        var cn = className && 'ui-timepickr-button '+ className || 'ui-timepickr-button';
-        return $.tpl('timepickr.button', {className: cn, label: o}).data('id', i)
-                .bind('mouseover', function(){
-                    $(this).siblings().find('span')
-                        .removeClass('ui-state-hover').end().end()
-                        .find('span').addClass('ui-state-hover');
-                });
-
-    },
-
-    _addRow: function(range, format, className, insertAfter) {
-        var ui  = this;
-        var btn = false;
-        var row = $.tpl('timepickr.row').bind('mouseover', function(){
-            $(this).next().show();
-        });
-        $.each(range, function(idx, val){
-            ui._createButton(val, format || false).appendTo(row);
-        });
-        if (className) {
-            $(row).addClass(className);
-        }
-        if (this.options.corners) {
-             row.find('span').addClass('ui-corner-'+ this.options.corners);
-        }
-        if (insertAfter) {
-            row.insertAfter(insertAfter);
-        }
-        else {
-            ui._dom.menu.append(row);
-        }
-        return row;
-    },
-
-    _setVal: function(val) {
-        val = val || this._getVal();
-        if (!(val.h==='' && val.m==='')) {        
-            this.element.data('timepickr.initialValue', val);
-            this.element.val(this._formatVal(val));        
-        }
-        if(this._dom.menu.is(':hidden')) {
-            this.element.trigger('change');
-        }
-    },
-
-    _getVal: function() {
-        var ols = this._dom.menu.find('ol');
-        function get(unit) {
-            var u = ols.filter('.'+unit).find('.ui-state-hover:first').text();
-            return u || ols.filter('.'+unit+'li:first span').text();
-        }
-        return {
-            h: get('hours'),
-            m: get('minutes'),
-            s: get('seconds'),
-            a: get('prefix'),
-            z: get('suffix'),
-            f: this.options['format'+ this.c],
-            c: this.c
-        };
-    },
-
-    _formatVal: function(ival) {
-        var val = ival || this._getVal();
-        val.c = this.options.convention;
-        val.f = val.c === 12 && this.options.format12 || this.options.format24;
-        return (new Time(val)).getTime();
-    },
-
-    blur: function() {
-        return this.element.blur();      
-    },
-
-    focus: function() {
-        return this.element.focus();      
-    },
-    show: function() {
-        this._trigger('show');
-        this.element.trigger(this.options.trigger);
-    },
-    hide: function() {
-        this._trigger('hide');
-        this._dom.menu.hide();
-    }
-
-});
-
-// These properties are shared accross every instances of timepickr 
-$.extend($.ui.timepickr.prototype, {
-    version:     '@VERSION',
-    //eventPrefix: '',
-    //getter:      '',
-    options:    {
-        convention:  24, // 24, 12
-        trigger:     'mouseover',
-        format12:    '{h:02.d}:{m:02.d} {z:s}',
-        format24:    '{h:02.d}:{m:02.d}',
-        hours:       true,
-        prefix:      ['am', 'pm'],
-        suffix:      ['am', 'pm'],
-        prefixVal:   false,
-        suffixVal:   true,
-        rangeHour12: $.range(1, 13),
-        rangeHour24: [$.range(0, 12), $.range(12, 24)],
-        rangeMin:    $.range(0, 60, 15),
-        rangeSec:    $.range(0, 60, 15),
-        corners:     'all',
-        // plugins
-        core:        true,
-        minutes:     true,
-        seconds:     false,
-        val:         false,
-        updateLive:  true,
-        resetOnBlur: true,
-        keyboardnav: true,
-        handle:      false,
-        handleEvent: 'click'
-    }
-});
-
-$.ui.plugin.add('timepickr', 'core', {
-    initialized: function(e, ui) {
-        var menu = ui._dom.menu;
-        var pos  = ui.element.position();
-
-        menu.insertAfter(ui.element).css('left', pos.left);
-
-        if (!$.boxModel) { // IE alignement fix
-            menu.css('margin-top', ui.element.height() + 8);
-        }
-        
-        ui.element
-            .bind(ui.options.trigger, function() {
-                ui._dom.menu.show();
-                ui._dom.menu.find('ol:first').show();
-                ui._trigger('focus');
-                if (ui.options.trigger != 'focus') {
-                    ui.element.focus();
-                }
-                ui._trigger('focus');
-            })
-            .bind('blur', function() {
-                ui.hide();
-                ui._trigger('blur');
-            });
-
-        menu.find('li').bind('mouseover.timepickr', function() {
-            ui._trigger('refresh');
-        });
-    },
-    refresh: function(e, ui) {
-        // Realign each menu layers
-        ui._dom.menu.find('ol').each(function(){
-            var p = $(this).prev('ol');
-            try { // .. to not fuckup IE
-                $(this).css('left', p.position().left + p.find('.ui-state-hover').position().left);
-            } catch(e) {};
-        });
-    }
-});
-
-$.ui.plugin.add('timepickr', 'hours', {
-    initialize: function(e, ui) {
-        if (ui.options.convention === 24) {
-            // prefix is required in 24h mode
-            ui._dom.prefix = ui._addRow(ui.options.prefix, false, 'prefix'); 
-
-            // split-range
-            if ($.isArray(ui.options.rangeHour24[0])) {
-                var range = [];
-                $.merge(range, ui.options.rangeHour24[0]);
-                $.merge(range, ui.options.rangeHour24[1]);
-                ui._dom.hours = ui._addRow(range, '{0:0.2d}', 'hours');
-                ui._dom.hours.find('li').slice(ui.options.rangeHour24[0].length, -1).hide();
-                var lis   = ui._dom.hours.find('li'); 
-
-                var show = [
-                    function() {
-                        lis.slice(ui.options.rangeHour24[0].length).hide().end()
-                           .slice(0, ui.options.rangeHour24[0].length).show()
-                           .filter(':visible:first').trigger('mouseover');
-
-                    },
-                    function() {
-                        lis.slice(0, ui.options.rangeHour24[0].length).hide().end()
-                           .slice(ui.options.rangeHour24[0].length).show()
-                           .filter(':visible:first').trigger('mouseover');
-                    }
-                ];
-
-                ui._dom.prefix.find('li').bind('mouseover.timepickr', function(){
-                    var index = ui._dom.menu.find('.prefix li').index(this);
-                    show[index].call();
-                });
-            }
-            else {
-                ui._dom.hours = ui._addRow(ui.options.rangeHour24, '{0:0.2d}', 'hours');
-                ui._dom.hours.find('li').slice(12, -1).hide();
-            }
-        }
-        else {
-            ui._dom.hours  = ui._addRow(ui.options.rangeHour12, '{0:0.2d}', 'hours');
-            // suffix is required in 12h mode
-            ui._dom.suffix = ui._addRow(ui.options.suffix, false, 'suffix'); 
-        }
-    }});
-
-$.ui.plugin.add('timepickr', 'minutes', {
-    initialize: function(e, ui) {
-        var p = ui._dom.hours && ui._dom.hours || false;
-        ui._dom.minutes = ui._addRow(ui.options.rangeMin, '{0:0.2d}', 'minutes', p);
-    }
-});
-
-$.ui.plugin.add('timepickr', 'seconds', {
-    initialize: function(e, ui) {
-        var p = ui._dom.minutes && ui._dom.minutes || false;
-        ui._dom.seconds = ui._addRow(ui.options.rangeSec, '{0:0.2d}', 'seconds', p);
-    }
-});
-
-$.ui.plugin.add('timepickr', 'val', {
-    initialized: function(e, ui) {
-        ui._setVal(ui.options.val);
-    }
-});
-
-$.ui.plugin.add('timepickr', 'updateLive', {
-    refresh: function(e, ui) {
-        ui._setVal();
-    }
-});
-
-$.ui.plugin.add('timepickr', 'resetOnBlur', {
-    initialized: function(e, ui) {
-        ui.element.data('timepickr.initialValue', ui._getVal());
-        ui._dom.menu.find('li > span').bind('mousedown.timepickr', function(){
-            ui.element.data('timepickr.initialValue', ui._getVal()); 
-        });
-    },
-    blur: function(e, ui) {
-        ui._setVal(ui.element.data('timepickr.initialValue'));
-    }
-});
-
-$.ui.plugin.add('timepickr', 'handle', {
-    initialized: function(e, ui) {
-        $(ui.options.handle).bind(ui.options.handleEvent + '.timepickr', function(){
-            ui.show();
-        });
-    }
-});
-
-$.ui.plugin.add('timepickr', 'keyboardnav', {
-    initialized: function(e, ui) {
-        ui.element
-            .bind('keydown', function(e) {
-                if ($.keyIs('enter', e)) {
-                    ui._setVal();
-                    ui.blur();
-                }
-                else if ($.keyIs('escape', e)) {
-                    ui.blur();
-                }
-            });
-    }
-});
-
-var Time = function() { // arguments: h, m, s, c, z, f || time string
-    if (!(this instanceof arguments.callee)) {
-        throw Error("Constructor called as a function");
-    }
-    // arguments as literal object
-    if (arguments.length == 1 && $.isObject(arguments[0])) {
-        this.h = arguments[0].h || 0;
-        this.m = arguments[0].m || 0;
-        this.s = arguments[0].s || 0;
-        this.c = arguments[0].c && ($.inArray(arguments[0].c, [12, 24]) >= 0) && arguments[0].c || 24;
-        this.f = arguments[0].f || ((this.c == 12) && '{h:02.d}:{m:02.d} {z:02.d}' || '{h:02.d}:{m:02.d}');
-        this.z = arguments[0].z || 'am';
-    }
-    // arguments as string
-    else if (arguments.length < 4 && $.isString(arguments[1])) {
-        this.c = arguments[2] && ($.inArray(arguments[0], [12, 24]) >= 0) && arguments[0] || 24;
-        this.f = arguments[3] || ((this.c == 12) && '{h:02.d}:{m:02.d} {z:02.d}' || '{h:02.d}:{m:02.d}');
-        this.z = arguments[4] || 'am';
-        
-        this.h = arguments[1] || 0; // parse
-        this.m = arguments[1] || 0; // parse
-        this.s = arguments[1] || 0; // parse
-    }
-    // no arguments (now)
-    else if (arguments.length === 0) {
-        // now
-    }
-    // standards arguments
-    else {
-        this.h = arguments[0] || 0;
-        this.m = arguments[1] || 0;
-        this.s = arguments[2] || 0;
-        this.c = arguments[3] && ($.inArray(arguments[3], [12, 24]) >= 0) && arguments[3] || 24;
-        this.f = this.f || ((this.c == 12) && '{h:02.d}:{m:02.d} {z:02.d}' || '{h:02.d}:{m:02.d}');
-        this.z = 'am';
-    }
-    return this;
-};
-
-Time.prototype.get        = function(p, f, u)    { return u && this.h || $.format(f, this.h); };
-Time.prototype.getHours   = function(unformated) { return this.get('h', '{0:02.d}', unformated); };
-Time.prototype.getMinutes = function(unformated) { return this.get('m', '{0:02.d}', unformated); };
-Time.prototype.getSeconds = function(unformated) { return this.get('s', '{0:02.d}', unformated); };
-Time.prototype.setFormat  = function(format)     { return this.f = format; };
-Time.prototype.getObject  = function()           { return { h: this.h, m: this.m, s: this.s, c: this.c, f: this.f, z: this.z }; };
-Time.prototype.getTime    = function()           { return $.format(this.f, {h: this.h, m: this.m, suffix: this.z}); }; // Thanks to Jackson for the fix.
-Time.prototype.parse      = function(str) { 
-    // 12h formats
-    if (this.c === 12) {
-        // Supported formats: (can't find any *official* standards for 12h..)
-        //  - [hh]:[mm]:[ss] [zz] | [hh]:[mm] [zz] | [hh] [zz] 
-        //  - [hh]:[mm]:[ss] [z.z.] | [hh]:[mm] [z.z.] | [hh] [z.z.]
-        this.tokens = str.split(/\s|:/);    
-        this.h = this.tokens[0] || 0;
-        this.m = this.tokens[1] || 0;
-        this.s = this.tokens[2] || 0;
-        this.z = this.tokens[3] || '';
-        return this.getObject();
-    }
-    // 24h formats
-    else { 
-        // Supported formats:
-        //  - ISO 8601: [hh][mm][ss] | [hh][mm] | [hh]  
-        //  - ISO 8601 extended: [hh]:[mm]:[ss] | [hh]:[mm] | [hh]
-        this.tokens = /:/.test(str) && str.split(/:/) || str.match(/[0-9]{2}/g);
-        this.h = this.tokens[0] || 0;
-        this.m = this.tokens[1] || 0;
-        this.s = this.tokens[2] || 0;
-        this.z = this.tokens[3] || '';
-        return this.getObject();
-    }
-};
-
-})(jQuery);
diff --git a/rt/share/html/NoAuth/js/util.js b/rt/share/html/NoAuth/js/util.js
index 5bfce41..fe5c0a3 100644
--- a/rt/share/html/NoAuth/js/util.js
+++ b/rt/share/html/NoAuth/js/util.js
@@ -222,35 +222,47 @@ function doOnLoad( js ) {
 }
 
 jQuery(function() {
-    jQuery(".ui-datepicker:not(.withtime)").datepicker( {
-        dateFormat: 'yy-mm-dd',
-        constrainInput: false
-    } );
-
-    jQuery(".ui-datepicker.withtime").datepicker( {
+    var opts = {
         dateFormat: 'yy-mm-dd',
         constrainInput: false,
-        onSelect: function( dateText, inst ) {
-            // trigger timepicker to get time
-            var button = document.createElement('input');
-            button.setAttribute('type',  'button');
-            jQuery(button).width('5em');
-            jQuery(button).insertAfter(this);
-            jQuery(button).timepickr({val: '00:00'});
-            var date_input = this;
-
-            jQuery(button).blur( function() {
-                var time = jQuery(button).val();
-                if ( ! time.match(/\d\d:\d\d/) ) {
-                    time = '00:00';
-                }
-                jQuery(date_input).val(  dateText + ' ' + time + ':00' );
-                jQuery(button).remove();
-            } );
-
-            jQuery(button).focus();
-        }
-    } );
+        showButtonPanel: true,
+        changeMonth: true,
+        changeYear: true,
+        showOtherMonths: true,
+        selectOtherMonths: true
+    };
+    jQuery(".ui-datepicker:not(.withtime)").datepicker(opts);
+    jQuery(".ui-datepicker.withtime").datetimepicker( jQuery.extend({}, opts, {
+        stepHour: 1,
+        // We fake this by snapping below for the minute slider
+        //stepMinute: 5,
+        hourGrid: 6,
+        minuteGrid: 15,
+        showSecond: false,
+        timeFormat: 'hh:mm:ss'
+    }) ).each(function(index, el) {
+        var tp = jQuery.datepicker._get( jQuery.datepicker._getInst(el), 'timepicker');
+        if (!tp) return;
+
+        // Hook after _injectTimePicker so we can modify the minute_slider
+        // right after it's first created
+        tp._base_injectTimePicker = tp._injectTimePicker;
+        tp._injectTimePicker = function() {
+            this._base_injectTimePicker.apply(this, arguments);
+
+            // Now that we have minute_slider, modify it to be stepped for mouse movements
+            var slider = jQuery.data(this.minute_slider[0], "slider");
+            slider._base_normValueFromMouse = slider._normValueFromMouse;
+            slider._normValueFromMouse = function() {
+                var value           = this._base_normValueFromMouse.apply(this, arguments);
+                var old_step        = this.options.step;
+                this.options.step   = 5;
+                var aligned         = this._trimAlignValue( value );
+                this.options.step   = old_step;
+                return aligned;
+            };
+        };
+    });
 });
 
 function textToHTML(value) {
diff --git a/rt/share/html/Prefs/Other.html b/rt/share/html/Prefs/Other.html
index 9f7e04a..b5d3edd 100644
--- a/rt/share/html/Prefs/Other.html
+++ b/rt/share/html/Prefs/Other.html
@@ -53,6 +53,7 @@
 % foreach my $section( RT->Config->Sections ) {
 <&|/Widgets/TitleBox, title => loc( $section ) &>
 % foreach my $option( RT->Config->Options( Section => $section ) ) {
+% next if $option eq 'EmailFrequency' && !RT->Config->Get('RecordOutgoingEmail');
 % my $meta = RT->Config->Meta( $option );
 <& $meta->{'Widget'},
     Default      => 1,
diff --git a/rt/share/html/REST/1.0/Forms/ticket/default b/rt/share/html/REST/1.0/Forms/ticket/default
index 9a2212b..016a50c 100755
--- a/rt/share/html/REST/1.0/Forms/ticket/default
+++ b/rt/share/html/REST/1.0/Forms/ticket/default
@@ -167,6 +167,17 @@ else {
             elsif (lc $k eq 'text') {
                 $text = delete $data{$k};
             }
+            elsif ( lc $k ne 'id' ) {
+                $e = 1;
+                push @$o, $k;
+                push(@comments, "# $k: Unknown field");
+            }
+        }
+
+        if ( $e ) {
+            unshift @comments, "# Could not create ticket.";
+            $k = \%data;
+            goto DONE;
         }
 
         # people fields allow multiple values
@@ -292,8 +303,10 @@ else {
         elsif (exists $simple{$key}) {
             $key = $simple{$key};
             $set = "Set$key";
+            my $current = $ticket->$key;
+            $current = '' unless defined $current;
 
-            next if (($val eq ($ticket->$key||''))|| ($ticket->$key =~ /^\d+$/ && $val =~ /^\d+$/ && $val == $ticket->$key));
+            next if ($val eq $current) or ($current =~ /^\d+$/ && $val =~ /^\d+$/ && $val == $current);
             ($n, $s) = $ticket->$set("$val");
         }
         elsif (exists $dates{$key}) {
@@ -331,13 +344,6 @@ else {
                 }
             }
             foreach $p (keys %new) {
-                # XXX: This is a stupid test.
-                unless ($p =~ /^[\w.+-]+\@([\w.-]+\.)*\w+.?$/) {
-                    $s = 0;
-                    $n = "$p is not a valid email address.";
-                    push @msgs, [ $s, $n ];
-                    next;
-                }
                 unless ($ticket->IsWatcher(Type => $type, Email => $p)) {
                     ($s, $n) = $ticket->AddWatcher(Type => $type,
                                                    Email => $p);
diff --git a/rt/share/html/Search/Chart.html b/rt/share/html/Search/Chart.html
index 070ce7c..571c3d3 100644
--- a/rt/share/html/Search/Chart.html
+++ b/rt/share/html/Search/Chart.html
@@ -98,14 +98,14 @@ my %query;
 
     for(@session_fields) {
         $query{$_} = $current->{$_} unless defined $query{$_};
-        $query{$_} = $m->request_args->{$_} unless defined $query{$_};
+        $query{$_} = $DECODED_ARGS->{$_} unless defined $query{$_};
     }
 
-    if ($m->request_args->{'SavedSearchLoadSubmit'}) {
-        $query{'SavedChartSearchId'} = $m->request_args->{'SavedSearchLoad'};
+    if ($DECODED_ARGS->{'SavedSearchLoadSubmit'}) {
+        $query{'SavedChartSearchId'} = $DECODED_ARGS->{'SavedSearchLoad'};
     }
 
-    if ($m->request_args->{'SavedSearchSave'}) {
+    if ($DECODED_ARGS->{'SavedSearchSave'}) {
         $query{'SavedChartSearchId'} = $saved_search->{'SearchId'};
     }
 
diff --git a/rt/share/html/Search/Elements/SelectPersonType b/rt/share/html/Search/Elements/SelectPersonType
index d07e49c..bc29111 100644
--- a/rt/share/html/Search/Elements/SelectPersonType
+++ b/rt/share/html/Search/Elements/SelectPersonType
@@ -62,7 +62,7 @@
 
 <%INIT>
 my @types;
-if ($Scope =~ 'queue') {
+if ($Scope =~ /queue/) {
    @types = qw(Cc AdminCc);
 }
 elsif ($Suffix eq 'Group') {
diff --git a/rt/share/html/Search/Results.html b/rt/share/html/Search/Results.html
index 171b38d..4fee865 100755
--- a/rt/share/html/Search/Results.html
+++ b/rt/share/html/Search/Results.html
@@ -151,6 +151,7 @@ if ($ARGS{'TicketsRefreshInterval'}) {
 my $refresh = $session{'tickets_refresh_interval'}
     || RT->Config->Get('SearchResultsRefreshInterval', $session{'CurrentUser'} );
 
+# Check $m->request_args, not $DECODED_ARGS, to avoid creating a new CSRF token on each refresh
 if (RT->Config->Get('RestrictReferrer') and $refresh and not $m->request_args->{CSRF_Token}) {
     my $token = RT::Interface::Web::StoreRequestToken( $session{'CurrentSearchHash'} );
     $m->notes->{RefreshURL} = RT->Config->Get('WebURL')
diff --git a/rt/share/html/Ticket/Attachment/dhandler b/rt/share/html/Ticket/Attachment/dhandler
index 75efeff..eb291e4 100755
--- a/rt/share/html/Ticket/Attachment/dhandler
+++ b/rt/share/html/Ticket/Attachment/dhandler
@@ -48,7 +48,7 @@
 <%perl>
     my ($ticket, $trans,$attach, $filename);
     my $arg = $m->dhandler_arg;                # get rest of path
-    if ($arg =~ '^(\d+)/(\d+)') {
+    if ($arg =~ m{^(\d+)/(\d+)}) {
         $trans = $1;
         $attach = $2;
     }
@@ -79,7 +79,12 @@
      my $enc = $AttachmentObj->OriginalEncoding || 'utf-8';
      my $iana = Encode::find_encoding( $enc );
      $iana = $iana? $iana->mime_name : $enc;
-	 $content_type .= ";charset=$iana";
+
+     require MIME::Types;
+     my $mimetype = MIME::Types->new->type($content_type);
+     unless ( $mimetype && $mimetype->isBinary ) {
+	    $content_type .= ";charset=$iana";
+     }
 
      $r->subprocess_env('no-gzip' => 1); # disable mod_deflate
      $r->content_type( $content_type );
diff --git a/rt/share/html/Ticket/Elements/ShowMembers b/rt/share/html/Ticket/Elements/ShowMembers
index c17c6e7..1ffbda2 100755
--- a/rt/share/html/Ticket/Elements/ShowMembers
+++ b/rt/share/html/Ticket/Elements/ShowMembers
@@ -48,8 +48,9 @@
 <ul>
 % while (my $link = $members->Next) {
 <li><& /Elements/ShowLink, URI => $link->BaseURI &><br />
+% next if $link->BaseObj and $checked->{$link->BaseObj->id};
 % if ($depth < 8) {
-<& /Ticket/Elements/ShowMembers, Ticket => $link->BaseObj, depth => ($depth+1) &> 
+<& /Ticket/Elements/ShowMembers, Ticket => $link->BaseObj, depth => ($depth+1), checked => $checked &> 
 % }
 </li>
 % }
@@ -61,9 +62,13 @@ return unless $Ticket;
 my $members = $Ticket->Members;
 return unless $members->Count;
 
+return if $checked->{$Ticket->id};
+
+$checked->{$Ticket->id} = 1;
 </%INIT>
 
 <%ARGS>
 $Ticket => undef
 $depth => 1
+$checked => {}
 </%ARGS>
diff --git a/rt/share/html/Ticket/Elements/ShowTransactionAttachments b/rt/share/html/Ticket/Elements/ShowTransactionAttachments
index 877201f..95a2341 100644
--- a/rt/share/html/Ticket/Elements/ShowTransactionAttachments
+++ b/rt/share/html/Ticket/Elements/ShowTransactionAttachments
@@ -144,6 +144,8 @@ my $render_attachment = sub {
     my $message = shift;
     my $name = defined $message->Filename && length $message->Filename ?  $message->Filename : '';
 
+    my $content_type = lc $message->ContentType;
+
     # if it has a content-disposition: attachment, don't show inline
     my $disposition = $message->GetHeader('Content-Disposition');
 
@@ -154,7 +156,7 @@ my $render_attachment = sub {
     }
 
     # If it's text
-    if ( $message->ContentType =~ m{^(text|message)}i ) {
+    if ( $content_type =~ m{^(text|message)/} ) {
         my $max_size = RT->Config->Get( 'MaxInlineBody', $session{'CurrentUser'} );
         if ( $disposition ne 'inline' ) {
             $m->out('<p>'. loc( 'Message body is not shown because sender requested not to inline it.' ) .'</p>');
@@ -175,16 +177,16 @@ my $render_attachment = sub {
             !$ParentObj
 
             # or its parent isn't a multipart alternative
-            || ( $ParentObj->ContentType !~ m{^multipart/alternative$}i )
+            || ( $ParentObj->ContentType !~ m{^multipart/(?:alternative|related)$}i )
 
             # or it's of our prefered alterative type
             || (
                 (
                     RT->Config->Get('PreferRichText')
-                    && ( $message->ContentType =~ m{^text/(?:html|enriched)$} )
+                    && ( $content_type =~ m{^text/(?:html|enriched)$} )
                 )
                 || ( !RT->Config->Get('PreferRichText')
-                    && ( $message->ContentType !~ m{^text/(?:html|enriched)$} )
+                    && ( $content_type !~ m{^text/(?:html|enriched)$} )
                 )
             )
         ) {
@@ -198,7 +200,6 @@ my $render_attachment = sub {
                 $content = $message->Content;
             }
 
-            my $content_type = lc $message->ContentType;
             $RT::Logger->debug(
                 "Rendering attachment #". $message->id
                 ." of '$content_type' type"
@@ -231,9 +232,8 @@ my $render_attachment = sub {
                 $m->out( $content );
             }
 
-            # if it's a text/plain show the body
-            elsif ( $message->ContentType =~ m{^(text|message)}i ) {
-
+            # It's a text type we don't have special handling for
+            else {
                 unless ( length $name ) {
                     eval { require Text::Quoted;  $content = Text::Quoted::extract($content); };
                     if ($@) { $RT::Logger->warning( "Text::Quoted failed: $@" ) }
@@ -250,7 +250,7 @@ my $render_attachment = sub {
     }
 
     # if it's an image, show it as an image
-    elsif ( RT->Config->Get('ShowTransactionImages') and  $message->ContentType =~ /^image\//i ) {
+    elsif ( RT->Config->Get('ShowTransactionImages') and  $content_type =~ m{^image/} ) {
         if ( $disposition ne 'inline' ) {
             $m->out('<p>'. loc( 'Message body is not shown because sender requested not to inline it.' ) .'</p>');
             return;
diff --git a/rt/share/html/m/_elements/raw_style b/rt/share/html/m/_elements/raw_style
index 8c19977..a349829 100644
--- a/rt/share/html/m/_elements/raw_style
+++ b/rt/share/html/m/_elements/raw_style
@@ -33,6 +33,7 @@ div.buttons {
     background-color: #ccc;
     -moz-border-radius: 0.25em;
     -webkit-border-radius: 0.25em;
+    border-radius: 0.25em;
     -webkit-box-shadow: #333 0px 0px 5px;
     -moz-box-shadow: #333 0px 0px 5px;
     box-shadow: #333 0px 0px 5px;
@@ -85,6 +86,7 @@ ul.menu li#active a
 div.titlebox, #bpscredits, .ticket_menu{
     -moz-border-radius: 1em;
     -webkit-border-radius: 1em;
+    border-radius: 1em;
     margin: 0.5em;
     background-color: #fff;
     padding-top: 1em;
@@ -336,6 +338,7 @@ input[type=submit], input[type=button], button, #paging a {
     padding-right: 0.6em;
     -moz-border-radius: 0.5em;
     -webkit-border-radius: 0.5em;
+    border-radius: 0.5em;
     background-color: #006699;
     color: #fff;
 }
@@ -353,6 +356,7 @@ form {
     border-bottom: 1px solid black;
     -moz-border-radius-bottomleft: 1em;
     -webkit-border-bottom-left-radius: 1em;
+    border-bottom-left-radius: 1em;
     padding: 0.5em;
     background-color: #fff;
 }
diff --git a/rt/share/html/m/_elements/wrapper b/rt/share/html/m/_elements/wrapper
index 794385d..1891079 100644
--- a/rt/share/html/m/_elements/wrapper
+++ b/rt/share/html/m/_elements/wrapper
@@ -3,7 +3,7 @@ $title => ''
 $show_home_button => 1
 </%args>
 <%init>
-if ($m->request_args->{'NotMobile'}) {
+if ($DECODED_ARGS->{'NotMobile'}) {
     $session{'NotMobile'} = 1;
     RT::Interface::Web::Redirect(RT->Config->Get('WebURL'));
     $m->abort();

commit 806d426d106efea2b2b13314108c4ac046511e1c
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Tue Sep 18 02:56:30 2012 -0700

    export host selection per service, RT#17914

diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
index 97394af..c757d36 100644
--- a/FS/FS/part_export.pm
+++ b/FS/FS/part_export.pm
@@ -330,6 +330,31 @@ sub label {
   ($self->exportname || $self->exporttype ). ' ('. $self->machine. ')';
 }
 
+=item label_html
+
+Returns a label for this export, "exportname: exporttype to machine".
+
+=cut
+
+sub label_html {
+  my $self = shift;
+
+  my $label = $self->exportname
+                ? '<B>'. $self->exportname. '</B>: ' #<BR>'.
+                : '';
+
+  $label .= $self->exporttype;
+
+  $label .= ' to '. ( $self->machine eq '_SVC_MACHINE'
+                        ? 'per-service hostname'
+                        : $self->machine
+                    )
+    if $self->machine;
+
+  $label;
+
+}
+
 #=item part_svc
 #
 #Returns the service definition (see L<FS::part_svc>) for this export.
diff --git a/httemplate/browse/part_export.cgi b/httemplate/browse/part_export.cgi
index beed708..b7ecc00 100755
--- a/httemplate/browse/part_export.cgi
+++ b/httemplate/browse/part_export.cgi
@@ -36,17 +36,7 @@ function part_export_areyousure(href) {
       <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>"><% $part_export->exportnum %></A></TD>
 
       <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
-%       if( $part_export->exportname ) {
-          <B><% $part_export->exportname %>:</B><BR>
-%       }
-        <% $part_export->exporttype %>
-        <% $part_export->machine
-             ? 'to '. ( $part_export->machine eq '_SVC_MACHINE'
-                          ? 'per-service hostname'
-                          : $part_export->machine
-                      )
-             : ''
-        %>
+        <% $part_export->label_html %>
         (<A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>">edit</A> | <A HREF="javascript:part_export_areyousure('<% $p %>misc/delete-part_export.cgi?<% $part_export->exportnum %>')">delete</A>)
       </TD>
 
diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi
index 26d090a..a8f4a7c 100755
--- a/httemplate/browse/part_svc.cgi
+++ b/httemplate/browse/part_svc.cgi
@@ -141,16 +141,7 @@ function part_export_areyousure(href) {
 %
 
         <TR>
-          <TD><A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>">
-<% $part_export->exportnum %>: 
-% if ($part_export->exportname) {
-<B><% $part_export->exportname %></B> (
-% }
-<% $part_export->exporttype %> to <% $part_export->machine %>
-% if ($part_export->exportname) {
-)
-% }
-</A></TD>
+          <TD><A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>"><% $part_export->label_html %></A></TD>
 	</TR>
 %  } 
 
diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi
index 4bd0837..007c246 100755
--- a/httemplate/edit/part_svc.cgi
+++ b/httemplate/edit/part_svc.cgi
@@ -144,12 +144,7 @@
 %              && qsearchs( 'export_svc', {
 %                                   exportnum => $part_export->exportnum,
 %                                   svcpart   => $clone || $part_svc->svcpart });
-%        $html .= '>'.$part_export->exportnum. ': ';
-%        $html .= $part_export->exportname . '<DIV ALIGN="right"><FONT SIZE=-1>'
-%          if ( $part_export->exportname );
-%        $html .= $part_export->exporttype. ' to '. $part_export->machine;
-%        $html .= '</FONT></DIV>' if ( $part_export->exportname );
-%        $html .= '</TD>';
+%        $html .= '>'. $part_export->label_html. '</TD>';
 %        $count++;
 %        $html .= '</TR><TR>' unless $count % $columns;
 %      }

commit 1ad547a47f16b4230762e752fbe48d460ed997e1
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Tue Sep 18 02:18:04 2012 -0700

    export host selection per service, RT#17914

diff --git a/FS/FS.pm b/FS/FS.pm
index 5ab3f71..2d963b5 100644
--- a/FS/FS.pm
+++ b/FS/FS.pm
@@ -284,6 +284,10 @@ L<FS::agent_payment_gateway> - Agent payment gateway class
 
 L<FS::cust_svc> - Service class
 
+L<FS::part_export_machine> - Export hostname choice class
+
+L<FS::svc_export_machine> - Customer export hostname class
+
 L<FS::cust_pkg> - Customer package class
 
 L<FS::cust_pkg_option> - Customer package option class
diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm
index 0ac269f..ca68c35 100644
--- a/FS/FS/Record.pm
+++ b/FS/FS/Record.pm
@@ -2421,10 +2421,9 @@ sub ut_coordn {
 
 }
 
-
 =item ut_domain COLUMN
 
-Check/untaint host and domain names.
+Check/untaint host and domain names.  May not be null.
 
 =cut
 
@@ -2432,11 +2431,27 @@ sub ut_domain {
   my( $self, $field ) = @_;
   #$self->getfield($field) =~/^(\w+\.)*\w+$/
   $self->getfield($field) =~/^(([\w\-]+\.)*\w+)$/
-    or return "Illegal (domain) $field: ". $self->getfield($field);
+    or return "Illegal (hostname) $field: ". $self->getfield($field);
   $self->setfield($field,$1);
   '';
 }
 
+=item ut_domainn COLUMN
+
+Check/untaint host and domain names.  May be null.
+
+=cut
+
+sub ut_domainn {
+  my( $self, $field ) = @_;
+  if ( $self->getfield($field) =~ /^()$/ ) {
+    $self->setfield($field,'');
+    '';
+  } else {
+    $self->ut_domain($field);
+  }
+}
+
 =item ut_name COLUMN
 
 Check/untaint proper names; allows alphanumerics, spaces and the following
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 4ef2a63..6e3956a 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -1890,6 +1890,29 @@ sub tables_hashref {
       'index'       => [ [ 'svcnum' ], [ 'optionname' ] ],
     },
 
+    'svc_export_machine' => {
+      'columns' => [
+        'svcexportmachinenum', 'serial', '', '', '', '',
+        'svcnum',                 'int', '', '', '', '', 
+        'machinenum',             'int', '', '', '', '',
+      ],
+      'primary_key' => 'svcexportmachinenum',
+      'unique'      => [],
+      'index'       => [],
+    },
+
+    'part_export_machine' => {
+      'columns' => [
+        'machinenum', 'serial', '', '', '', '',
+        'exportnum',     'int', '', '', '', '',
+        'machine',    'varchar', 'NULL', $char_d, '', '', 
+        'disabled',      'char', 'NULL',       1, '', '',
+      ],
+      'primary_key' => 'machinenum',
+      'unique'      => [ [ 'exportnum', 'machine' ] ],
+      'index'       => [ [ 'exportnum' ] ],
+    },
+
    'part_pkg' => {
       'columns' => [
         'pkgpart',       'serial',    '',   '', '', '', 
@@ -2623,11 +2646,11 @@ sub tables_hashref {
 
     'part_export' => {
       'columns' => [
-        'exportnum', 'serial', '', '', '', '', 
+        'exportnum',   'serial',     '',      '', '', '', 
         'exportname', 'varchar', 'NULL', $char_d, '', '',
-        'machine', 'varchar', '', $char_d, '', '', 
-        'exporttype', 'varchar', '', $char_d, '', '', 
-        'nodomain',     'char', 'NULL', 1, '', '', 
+        'machine',    'varchar', 'NULL', $char_d, '', '', 
+        'exporttype', 'varchar',     '', $char_d, '', '', 
+        'nodomain',      'char', 'NULL',       1, '', '', 
       ],
       'primary_key' => 'exportnum',
       'unique'      => [],
diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
index 45773e0..97394af 100644
--- a/FS/FS/part_export.pm
+++ b/FS/FS/part_export.pm
@@ -4,10 +4,11 @@ use strict;
 use vars qw( @ISA @EXPORT_OK $DEBUG %exports );
 use Exporter;
 use Tie::IxHash;
-use base qw( FS::option_Common FS::m2m_Common ); # m2m for 'export_nas'
+use base qw( FS::option_Common FS::m2m_Common );
 use FS::Record qw( qsearch qsearchs dbh );
 use FS::part_svc;
 use FS::part_export_option;
+use FS::part_export_machine;
 use FS::export_svc;
 
 #for export modules, though they should probably just use it themselves
@@ -108,6 +109,50 @@ otherwise returns false.
 If a hash reference of options is supplied, part_export_option records are
 created (see L<FS::part_export_option>).
 
+=cut
+
+sub insert {
+  my $self = shift;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $error = $self->SUPER::insert(@_);
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  #kinda false laziness with process_m2name
+  my @machines = map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ }
+                   grep /\S/,
+                     split /[\n\r]{1,2}/,
+                       $self->part_export_machine_textarea;
+
+  foreach my $machine ( @machines ) {
+
+    my $part_export_machine = new FS::part_export_machine {
+      'exportnum' => $self->exportnum,
+      'machine'   => $machine,
+    };
+    $error = $part_export_machine->insert;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  '';
+}
+
 =item delete
 
 Delete this record from the database.
@@ -117,13 +162,13 @@ Delete this record from the database.
 #foreign keys would make this much less tedious... grr dumb mysql
 sub delete {
   my $self = shift;
+
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
   local $SIG{QUIT} = 'IGNORE';
   local $SIG{TERM} = 'IGNORE';
   local $SIG{TSTP} = 'IGNORE';
   local $SIG{PIPE} = 'IGNORE';
-
   my $oldAutoCommit = $FS::UID::AutoCommit;
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
@@ -147,10 +192,103 @@ sub delete {
     }
   }
 
-  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  foreach my $part_export_machine ( $self->part_export_machine ) {
+    my $error = $part_export_machine->delete;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
 
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
   '';
+}
+
+=item replace [ OLD_RECORD ] [ HASHREF | OPTION => VALUE ... ]
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+If a list or hash reference of options is supplied, option records are created
+or modified.
+
+=cut
 
+sub replace {
+  my $self = shift;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $error = $self->SUPER::replace(@_);
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  if ( $self->part_export_machine_textarea ) {
+
+    my %part_export_machine = map { $_->machine => $_ }
+                                $self->part_export_machine;
+
+    my @machines = map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ }
+                     grep /\S/,
+                       split /[\n\r]{1,2}/,
+                         $self->part_export_machine_textarea;
+
+    foreach my $machine ( @machines ) {
+
+      if ( $part_export_machine{$machine} ) {
+
+        if ( $part_export_machine{$machine}->disabled eq 'Y' ) {
+          $part_export_machine{$machine}->disabled('');
+          $error = $part_export_machine{$machine}->replace;
+          if ( $error ) {
+            $dbh->rollback if $oldAutoCommit;
+            return $error;
+          }
+        }
+
+        delete $part_export_machine{$machine}; #so we don't disable it below
+
+      } else {
+
+        my $part_export_machine = new FS::part_export_machine {
+                                        'exportnum' => $self->exportnum,
+                                        'machine'   => $machine
+                                      };
+        $error = $part_export_machine->insert;
+        if ( $error ) {
+          $dbh->rollback if $oldAutoCommit;
+          return $error;
+        }
+  
+      }
+
+    }
+
+
+    foreach my $part_export_machine ( values %part_export_machine ) {
+      $part_export_machine->disabled('Y');
+      $error = $part_export_machine->replace;
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return $error;
+      }
+    }
+
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  '';
 }
 
 =item check
@@ -166,7 +304,7 @@ sub check {
   my $error = 
     $self->ut_numbern('exportnum')
     || $self->ut_textn('exportname')
-    || $self->ut_domain('machine')
+    || $self->ut_domainn('machine')
     || $self->ut_alpha('exporttype')
   ;
   return $error if $error;
@@ -233,6 +371,20 @@ sub cust_svc {
       $self->export_svc;
 }
 
+=item part_export_machine
+
+Returns all machines as FS::part_export_machine objects (see
+L<FS::part_export_machine>).
+
+=cut
+
+sub part_export_machine {
+  my $self = shift;
+  map { $_ } #behavior of sort undefined in scalar context
+    sort { $a->machine cmp $b->machine }
+      qsearch('part_export_machine', { 'exportnum' => $self->exportnum } );
+}
+
 =item export_svc
 
 Returns a list of associated FS::export_svc records.
diff --git a/FS/FS/part_export/acct_google.pm b/FS/FS/part_export/acct_google.pm
index afc45db..d153728 100644
--- a/FS/FS/part_export/acct_google.pm
+++ b/FS/FS/part_export/acct_google.pm
@@ -16,10 +16,12 @@ tie my %options, 'Tie::IxHash',
 # admin logins.
 
 %info = (
-  'svc'       => 'svc_acct',
-  'desc'      => 'Google hosted mail',
-  'options'   => \%options,
-  'nodomain'  => 'Y',
+  'svc'        => 'svc_acct',
+  'desc'       => 'Google hosted mail',
+  'options'    => \%options,
+  'nodomain'   => 'Y',
+  'no_machine' => 1,
+  'default_svc_class' => 'Email',
   'notes'    => <<'END'
 Export accounts to the Google Provisioning API.  Requires 
 REST::Google::Apps::Provisioning from CPAN.
diff --git a/FS/FS/part_export/acct_http.pm b/FS/FS/part_export/acct_http.pm
index b4c64ac..23df7b3 100644
--- a/FS/FS/part_export/acct_http.pm
+++ b/FS/FS/part_export/acct_http.pm
@@ -51,6 +51,7 @@ tie %options, 'Tie::IxHash',
   'svc'     => 'svc_acct',
   'desc'    => 'Send an HTTP or HTTPS GET or POST request, for accounts.',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END'
 Send an HTTP or HTTPS GET or POST to the specified URL on account addition,
 modification and deletion.  For HTTPS support,
diff --git a/FS/FS/part_export/acct_plesk.pm b/FS/FS/part_export/acct_plesk.pm
index d8d70a3..50b6fae 100644
--- a/FS/FS/part_export/acct_plesk.pm
+++ b/FS/FS/part_export/acct_plesk.pm
@@ -15,9 +15,11 @@ tie my %options, 'Tie::IxHash',
 ;
 
 %info = (
-  'svc'    => 'svc_acct',
-  'desc'   => 'Real-time export to Plesk managed mail service',
-  'options'=> \%options,
+  'svc'        => 'svc_acct',
+  'desc'       => 'Real-time export to Plesk managed mail service',
+  'options'    => \%options,
+  'no_machine' => 1,
+  'default_svc_class' => 'Email',
   'notes'  => <<'END'
 Real-time export to
 <a href="http://www.swsoft.com/">Plesk</a> managed server.
diff --git a/FS/FS/part_export/acct_sql.pm b/FS/FS/part_export/acct_sql.pm
index ffe39ca..8163f20 100644
--- a/FS/FS/part_export/acct_sql.pm
+++ b/FS/FS/part_export/acct_sql.pm
@@ -60,11 +60,13 @@ my $postfix_native_mailbox_map =
                  keys %postfix_native_mailbox_map      );
 
 %info = (
-  'svc'      => 'svc_acct',
-  'desc'     => 'Real-time export of accounts to SQL databases '.
-                '(vpopmail, Postfix+Courier IMAP, others?)',
-  'options'  => \%options,
-  'nodomain' => '',
+  'svc'        => 'svc_acct',
+  'desc'       => 'Real-time export of accounts to SQL databases '.
+                  '(vpopmail, Postfix+Courier IMAP, others?)',
+  'options'    => \%options,
+  'nodomain'   => '',
+  'no_machine' => 1,
+  'default_svc_class' => 'Email',
   'notes'    => <<END
 Export accounts (svc_acct records) to SQL databases.  Currently has default
 configurations for vpopmail and Postfix+Courier IMAP but intended to be
diff --git a/FS/FS/part_export/acct_sql_status.pm b/FS/FS/part_export/acct_sql_status.pm
index e6aeb20..248105f 100644
--- a/FS/FS/part_export/acct_sql_status.pm
+++ b/FS/FS/part_export/acct_sql_status.pm
@@ -14,6 +14,7 @@ delete $options{$_} for qw( table schema static primary_key );
   'desc'     => 'Mailbox status information from SQL',
   'options'  => \%options,
   'nodomain' => '',
+  'no_machine' => 1,
   'notes'    => <<END
 Read mailbox status information (vacation and spam settings) from an SQL
 database, tables "vacation" and "users" respectively.
diff --git a/FS/FS/part_export/acct_xmlrpc.pm b/FS/FS/part_export/acct_xmlrpc.pm
index 96ad1fa..3070f28 100644
--- a/FS/FS/part_export/acct_xmlrpc.pm
+++ b/FS/FS/part_export/acct_xmlrpc.pm
@@ -34,6 +34,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_acct',
   'desc'    => 'Configurable provisioning of accounts via the XML-RPC protocol',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END',
 Configurable, real-time export of accounts via the XML-RPC protocol.<BR>
 <BR>
diff --git a/FS/FS/part_export/amazon_ec2.pm b/FS/FS/part_export/amazon_ec2.pm
index 0e65ca0..06e2c23 100644
--- a/FS/FS/part_export/amazon_ec2.pm
+++ b/FS/FS/part_export/amazon_ec2.pm
@@ -20,6 +20,7 @@ tie my %options, 'Tie::IxHash',
   'desc'     =>
     'Export to Amazon EC2',
   'options'  => \%options,
+  'no_machine' => 1,
   'notes'    => <<'END'
 Create instances in the Amazon EC2 (Elastic compute cloud).  Install
 Net::Amazon::EC2 perl module.  Advisable to set svc_external-skip_manual config
diff --git a/FS/FS/part_export/artera_turbo.pm b/FS/FS/part_export/artera_turbo.pm
index c006db9..e22bbf2 100644
--- a/FS/FS/part_export/artera_turbo.pm
+++ b/FS/FS/part_export/artera_turbo.pm
@@ -37,6 +37,7 @@ tie my %options, 'Tie::IxHash',
     'Real-time export to Artera Turbo Reseller API',
   'options'  => \%options,
   #'nodomain' => 'Y',
+  'no_machine' => 1,
   'notes'    => <<'END'
 Real-time export to <a href="http://www.arteraturbo.com/">Artera Turbo</a>
 Reseller API.  Requires installation of
diff --git a/FS/FS/part_export/broadband_http.pm b/FS/FS/part_export/broadband_http.pm
index 9edfee5..c1ed7fc 100644
--- a/FS/FS/part_export/broadband_http.pm
+++ b/FS/FS/part_export/broadband_http.pm
@@ -45,6 +45,7 @@ tie %options, 'Tie::IxHash',
   'svc'     => 'svc_broadband',
   'desc'    => 'Send an HTTP or HTTPS GET or POST request, for accounts.',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END'
 <p>Send an HTTP or HTTPS GET or POST to the specified URL on account addition,
 modification and deletion.  For HTTPS support,
diff --git a/FS/FS/part_export/broadband_nas.pm b/FS/FS/part_export/broadband_nas.pm
index a160c99..5a8ffac 100644
--- a/FS/FS/part_export/broadband_nas.pm
+++ b/FS/FS/part_export/broadband_nas.pm
@@ -43,6 +43,7 @@ FS::UID->install_callback(
   'svc'     => 'svc_broadband',
   'desc'    => 'Create a NAS entry in Freeside',
   'options' => \%options,
+  'no_machine' => 1,
   'weight'  => 10,
   'notes'   => <<'END'
 <p>Create an entry in the NAS (RADIUS client) table, inheriting the IP 
diff --git a/FS/FS/part_export/broadband_shellcommands.pm b/FS/FS/part_export/broadband_shellcommands.pm
index c7f0fbb..cf9c36c 100644
--- a/FS/FS/part_export/broadband_shellcommands.pm
+++ b/FS/FS/part_export/broadband_shellcommands.pm
@@ -107,3 +107,4 @@ sub ssh_cmd { #subroutine, not method
   '';
 }
 
+1;
diff --git a/FS/FS/part_export/broadband_snmp.pm b/FS/FS/part_export/broadband_snmp.pm
index cb1740e..44b4dba 100644
--- a/FS/FS/part_export/broadband_snmp.pm
+++ b/FS/FS/part_export/broadband_snmp.pm
@@ -52,6 +52,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_broadband',
   'desc'    => 'Send SNMP requests to the service IP address',
   'options' => \%options,
+  'no_machine' => 1,
   'weight'  => 10,
   'notes'   => <<'END'
 Send one or more SNMP SET requests to the IP address registered to the service.
diff --git a/FS/FS/part_export/broadband_sql.pm b/FS/FS/part_export/broadband_sql.pm
index 697d3cd..4f526c8 100644
--- a/FS/FS/part_export/broadband_sql.pm
+++ b/FS/FS/part_export/broadband_sql.pm
@@ -24,6 +24,7 @@ tie my %options, 'Tie::IxHash',
   'desc'     => 'Real-time export of broadband services to SQL databases ',
   'options'  => \%options,
   'nodomain' => '',
+  'no_machine' => 1,
   'notes'    => <<END
 END
 );
diff --git a/FS/FS/part_export/broadband_sqlradius.pm b/FS/FS/part_export/broadband_sqlradius.pm
index 5806362..b5d1a80 100644
--- a/FS/FS/part_export/broadband_sqlradius.pm
+++ b/FS/FS/part_export/broadband_sqlradius.pm
@@ -55,6 +55,7 @@ tie %options, 'Tie::IxHash',
   'svc'      => 'svc_broadband',
   'desc'     => 'Real-time export to SQL-backed RADIUS (such as FreeRadius) for broadband services',
   'options'  => \%options,
+  'no_machine' => 1,
   'nas'      => 'Y',
   'notes'    => <<END,
 Real-time export of <b>radcheck</b>, <b>radreply</b>, and <b>usergroup</b> 
diff --git a/FS/FS/part_export/communigate_pro.pm b/FS/FS/part_export/communigate_pro.pm
index a3ec5e0..8b66225 100644
--- a/FS/FS/part_export/communigate_pro.pm
+++ b/FS/FS/part_export/communigate_pro.pm
@@ -36,6 +36,7 @@ tie %options, 'Tie::IxHash',
   'svc'     => [qw( svc_acct svc_domain svc_forward svc_mailinglist )],
   'desc'    => 'Real-time export of accounts, domains, mail forwards and mailing lists to a CommuniGate Pro mail server',
   'options' => \%options,
+  'default_svc_class' => 'Email',
   'notes'   => <<'END'
 Real time export of accounts, domains, mail forwards and mailing lists to a
 <a href="http://www.stalker.com/CommuniGatePro/">CommuniGate Pro</a>
diff --git a/FS/FS/part_export/communigate_pro_singledomain.pm b/FS/FS/part_export/communigate_pro_singledomain.pm
index e25043f..cecea28 100644
--- a/FS/FS/part_export/communigate_pro_singledomain.pm
+++ b/FS/FS/part_export/communigate_pro_singledomain.pm
@@ -16,6 +16,7 @@ tie my %options, 'Tie::IxHash', %FS::part_export::communigate_pro::options,
     'Real-time export to a CommuniGate Pro mail server, one domain only',
   'options'  => \%options,
   'nodomain' => 'Y',
+  'default_svc_class' => 'Email',
   'notes'    => <<'END'
 Real time export to a
 <a href="http://www.stalker.com/CommuniGatePro/">CommuniGate Pro</a>
diff --git a/FS/FS/part_export/cp.pm b/FS/FS/part_export/cp.pm
index 96fa437..2ae97e1 100644
--- a/FS/FS/part_export/cp.pm
+++ b/FS/FS/part_export/cp.pm
@@ -18,6 +18,7 @@ tie my %options, 'Tie::IxHash',
   'svc'    => 'svc_acct',
   'desc'   => 'Real-time export to Critical Path Account Provisioning Protocol',
   'options'=> \%options,
+  'default_svc_class' => 'Email',
   'notes'  => <<'END'
 Real-time export to
 <a href="http://www.cp.net/">Critial Path Account Provisioning Protocol</a>.
diff --git a/FS/FS/part_export/cpanel.pm b/FS/FS/part_export/cpanel.pm
index 0ad00df..6c61e3d 100644
--- a/FS/FS/part_export/cpanel.pm
+++ b/FS/FS/part_export/cpanel.pm
@@ -190,3 +190,5 @@ sub cpanel_connect {
 
   $whm;
 }
+
+1;
diff --git a/FS/FS/part_export/cust_http.pm b/FS/FS/part_export/cust_http.pm
index e8b677b..e834f93 100644
--- a/FS/FS/part_export/cust_http.pm
+++ b/FS/FS/part_export/cust_http.pm
@@ -55,6 +55,7 @@ tie %options, 'Tie::IxHash',
   'svc'     => 'cust_main',
   'desc'    => 'Send an HTTP or HTTPS GET or POST request, for customers.',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END'
 Send an HTTP or HTTPS GET or POST to the specified URL on customer addition,
 modification and deletion.  For HTTPS support,
diff --git a/FS/FS/part_export/cyrus.pm b/FS/FS/part_export/cyrus.pm
index 84c9e5a..246d5b3 100644
--- a/FS/FS/part_export/cyrus.pm
+++ b/FS/FS/part_export/cyrus.pm
@@ -17,6 +17,8 @@ tie my %options, 'Tie::IxHash',
   'desc'     => 'Real-time export to Cyrus IMAP server',
   'options'  => \%options,
   'nodomain' => 'Y',
+  'no_machine' => 1, #de facto... but "server" option should move to it
+  'default_svc_class' => 'Email',
   'notes'    => <<'END'
 Integration with
 <a href="http://asg.web.cmu.edu/cyrus/imapd/">Cyrus IMAP Server</a>.
diff --git a/FS/FS/part_export/dashcs_e911.pm b/FS/FS/part_export/dashcs_e911.pm
index 320d0a6..2717233 100644
--- a/FS/FS/part_export/dashcs_e911.pm
+++ b/FS/FS/part_export/dashcs_e911.pm
@@ -20,6 +20,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_phone',
   'desc'    => 'Provision e911 services via Dash Carrier Services',
   'notes'   => 'Provision e911 services via Dash Carrier Services',
+  'no_machine' => 1,
   'options' => \%options,
 );
 
diff --git a/FS/FS/part_export/domain_sql.pm b/FS/FS/part_export/domain_sql.pm
index 0749fec..ff0d949 100644
--- a/FS/FS/part_export/domain_sql.pm
+++ b/FS/FS/part_export/domain_sql.pm
@@ -26,6 +26,7 @@ my $postfix_transport_static =
   'desc'    => 'Real time export of domains to SQL databases '.
                '(postfix, others?)',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<END
 Export domains (svc_domain records) to SQL databases.  Currently this is a
 simple export with a default for Postfix, but it can be extended for other
diff --git a/FS/FS/part_export/everyone_net.pm b/FS/FS/part_export/everyone_net.pm
index 0fd32fa..7386973 100644
--- a/FS/FS/part_export/everyone_net.pm
+++ b/FS/FS/part_export/everyone_net.pm
@@ -18,6 +18,8 @@ tie my %options, 'Tie::IxHash',
   'svc'    => 'svc_acct',
   'desc'   => 'Real-time export to Everyone.net outsourced mail service',
   'options'=> \%options,
+  'no_machine' => 1,
+  'default_svc_class' => 'Email',
   'notes'  => <<'END'
 Real-time export to
 <a href="http://www.everyone.net/">Everyone.net</a> via the XRC Remote API.
diff --git a/FS/FS/part_export/ez_prepaid.pm b/FS/FS/part_export/ez_prepaid.pm
index d171eb1..9f454df 100644
--- a/FS/FS/part_export/ez_prepaid.pm
+++ b/FS/FS/part_export/ez_prepaid.pm
@@ -34,6 +34,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_external',
   'desc'    => 'Purchase EZ-Prepaid PIN',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END'
 <P>Export to the EZ-Prepaid PIN purchase service.  If the purchase is allowed,
 the PIN will be stored as svc_external.id.</P>
diff --git a/FS/FS/part_export/forward_sql.pm b/FS/FS/part_export/forward_sql.pm
index 563efcc..eb41378 100644
--- a/FS/FS/part_export/forward_sql.pm
+++ b/FS/FS/part_export/forward_sql.pm
@@ -10,6 +10,7 @@ use FS::Record;
   'desc'     => 'Real-time export of forwards to SQL databases ',
                 #.' (vpopmail, Postfix+Courier IMAP, others?)',
   'options'  => __PACKAGE__->sql_options,
+  'no_machine' => 1,
   'notes'    => <<END
 Export mail forwards (svc_forward records) to SQL databases.
 
diff --git a/FS/FS/part_export/globalpops_voip.pm b/FS/FS/part_export/globalpops_voip.pm
index 6df21f4..9fe45ba 100644
--- a/FS/FS/part_export/globalpops_voip.pm
+++ b/FS/FS/part_export/globalpops_voip.pm
@@ -19,6 +19,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_phone',
   'desc'    => 'Provision phone numbers to VoIP Innovations (formerly GlobalPOPs VoIP)',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END'
 Requires installation of
 <a href="http://search.cpan.org/dist/Net-GlobalPOPs-MediaServicesAPI">Net::GlobalPOPs::MediaServicesAPI</a>
diff --git a/FS/FS/part_export/http.pm b/FS/FS/part_export/http.pm
index 3749224..c35c89f 100644
--- a/FS/FS/part_export/http.pm
+++ b/FS/FS/part_export/http.pm
@@ -43,6 +43,7 @@ tie %options, 'Tie::IxHash',
   'svc'     => 'svc_domain',
   'desc'    => 'Send an HTTP or HTTPS GET or POST request',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END'
 Send an HTTP or HTTPS GET or POST to the specified URL.  For HTTPS support,
 <a href="http://search.cpan.org/dist/Crypt-SSLeay">Crypt::SSLeay</a>
diff --git a/FS/FS/part_export/http_status.pm b/FS/FS/part_export/http_status.pm
index 5342106..6fbd3fb 100644
--- a/FS/FS/part_export/http_status.pm
+++ b/FS/FS/part_export/http_status.pm
@@ -17,6 +17,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_dsl',
   'desc'    => 'Retrieve status information via HTTP or HTTPS',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END'
 Fields from the service can be substituted in the URL as $field.
 END
diff --git a/FS/FS/part_export/ikano.pm b/FS/FS/part_export/ikano.pm
index eedc9d0..23917bf 100644
--- a/FS/FS/part_export/ikano.pm
+++ b/FS/FS/part_export/ikano.pm
@@ -31,6 +31,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_dsl',
   'desc'    => 'Provision DSL to Ikano',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END'
 Requires installation of
 <a href="http://search.cpan.org/dist/Net-Ikano">Net::Ikano</a> from CPAN.
diff --git a/FS/FS/part_export/indosoft.pm b/FS/FS/part_export/indosoft.pm
index b573401..02ae5ef 100644
--- a/FS/FS/part_export/indosoft.pm
+++ b/FS/FS/part_export/indosoft.pm
@@ -17,6 +17,7 @@ tie my %options, 'Tie::IxHash',
   'desc'     =>
     'Export conferences to the Indosoft Conference Bridge',
   'options'  => \%options,
+  'no_machine' => 1,
   'notes'    => <<'END'
 Export conferences to the Indosoft conference bridge.
 Net::Indosoft::Voicebridge is required.
diff --git a/FS/FS/part_export/infostreet.pm b/FS/FS/part_export/infostreet.pm
index ef16c7c..51f5760 100644
--- a/FS/FS/part_export/infostreet.pm
+++ b/FS/FS/part_export/infostreet.pm
@@ -19,6 +19,7 @@ tie my %options, 'Tie::IxHash',
   'desc'     => 'Real-time export to InfoStreet streetSmartAPI',
   'options'  => \%options,
   'nodomain' => 'Y',
+  'no_machine' => 1,
   'notes'    => <<'END'
 Real-time export to
 <a href="http://www.infostreet.com/">InfoStreet</a> streetSmartAPI.
diff --git a/FS/FS/part_export/internal_diddb.pm b/FS/FS/part_export/internal_diddb.pm
index a94e43e..b51f631 100644
--- a/FS/FS/part_export/internal_diddb.pm
+++ b/FS/FS/part_export/internal_diddb.pm
@@ -17,6 +17,7 @@ tie my %options, 'Tie::IxHash',
   'desc'    => 'Provision phone numbers from the internal DID database',
   'notes'   => 'After adding the export, DIDs may be imported under Tools -> Importing -> Import phone numbers (DIDs)',
   'options' => \%options,
+  'no_machine' => 1,
 );
 
 sub rebless { shift; }
diff --git a/FS/FS/part_export/ldap.pm b/FS/FS/part_export/ldap.pm
index 8385320..fe634d2 100644
--- a/FS/FS/part_export/ldap.pm
+++ b/FS/FS/part_export/ldap.pm
@@ -41,6 +41,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_acct',
   'desc'    => 'Real-time export to LDAP',
   'options' => \%options,
+  'default_svc_class' => 'Email',
   'notes'   => <<'END'
 Real-time export to arbitrary LDAP attributes.  Requires installation of
 <a href="http://search.cpan.org/dist/Net-LDAP">Net::LDAP</a> from CPAN.
diff --git a/FS/FS/part_export/netsapiens.pm b/FS/FS/part_export/netsapiens.pm
index 6e2ee8a..2e37d04 100644
--- a/FS/FS/part_export/netsapiens.pm
+++ b/FS/FS/part_export/netsapiens.pm
@@ -72,10 +72,11 @@ tie my %options, 'Tie::IxHash',
 ;
 
 %info = (
-  'svc'      => [ 'svc_phone', ], # 'part_device',
-  'desc'     => 'Provision phone numbers to NetSapiens',
-  'options'  => \%options,
-  'notes'    => <<'END'
+  'svc'        => [ 'svc_phone', ], # 'part_device',
+  'desc'       => 'Provision phone numbers to NetSapiens',
+  'options'    => \%options,
+  'no_machine' => 1,
+  'notes'      => <<'END'
 Requires installation of
 <a href="http://search.cpan.org/dist/REST-Client">REST::Client</a>
 from CPAN.
diff --git a/FS/FS/part_export/null.pm b/FS/FS/part_export/null.pm
index 0145af3..3a76488 100644
--- a/FS/FS/part_export/null.pm
+++ b/FS/FS/part_export/null.pm
@@ -11,3 +11,4 @@ sub _export_insert {}
 sub _export_replace {}
 sub _export_delete {}
 
+1;
diff --git a/FS/FS/part_export/phone_shellcommands.pm b/FS/FS/part_export/phone_shellcommands.pm
index 040af27..5c1ae01 100644
--- a/FS/FS/part_export/phone_shellcommands.pm
+++ b/FS/FS/part_export/phone_shellcommands.pm
@@ -138,3 +138,4 @@ sub ssh_cmd { #subroutine, not method
   &Net::SSH::ssh_cmd( { @_ } );
 }
 
+1;
diff --git a/FS/FS/part_export/phone_sqlopensips.pm b/FS/FS/part_export/phone_sqlopensips.pm
index 3d01c16..7b07ecf 100644
--- a/FS/FS/part_export/phone_sqlopensips.pm
+++ b/FS/FS/part_export/phone_sqlopensips.pm
@@ -21,10 +21,11 @@ tie %options, 'Tie::IxHash',
 ;
 
 %info = (
-  'svc'      => 'svc_phone',
-  'desc'     => 'Export DIDs to OpenSIPs dr_rules table',
-  'options'  => \%options,
-  'notes'    => 'Export DIDs to OpenSIPs dr_rules table',
+  'svc'        => 'svc_phone',
+  'desc'       => 'Export DIDs to OpenSIPs dr_rules table',
+  'options'    => \%options,
+  'no_machine' => 1,
+  'notes'      => 'Export DIDs to OpenSIPs dr_rules table',
 );
 
 sub rebless { shift; }
@@ -93,3 +94,4 @@ sub dr_reload {
     '';
 }
 
+1;
diff --git a/FS/FS/part_export/phone_sqlradius.pm b/FS/FS/part_export/phone_sqlradius.pm
index 6b14bed..46c372c 100644
--- a/FS/FS/part_export/phone_sqlradius.pm
+++ b/FS/FS/part_export/phone_sqlradius.pm
@@ -39,10 +39,11 @@ tie %options, 'Tie::IxHash',
 ;
 
 %info = (
-  'svc'      => 'svc_phone',
-  'desc'     => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS) for phone provisioning and rating',
-  'options'  => \%options,
-  'notes'    => <<END,
+  'svc'        => 'svc_phone',
+  'desc'       => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS) for phone provisioning and rating',
+  'options'    => \%options,
+  'no_machine' => 1,
+  'notes'      => <<END,
 Real-time export of <b>radcheck</b> table
 to any SQL database for <a href="http://www.freeradius.org/">FreeRADIUS</a>
 or <a href="http://radius.innercite.com/">ICRADIUS</a>.
diff --git a/FS/FS/part_export/postfix.pm b/FS/FS/part_export/postfix.pm
index 4fd19ee..9a8d617 100644
--- a/FS/FS/part_export/postfix.pm
+++ b/FS/FS/part_export/postfix.pm
@@ -22,6 +22,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_forward',
   'desc'    => 'Postfix text files',
   'options' => \%options,
+  'default_svc_class' => 'Email',
   'notes'   => <<'END'
 Batch export of Postfix aliases and virtual files.
 <a href="http://search.cpan.org/dist/File-Rsync">File::Rsync</a>
diff --git a/FS/FS/part_export/prizm.pm b/FS/FS/part_export/prizm.pm
index 02e89c6..9964489 100644
--- a/FS/FS/part_export/prizm.pm
+++ b/FS/FS/part_export/prizm.pm
@@ -79,11 +79,12 @@ possibly harmful.
 EOT
 
 %info = (
-  'svc'      => 'svc_broadband',
-  'desc'     => 'Real-time export to Northbound Interface',
-  'options'  => \%options,
-  'nodomain' => 'Y',
-  'notes'    => $notes,
+  'svc'        => 'svc_broadband',
+  'desc'       => 'Real-time export to Northbound Interface',
+  'options'    => \%options,
+  'nodomain'   => 'Y',
+  'no_machine' => 1,
+  'notes'      => $notes,
 );
 
 sub prizm_command {
diff --git a/FS/FS/part_export/radiator.pm b/FS/FS/part_export/radiator.pm
index 2ac3edb..f09d36a 100644
--- a/FS/FS/part_export/radiator.pm
+++ b/FS/FS/part_export/radiator.pm
@@ -11,6 +11,8 @@ tie my %options, 'Tie::IxHash', %FS::part_export::sqlradius::options;
   'desc'     => 'Real-time export to RADIATOR',
   'options'  => \%options,
   'nodomain' => '',
+  'no_machine' => 1,
+  'default_svc_class' => 'Internet',
   'notes' => <<'END',
 Real-time export of the <b>radusers</b> table to any SQL database in
 <a href="http://www.open.com.au/radiator/">Radiator</a>-native format.
diff --git a/FS/FS/part_export/router.pm b/FS/FS/part_export/router.pm
index 6a1d676..3071ece 100644
--- a/FS/FS/part_export/router.pm
+++ b/FS/FS/part_export/router.pm
@@ -87,6 +87,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_broadband',
   'desc'    => 'Send a command to a router.',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => 'Installation of Net::Telnet from CPAN is required for telnet connections.  This export will execute if the following virtual fields are set on the router: admin_user, admin_password, admin_address, admin_timeout, admin_prompt.  Option virtual fields are: admin_cmd_insert, admin_cmd_replace, admin_cmd_delete, admin_cmd_suspend, admin_cmd_unsuspend.  See the module documentation for a full list of required/supported router virtual fields.',
 );
 
diff --git a/FS/FS/part_export/rt_ticket.pm b/FS/FS/part_export/rt_ticket.pm
index b53b7da..7ae6105 100644
--- a/FS/FS/part_export/rt_ticket.pm
+++ b/FS/FS/part_export/rt_ticket.pm
@@ -127,6 +127,7 @@ tie my %options, 'Tie::IxHash', (
   'Create an RT ticket',
   'options'  => \%options,
   'nodomain' => '',
+  'no_machine' => 1,
   'notes'    => ' 
   Create a ticket in RT.  The subject and body of the ticket 
   will be generated from a message template.'
diff --git a/FS/FS/part_export/send_email.pm b/FS/FS/part_export/send_email.pm
index 05f6236..6ba131f 100644
--- a/FS/FS/part_export/send_email.pm
+++ b/FS/FS/part_export/send_email.pm
@@ -85,6 +85,7 @@ tie my %options, 'Tie::IxHash', (
   'Send an email message',
   'options'  => \%options,
   'nodomain' => '',
+  'no_machine' => 1,
   'notes'    => ' 
   Send an email message.  The subject and body of the message
   will be generated from a message template.'
diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm
index 20e9091..b9d6551 100644
--- a/FS/FS/part_export/shellcommands.pm
+++ b/FS/FS/part_export/shellcommands.pm
@@ -97,12 +97,13 @@ tie my %options, 'Tie::IxHash',
 ;
 
 %info = (
-  'svc'      => 'svc_acct',
-  'desc'     =>
+  'svc'         => 'svc_acct',
+  'desc'        =>
     'Real-time export via remote SSH (i.e. useradd, userdel, etc.)',
-  'options'  => \%options,
-  'nodomain' => 'Y',
-  'notes' => <<'END'
+  'options'     => \%options,
+  'nodomain'    => 'Y',
+  'svc_machine' => 1,
+  'notes'       => <<'END'
 Run remote commands via SSH.  Usernames are considered unique (also see
 shellcommands_withdomain).  You probably want this if the commands you are
 running will not accept a domain as a parameter.  You will need to
@@ -124,24 +125,7 @@ running will not accept a domain as a parameter.  You will need to
       this.form.unsuspend_stdin.value="";
     '>
   <LI>
-    <INPUT TYPE="button" VALUE="FreeBSD before 4.10 / 5.3" onClick='
-      this.form.useradd.value = "lockf /etc/passwd.lock pw useradd $username -d $dir -m -s $shell -u $uid -c $finger -h 0";
-      this.form.useradd_stdin.value = "$_password\n";
-      this.form.userdel.value = "lockf /etc/passwd.lock pw userdel $username -r"; this.form.userdel_stdin.value="";
-      this.form.usermod.value = "lockf /etc/passwd.lock pw usermod $old_username -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -g $new_gid -c $new_finger -h 0";
-      this.form.usermod_stdin.value = "$new__password\n"; this.form.suspend.value = "lockf /etc/passwd.lock pw lock $username";
-      this.form.suspend_stdin.value="";
-      this.form.unsuspend.value = "lockf /etc/passwd.lock pw unlock $username"; this.form.unsuspend_stdin.value="";
-    '>
-    Note: On FreeBSD versions before 5.3 and 4.10 (4.10 is after 4.9, not
-    4.1!), due to deficient locking in pw(1), you must disable the chpass(1),
-    chsh(1), chfn(1), passwd(1), and vipw(1) commands, or replace them with
-    wrappers that prepend "lockf /etc/passwd.lock".  Alternatively, apply the
-    patch in
-    <A HREF="http://www.freebsd.org/cgi/query-pr.cgi?pr=23501">FreeBSD PR#23501</A>
-    and use the "FreeBSD 4.10 / 5.3 or later" button below.
-  <LI>
-    <INPUT TYPE="button" VALUE="FreeBSD 4.10 / 5.3 or later" onClick='
+    <INPUT TYPE="button" VALUE="FreeBSD" onClick='
       this.form.useradd.value = "pw useradd $username -d $dir -m -s $shell -u $uid -g $gid -c $finger -h 0";
       this.form.useradd_stdin.value = "$_password\n";
       this.form.userdel.value = "pw userdel $username -r";
diff --git a/FS/FS/part_export/sqlmail.pm b/FS/FS/part_export/sqlmail.pm
index cbdaf7f..19505b4 100644
--- a/FS/FS/part_export/sqlmail.pm
+++ b/FS/FS/part_export/sqlmail.pm
@@ -37,6 +37,7 @@ tie my %options, 'Tie::IxHash',
   'desc'     => 'Real-time export to SQL-backed mail server',
   'options'  => \%options,
   'nodomain' => '',
+  'default_svc_class' => 'Email',
   'notes'    => <<'END'
 Database schema can be made to work with Courier IMAP, Exim and Dovecot.
 Others could work but are untested.  (more detailed description from
diff --git a/FS/FS/part_export/sqlradius.pm b/FS/FS/part_export/sqlradius.pm
index 7213966..6760d09 100644
--- a/FS/FS/part_export/sqlradius.pm
+++ b/FS/FS/part_export/sqlradius.pm
@@ -110,6 +110,7 @@ END
   'desc'     => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS)',
   'options'  => \%options,
   'nodomain' => 'Y',
+  'no_machine' => 1,
   'nas'      => 'Y', # show export_nas selection in UI
   'default_svc_class' => 'Internet',
   'notes'    => $notes1.
diff --git a/FS/FS/part_export/textradius.pm b/FS/FS/part_export/textradius.pm
index 869c7c7..07de875 100644
--- a/FS/FS/part_export/textradius.pm
+++ b/FS/FS/part_export/textradius.pm
@@ -18,6 +18,7 @@ tie my %options, 'Tie::IxHash',
   'desc'    =>
     'Real-time export to a text /etc/raddb/users file (Livingston, Cistron)',
   'options' => \%options,
+  'default_svc_class' => 'Internet',
   'notes'   => <<'END'
 This will edit a text RADIUS users file in place on a remote server.
 Requires installation of
diff --git a/FS/FS/part_export/trango.pm b/FS/FS/part_export/trango.pm
index e7f1126..64d2cc4 100644
--- a/FS/FS/part_export/trango.pm
+++ b/FS/FS/part_export/trango.pm
@@ -68,6 +68,7 @@ tie my %options, 'Tie::IxHash', (
   'svc'     => 'svc_broadband',
   'desc'    => 'Sends SNMP SETs to a Trango AP.',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => 'Requires Net::SNMP.  See the documentation for FS::part_export::trango for required virtual fields and usage information.',
 );
 
diff --git a/FS/FS/part_export/vitelity.pm b/FS/FS/part_export/vitelity.pm
index 12c3a7f..350a5ad 100644
--- a/FS/FS/part_export/vitelity.pm
+++ b/FS/FS/part_export/vitelity.pm
@@ -26,6 +26,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_phone',
   'desc'    => 'Provision phone numbers to Vitelity',
   'options' => \%options,
+  'no_machine' => 1,
   'notes'   => <<'END'
 Requires installation of
 <a href="http://search.cpan.org/dist/Net-Vitelity">Net::Vitelity</a>
diff --git a/FS/FS/part_export/vpopmail.pm b/FS/FS/part_export/vpopmail.pm
index 799a8e1..5fca170 100644
--- a/FS/FS/part_export/vpopmail.pm
+++ b/FS/FS/part_export/vpopmail.pm
@@ -23,6 +23,7 @@ tie my %options, 'Tie::IxHash',
   'svc'     => 'svc_acct',
   'desc'    => 'Real-time export to vpopmail text files',
   'options' => \%options,
+  'default_svc_class' => 'Email',
   'notes'   => <<'END'
 This export is currently unmaintained.  See shellcommands_withdomain for an
 export that uses vpopmail CLI commands instead.<BR>
diff --git a/FS/FS/part_export/www_plesk.pm b/FS/FS/part_export/www_plesk.pm
index ccf9b3e..a247f05 100644
--- a/FS/FS/part_export/www_plesk.pm
+++ b/FS/FS/part_export/www_plesk.pm
@@ -18,10 +18,11 @@ tie my %options, 'Tie::IxHash',
 ;
 
 %info = (
-  'svc'    => 'svc_www',
-  'desc'   => 'Real-time export to Plesk managed hosting service',
-  'options'=> \%options,
-  'notes'  => <<'END'
+  'svc'        => 'svc_www',
+  'desc'       => 'Real-time export to Plesk managed hosting service',
+  'options'    => \%options,
+  'no_machine' => 1,
+  'notes'      => <<'END'
 Real-time export to
 <a href="http://www.swsoft.com/">Plesk</a> managed server.
 Requires installation of
diff --git a/FS/FS/part_export/www_shellcommands.pm b/FS/FS/part_export/www_shellcommands.pm
index d6116ab..bef2e94 100644
--- a/FS/FS/part_export/www_shellcommands.pm
+++ b/FS/FS/part_export/www_shellcommands.pm
@@ -188,3 +188,4 @@ sub ssh_cmd { #subroutine, not method
   '';
 }
 
+1;
diff --git a/FS/FS/part_export_machine.pm b/FS/FS/part_export_machine.pm
new file mode 100644
index 0000000..1598e03
--- /dev/null
+++ b/FS/FS/part_export_machine.pm
@@ -0,0 +1,155 @@
+package FS::part_export_machine;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( dbh qsearch ); #qsearchs );
+use FS::part_export;
+use FS::svc_export_machine;
+
+=head1 NAME
+
+FS::part_export_machine - Object methods for part_export_machine records
+
+=head1 SYNOPSIS
+
+  use FS::part_export_machine;
+
+  $record = new FS::part_export_machine \%hash;
+  $record = new FS::part_export_machine { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::part_export_machine object represents an export hostname choice.
+FS::part_export_machine inherits from FS::Record.  The following fields are
+currently supported:
+
+=over 4
+
+=item machinenum
+
+primary key
+
+=item exportnum
+
+Export, see L<FS::part_export>
+
+=item machine
+
+Hostname or IP address
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record.  To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub table { 'part_export_machine'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+sub delete {
+  my $self = shift;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $error = $self->SUPER::delete;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  foreach my $svc_export_machine ( $self->svc_export_machine ) {
+    my $error = $svc_export_machine->delete;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  '';
+
+}
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=item check
+
+Checks all fields to make sure this is a valid record.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('machinenum')
+    || $self->ut_foreign_key('exportnum', 'part_export', 'exportnum')
+    || $self->ut_domain('machine')
+    || $self->ut_enum('disabled', [ '', 'Y' ])
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=item svc_export_machine
+
+=cut
+
+sub svc_export_machine {
+  my $self = shift;
+  qsearch( 'svc_export_machine', { 'machinenum' => $self->machinenum } );
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::part_export>, L<FS::Record>
+
+=cut
+
+1;
+
diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm
index dd18e87..7f22411 100644
--- a/FS/FS/part_svc.pm
+++ b/FS/FS/part_svc.pm
@@ -591,7 +591,7 @@ sub _svc_defs {
       };
       my $mod = $1;
 
-      if ( $mod =~ /^svc_[A-Z]/ or $mod =~ /^svc_acct_pop$/ ) {
+      if ( $mod =~ /^svc_[A-Z]/ or $mod =~ /^(svc_acct_pop|svc_export_machine)$/ ) {
         warn "skipping FS::$mod" if $DEBUG;
 	next;
       }
diff --git a/FS/FS/svc_export_machine.pm b/FS/FS/svc_export_machine.pm
new file mode 100644
index 0000000..39629d8
--- /dev/null
+++ b/FS/FS/svc_export_machine.pm
@@ -0,0 +1,111 @@
+package FS::svc_export_machine;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record; # qw( qsearch qsearchs );
+use FS::cust_svc;
+use FS::part_export_machine;
+
+=head1 NAME
+
+FS::svc_export_machine - Object methods for svc_export_machine records
+
+=head1 SYNOPSIS
+
+  use FS::svc_export_machine;
+
+  $record = new FS::svc_export_machine \%hash;
+  $record = new FS::svc_export_machine { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::svc_export_machine object represents a customer service export
+hostname.  FS::svc_export_machine inherits from FS::Record.  The following
+fields are currently supported:
+
+=over 4
+
+=item svcexportmachinenum
+
+primary key
+
+=item svcnum
+
+Customer service, see L<FS::cust_svc>
+
+=item machinenum
+
+Export hostname, see L<FS::part_export_machine>
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record.  To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub table { 'svc_export_machine'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=item delete
+
+Delete this record from the database.
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=item check
+
+Checks all fields to make sure this is a valid record.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('svcexportmachinenum')
+    || $self->ut_foreign_key('svcnum', 'cust_svc', 'svcnum')
+    || $self->ut_foreign_key('machinenum', 'part_export_machine', 'machinenum' )
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::cust_svc>, L<FS::part_export_machine>, L<FS::Record>
+
+=cut
+
+1;
+
diff --git a/FS/MANIFEST b/FS/MANIFEST
index bb10fb7..479dcad 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -668,3 +668,7 @@ t/cust_bill_pkg_discount_void.t
 FS/Trace.pm
 FS/agent_pkg_class.pm
 t/agent_pkg_class.t
+FS/part_export_machine.pm
+t/part_export_machine.t
+FS/svc_export_machine.pm
+t/svc_export_machine.t
diff --git a/FS/t/part_export_machine.t b/FS/t/part_export_machine.t
new file mode 100644
index 0000000..792bb50
--- /dev/null
+++ b/FS/t/part_export_machine.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::part_export_machine;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/svc_export_machine.t b/FS/t/svc_export_machine.t
new file mode 100644
index 0000000..5279be2
--- /dev/null
+++ b/FS/t/svc_export_machine.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::svc_export_machine;
+$loaded=1;
+print "ok 1\n";
diff --git a/httemplate/browse/part_export.cgi b/httemplate/browse/part_export.cgi
index 8e28f4f..beed708 100755
--- a/httemplate/browse/part_export.cgi
+++ b/httemplate/browse/part_export.cgi
@@ -36,10 +36,19 @@ function part_export_areyousure(href) {
       <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>"><% $part_export->exportnum %></A></TD>
 
       <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
-% if( $part_export->exportname ) {
-  <B><% $part_export->exportname %>:</B><BR>
-% }
-<% $part_export->exporttype %> to <% $part_export->machine %> (<A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>">edit</A> | <A HREF="javascript:part_export_areyousure('<% $p %>misc/delete-part_export.cgi?<% $part_export->exportnum %>')">delete</A>)</TD>
+%       if( $part_export->exportname ) {
+          <B><% $part_export->exportname %>:</B><BR>
+%       }
+        <% $part_export->exporttype %>
+        <% $part_export->machine
+             ? 'to '. ( $part_export->machine eq '_SVC_MACHINE'
+                          ? 'per-service hostname'
+                          : $part_export->machine
+                      )
+             : ''
+        %>
+        (<A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>">edit</A> | <A HREF="javascript:part_export_areyousure('<% $p %>misc/delete-part_export.cgi?<% $part_export->exportnum %>')">delete</A>)
+      </TD>
 
       <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
         <% itable() %>
diff --git a/httemplate/edit/part_export.cgi b/httemplate/edit/part_export.cgi
index d7219b7..0407ee7 100644
--- a/httemplate/edit/part_export.cgi
+++ b/httemplate/edit/part_export.cgi
@@ -13,12 +13,6 @@
   </TD>
 </TR>
 <TR>
-  <TD ALIGN="right">Export host</TD>
-  <TD>
-    <INPUT TYPE="text" NAME="machine" VALUE="<% $part_export->machine %>">
-  </TD>
-</TR>
-<TR>
   <TD ALIGN="right">Export</TD>
   <TD><% $widget->html %>
 
@@ -63,7 +57,7 @@ my $widget = new HTML::Widgets::SelectLayers(
   'options'        => \%layers,
   'form_name'      => 'dummy',
   'form_action'    => 'process/part_export.cgi',
-  'form_text'      => [qw( exportnum exportname machine )],
+  'form_text'      => [qw( exportnum exportname )],
 #  'form_checkbox'  => [qw()],
   'html_between'    => "</TD></TR></TABLE>\n",
   'layer_callback'  => sub {
@@ -71,9 +65,69 @@ my $widget = new HTML::Widgets::SelectLayers(
     my $html = qq!<INPUT TYPE="hidden" NAME="exporttype" VALUE="$layer">!.
                ntable("#cccccc",2);
 
-    $html .= '<TR><TD ALIGN="right">Description</TD><TD BGCOLOR=#ffffff>'.
-             $exports->{$layer}{notes}. '</TD></TR>'
-      if $layer;
+    if ( $layer ) {
+      $html .= '<TR><TD ALIGN="right">Description</TD><TD BGCOLOR=#ffffff>'.
+               $exports->{$layer}{notes}. '</TD></TR>';
+
+      if ( $exports->{$layer}{no_machine} ) {
+        $html .= '<INPUT TYPE="hidden" NAME="machine" VALUE="">'.
+                 '<INPUT TYPE="hidden" NAME="svc_machine" VALUE=N">';
+      } else {
+        $html .= '<TR><TD ALIGN="right">Hostname or IP</TD><TD>';
+        my $machine = $part_export->machine;
+        if ( $exports->{$layer}{svc_machine} ) {
+          my( $N_CHK, $Y_CHK) = ( 'CHECKED', '' );
+          my( $machine_DISABLED, $pem_DISABLED) = ( '', 'DISABLED' );
+          my $part_export_machine = '';
+          if ( $cgi->param('svc_machine') eq 'Y'
+                 || $machine eq '_SVC_MACHINE'
+             )
+          {
+            $Y_CHK = 'CHECKED';
+            $N_CHK = 'CHECKED';
+            $machine_DISABLED = 'DISABLED';
+            $pem_DISABLED = '';
+            $machine = '';
+            $part_export_machine =
+              $cgi->param('part_export_machine')
+              || join "\n",
+                   map $_->machine,
+                     grep ! $_->disabled,
+                       $part_export->part_export_machine;
+          }
+          my $oc = qq(onChange="${layer}_svc_machine_changed(this)");
+          $html .= qq[
+            <INPUT TYPE="radio" NAME="svc_machine" VALUE="N" $N_CHK $oc>
+            <INPUT TYPE="text" NAME="machine" ID="${layer}_machine" VALUE="$machine" $machine_DISABLED>
+            <BR>
+            <INPUT TYPE="radio" NAME="svc_machine" VALUE="Y" $Y_CHK $oc>
+            Selected in each customer service from these choices
+            <TEXTAREA NAME="part_export_machine" ID="${layer}_part_export_machine" $pem_DISABLED>$part_export_machine</TEXTAREA>
+
+            <SCRIPT TYPE="text/javascript">
+              function ${layer}_svc_machine_changed (what) {
+                if ( what.checked ) {
+                  var machine = document.getElementById("${layer}_machine");
+                  var part_export_machine = document.getElementById("${layer}_part_export_machine");
+                  if ( what.value == 'Y' ) {
+                    machine.disabled = true;
+                    part_export_machine.disabled = false;
+                  } else if ( what.value == 'N' ) {
+                    machine.disabled = false;
+                    part_export_machine.disabled = true;
+                  }
+                }
+              }
+            </SCRIPT>
+          ];
+        } else {
+          $html .= qq(<INPUT TYPE="text" NAME="machine" VALUE="$machine">).
+                     '<INPUT TYPE="hidden" NAME="svc_machine" VALUE=N">';
+        }
+        $html .= "</TD></TR>";
+      }
+
+    }
 
     foreach my $option ( keys %{$exports->{$layer}{options}} ) {
       my $optinfo = $exports->{$layer}{options}{$option};
diff --git a/httemplate/edit/process/part_export.cgi b/httemplate/edit/process/part_export.cgi
index 21150ef..6432d6b 100644
--- a/httemplate/edit/process/part_export.cgi
+++ b/httemplate/edit/process/part_export.cgi
@@ -28,6 +28,11 @@ my $new = new FS::part_export ( {
   } fields('part_export')
 } );
 
+if ( $cgi->param('svc_machine') eq 'Y' ) {
+  $new->machine('_SVC_MACHINE');
+  $new->part_export_machine_textarea( $cgi->param('part_export_machine') );
+}
+
 my $error;
 if ( $exportnum ) {
   #warn $old;

-----------------------------------------------------------------------

Summary of changes:
 FS/FS.pm                                           |    4 +
 FS/FS/Record.pm                                    |   21 +-
 FS/FS/Schema.pm                                    |   31 +-
 FS/FS/part_export.pm                               |  185 +++-
 FS/FS/part_export/acct_google.pm                   |   10 +-
 FS/FS/part_export/acct_http.pm                     |    1 +
 FS/FS/part_export/acct_plesk.pm                    |    8 +-
 FS/FS/part_export/acct_sql.pm                      |   12 +-
 FS/FS/part_export/acct_sql_status.pm               |    1 +
 FS/FS/part_export/acct_xmlrpc.pm                   |    1 +
 FS/FS/part_export/amazon_ec2.pm                    |    1 +
 FS/FS/part_export/artera_turbo.pm                  |    1 +
 FS/FS/part_export/broadband_http.pm                |    1 +
 FS/FS/part_export/broadband_nas.pm                 |    1 +
 FS/FS/part_export/broadband_shellcommands.pm       |    1 +
 FS/FS/part_export/broadband_snmp.pm                |    1 +
 FS/FS/part_export/broadband_sql.pm                 |    1 +
 FS/FS/part_export/broadband_sqlradius.pm           |    1 +
 FS/FS/part_export/communigate_pro.pm               |    1 +
 FS/FS/part_export/communigate_pro_singledomain.pm  |    1 +
 FS/FS/part_export/cp.pm                            |    1 +
 FS/FS/part_export/cpanel.pm                        |    2 +
 FS/FS/part_export/cust_http.pm                     |    1 +
 FS/FS/part_export/cyrus.pm                         |    2 +
 FS/FS/part_export/dashcs_e911.pm                   |    1 +
 FS/FS/part_export/domain_sql.pm                    |    1 +
 FS/FS/part_export/everyone_net.pm                  |    2 +
 FS/FS/part_export/ez_prepaid.pm                    |    1 +
 FS/FS/part_export/forward_sql.pm                   |    1 +
 FS/FS/part_export/globalpops_voip.pm               |    1 +
 FS/FS/part_export/http.pm                          |    1 +
 FS/FS/part_export/http_status.pm                   |    1 +
 FS/FS/part_export/ikano.pm                         |    1 +
 FS/FS/part_export/indosoft.pm                      |    1 +
 FS/FS/part_export/infostreet.pm                    |    1 +
 FS/FS/part_export/internal_diddb.pm                |    1 +
 FS/FS/part_export/ldap.pm                          |    1 +
 FS/FS/part_export/netsapiens.pm                    |    9 +-
 FS/FS/part_export/null.pm                          |    1 +
 FS/FS/part_export/phone_shellcommands.pm           |    1 +
 FS/FS/part_export/phone_sqlopensips.pm             |   10 +-
 FS/FS/part_export/phone_sqlradius.pm               |    9 +-
 FS/FS/part_export/postfix.pm                       |    1 +
 FS/FS/part_export/prizm.pm                         |   11 +-
 FS/FS/part_export/radiator.pm                      |    2 +
 FS/FS/part_export/router.pm                        |    1 +
 FS/FS/part_export/rt_ticket.pm                     |    1 +
 FS/FS/part_export/send_email.pm                    |    1 +
 FS/FS/part_export/shellcommands.pm                 |   30 +-
 FS/FS/part_export/sqlmail.pm                       |    1 +
 FS/FS/part_export/sqlradius.pm                     |    1 +
 FS/FS/part_export/textradius.pm                    |    1 +
 FS/FS/part_export/trango.pm                        |    1 +
 FS/FS/part_export/vitelity.pm                      |    1 +
 FS/FS/part_export/vpopmail.pm                      |    1 +
 FS/FS/part_export/www_plesk.pm                     |    9 +-
 FS/FS/part_export/www_shellcommands.pm             |    1 +
 FS/FS/{mailinglist.pm => part_export_machine.pm}   |   92 +-
 FS/FS/part_svc.pm                                  |    2 +-
 .../{agent_pkg_class.pm => svc_export_machine.pm}  |   48 +-
 FS/MANIFEST                                        |    4 +
 FS/t/{AccessRight.t => part_export_machine.t}      |    2 +-
 FS/t/{AccessRight.t => svc_export_machine.t}       |    2 +-
 httemplate/browse/part_export.cgi                  |    7 +-
 httemplate/browse/part_svc.cgi                     |   11 +-
 httemplate/edit/part_export.cgi                    |   74 +-
 httemplate/edit/part_svc.cgi                       |    7 +-
 httemplate/edit/process/part_export.cgi            |    5 +
 rt/bin/rt                                          |    2 +-
 rt/bin/rt.in                                       |    2 +-
 rt/configure                                       |  149 ++-
 rt/docs/web_deployment.pod                         |    2 +-
 rt/etc/initialdata                                 |    2 +-
 rt/etc/schema.SQLite                               |  106 +-
 rt/etc/upgrade/3.3.0/schema.mysql                  |   53 +-
 rt/etc/upgrade/3.3.11/schema.mysql                 |    4 +-
 rt/etc/upgrade/3.9.5/schema.mysql                  |   24 +-
 rt/etc/upgrade/3.9.7/schema.mysql                  |   10 +-
 rt/lib/RT/Action/CreateTickets.pm                  |    3 +-
 rt/lib/RT/Articles.pm                              |    3 +
 rt/lib/RT/Config.pm                                |    6 +-
 rt/lib/RT/Crypt/GnuPG.pm                           |    1 +
 rt/lib/RT/Dashboard.pm                             |   30 +
 rt/lib/RT/Generated.pm                             |    2 +-
 rt/lib/RT/I18N.pm                                  |    6 +-
 rt/lib/RT/Interface/Email.pm                       |   39 +-
 rt/lib/RT/Interface/Web.pm                         |   44 +-
 rt/lib/RT/Record.pm                                |    4 +-
 rt/lib/RT/Scrip.pm                                 |    2 +-
 rt/lib/RT/Scrips.pm                                |   80 +-
 rt/lib/RT/Search/Googleish.pm                      |   16 +-
 rt/lib/RT/SearchBuilder.pm                         |   40 +-
 rt/lib/RT/Shredder.pm                              |    6 +-
 rt/lib/RT/Test.pm                                  |    6 +-
 rt/lib/RT/Ticket.pm                                |   76 +-
 rt/lib/RT/Tickets.pm                               |   11 +
 rt/lib/RT/URI.pm                                   |   19 +
 rt/lib/RT/User.pm                                  |    2 +-
 rt/sbin/standalone_httpd                           |    2 +-
 rt/sbin/standalone_httpd.in                        |    2 +-
 rt/share/html/Admin/Queues/Modify.html             |    2 +-
 rt/share/html/Approvals/Elements/PendingMyApproval |    2 +-
 rt/share/html/Approvals/autohandler                |    9 +-
 rt/share/html/Dashboards/Subscription.html         |    2 +-
 rt/share/html/Elements/ColumnMap                   |    8 +-
 rt/share/html/Elements/EditCustomField             |    2 +-
 rt/share/html/Elements/Header                      |    3 +-
 rt/share/html/Elements/HeaderJavascript            |    2 +-
 rt/share/html/Elements/ListActions                 |    2 +-
 rt/share/html/Elements/MessageBox                  |    3 +-
 rt/share/html/Elements/QueueSummaryByStatus        |   10 +-
 rt/share/html/Elements/RT__CustomField/ColumnMap   |    4 +-
 rt/share/html/Elements/SelectWatcherType           |    2 +-
 rt/share/html/Elements/Tabs                        |    2 +-
 rt/share/html/Helpers/Autocomplete/Users           |    3 +
 rt/share/html/NoAuth/css/aileron/boxes.css         |    4 -
 rt/share/html/NoAuth/css/aileron/ticket.css        |   13 +-
 rt/share/html/NoAuth/css/ballard/boxes.css         |    5 +
 rt/share/html/NoAuth/css/ballard/layout.css        |    4 +
 rt/share/html/NoAuth/css/ballard/nav.css           |    3 +
 rt/share/html/NoAuth/css/ballard/ticket-search.css |    1 +
 rt/share/html/NoAuth/css/ballard/ticket.css        |    3 +
 rt/share/html/NoAuth/css/base/forms.css            |    1 +
 .../NoAuth/css/base/jquery-ui-timepicker-addon.css |    7 +
 rt/share/html/NoAuth/css/base/jquery-ui.css        |    2 -
 .../NoAuth/css/base/jquery-ui.custom.modified.css  |   24 +
 rt/share/html/NoAuth/css/base/main.css             |    1 +
 rt/share/html/NoAuth/css/base/superfish-navbar.css |    2 +
 rt/share/html/NoAuth/css/base/superfish.css        |    2 +
 rt/share/html/NoAuth/css/base/ticket-form.css      |   31 +-
 rt/share/html/NoAuth/css/base/ui.timepickr.css     |   56 -
 .../html/NoAuth/css/base/ui.timepickr.custom.css   |   54 -
 rt/share/html/NoAuth/css/web2/nav.css              |    1 +
 .../html/NoAuth/js/jquery-ui-1.8.4.custom.min.js   |   50 +
 .../html/NoAuth/js/jquery-ui-patch-datepicker.js   |   31 +
 .../html/NoAuth/js/jquery-ui-timepicker-addon.js   | 1326 ++++++++++++++++++++
 rt/share/html/NoAuth/js/ui.timepickr.js            |  941 --------------
 rt/share/html/NoAuth/js/util.js                    |   66 +-
 rt/share/html/Prefs/Other.html                     |    1 +
 rt/share/html/REST/1.0/Forms/ticket/default        |   22 +-
 rt/share/html/Search/Chart.html                    |    8 +-
 rt/share/html/Search/Elements/SelectPersonType     |    2 +-
 rt/share/html/Search/Results.html                  |    1 +
 rt/share/html/Ticket/Attachment/dhandler           |    9 +-
 rt/share/html/Ticket/Elements/ShowMembers          |    7 +-
 .../Ticket/Elements/ShowTransactionAttachments     |   18 +-
 rt/share/html/m/_elements/raw_style                |    4 +
 rt/share/html/m/_elements/wrapper                  |    2 +-
 148 files changed, 2530 insertions(+), 1633 deletions(-)
 copy FS/FS/{mailinglist.pm => part_export_machine.pm} (52%)
 copy FS/FS/{agent_pkg_class.pm => svc_export_machine.pm} (55%)
 copy FS/t/{AccessRight.t => part_export_machine.t} (77%)
 copy FS/t/{AccessRight.t => svc_export_machine.t} (78%)
 create mode 100644 rt/share/html/NoAuth/css/base/jquery-ui-timepicker-addon.css
 delete mode 100644 rt/share/html/NoAuth/css/base/ui.timepickr.css
 delete mode 100644 rt/share/html/NoAuth/css/base/ui.timepickr.custom.css
 create mode 100644 rt/share/html/NoAuth/js/jquery-ui-timepicker-addon.js
 delete mode 100644 rt/share/html/NoAuth/js/ui.timepickr.js




More information about the freeside-commits mailing list