rt 4.0.7
authorIvan Kohler <ivan@freeside.biz>
Sun, 23 Sep 2012 21:56:51 +0000 (14:56 -0700)
committerIvan Kohler <ivan@freeside.biz>
Sun, 23 Sep 2012 21:56:51 +0000 (14:56 -0700)
80 files changed:
rt/bin/rt
rt/bin/rt.in
rt/configure
rt/docs/web_deployment.pod
rt/etc/initialdata
rt/etc/schema.SQLite
rt/etc/upgrade/3.3.0/schema.mysql
rt/etc/upgrade/3.3.11/schema.mysql
rt/etc/upgrade/3.9.5/schema.mysql
rt/etc/upgrade/3.9.7/schema.mysql
rt/lib/RT/Action/CreateTickets.pm
rt/lib/RT/Articles.pm
rt/lib/RT/Config.pm
rt/lib/RT/Crypt/GnuPG.pm
rt/lib/RT/Dashboard.pm
rt/lib/RT/Generated.pm
rt/lib/RT/I18N.pm
rt/lib/RT/Interface/Email.pm
rt/lib/RT/Interface/Web.pm
rt/lib/RT/Record.pm
rt/lib/RT/Scrip.pm
rt/lib/RT/Scrips.pm
rt/lib/RT/Search/Googleish.pm
rt/lib/RT/SearchBuilder.pm
rt/lib/RT/Shredder.pm
rt/lib/RT/Test.pm
rt/lib/RT/Ticket.pm
rt/lib/RT/Tickets.pm
rt/lib/RT/URI.pm
rt/lib/RT/User.pm
rt/sbin/standalone_httpd
rt/sbin/standalone_httpd.in
rt/share/html/Admin/Queues/Modify.html
rt/share/html/Approvals/Elements/PendingMyApproval
rt/share/html/Approvals/autohandler
rt/share/html/Dashboards/Subscription.html
rt/share/html/Elements/ColumnMap
rt/share/html/Elements/EditCustomField
rt/share/html/Elements/Header
rt/share/html/Elements/HeaderJavascript
rt/share/html/Elements/ListActions
rt/share/html/Elements/MessageBox
rt/share/html/Elements/QueueSummaryByStatus
rt/share/html/Elements/RT__CustomField/ColumnMap
rt/share/html/Elements/SelectWatcherType
rt/share/html/Elements/Tabs
rt/share/html/Helpers/Autocomplete/Users
rt/share/html/NoAuth/css/aileron/boxes.css
rt/share/html/NoAuth/css/aileron/ticket.css
rt/share/html/NoAuth/css/ballard/boxes.css
rt/share/html/NoAuth/css/ballard/layout.css
rt/share/html/NoAuth/css/ballard/nav.css
rt/share/html/NoAuth/css/ballard/ticket-search.css
rt/share/html/NoAuth/css/ballard/ticket.css
rt/share/html/NoAuth/css/base/forms.css
rt/share/html/NoAuth/css/base/jquery-ui-timepicker-addon.css [new file with mode: 0644]
rt/share/html/NoAuth/css/base/jquery-ui.css
rt/share/html/NoAuth/css/base/jquery-ui.custom.modified.css
rt/share/html/NoAuth/css/base/main.css
rt/share/html/NoAuth/css/base/superfish-navbar.css
rt/share/html/NoAuth/css/base/superfish.css
rt/share/html/NoAuth/css/base/ticket-form.css
rt/share/html/NoAuth/css/base/ui.timepickr.css [deleted file]
rt/share/html/NoAuth/css/base/ui.timepickr.custom.css [deleted file]
rt/share/html/NoAuth/css/web2/nav.css
rt/share/html/NoAuth/js/jquery-ui-1.8.4.custom.min.js
rt/share/html/NoAuth/js/jquery-ui-patch-datepicker.js
rt/share/html/NoAuth/js/jquery-ui-timepicker-addon.js [new file with mode: 0644]
rt/share/html/NoAuth/js/ui.timepickr.js [deleted file]
rt/share/html/NoAuth/js/util.js
rt/share/html/Prefs/Other.html
rt/share/html/REST/1.0/Forms/ticket/default
rt/share/html/Search/Chart.html
rt/share/html/Search/Elements/SelectPersonType
rt/share/html/Search/Results.html
rt/share/html/Ticket/Attachment/dhandler
rt/share/html/Ticket/Elements/ShowMembers
rt/share/html/Ticket/Elements/ShowTransactionAttachments
rt/share/html/m/_elements/raw_style
rt/share/html/m/_elements/wrapper

index 32f459a..89873f5 100755 (executable)
--- 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";
index e54a07a..2a9f643 100644 (file)
@@ -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";
index 1862c5f..76ef85b 100755 (executable)
@@ -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@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@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 = "\a"
 
@@ -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
  ;;
index 4c3f73f..5d2cd4c 100644 (file)
@@ -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.
 
index cc07cec..7ab746d 100644 (file)
@@ -1,4 +1,4 @@
-# Initial data for a fresh RT3 Installation.
+# Initial data for a fresh RT installation.
 
 @Users = (
     {  Name         => 'root',
index 138971c..6897be2 100644 (file)
@@ -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,
index f699836..d8b0499 100644 (file)
@@ -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;
index cc35d40..eff8478 100644 (file)
@@ -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;
index 4bd0907..fe5018c 100644 (file)
@@ -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;
index 1be1656..4cbed6c 100644 (file)
@@ -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;
index 31489c8..efd2bda 100644 (file)
@@ -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}");
     }
 }
 
index 8dd661d..47d0ebe 100644 (file)
@@ -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,
         );
     }
 }
index f87ef84..014c764 100644 (file)
@@ -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;
index ab444d0..c5fb12b 100644 (file)
@@ -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 {
index 14ffa6a..2e2bbc4 100644 (file)
@@ -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;
index 2abcf3b..9fd946f 100644 (file)
@@ -50,7 +50,7 @@ package RT;
 use warnings;
 use strict;
 
-our $VERSION = '4.0.6';
+our $VERSION = '4.0.7';
 
 
 
index cadf7cc..e453cfa 100644 (file)
@@ -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 );
             }
index 02a1ec0..4c3ee99 100755 (executable)
@@ -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'} );
index 94da307..1aae758 100644 (file)
@@ -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)
     );
index e134178..fd238de 100755 (executable)
@@ -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'}
             )
         );
     }
index 9506616..8f97e74 100755 (executable)
@@ -545,7 +545,7 @@ sub _Set {
         }
     }
 
-    return $self->__Set(@_);
+    return $self->SUPER::_Set(@_);
 }
 
 
index 13a4b7d..fa33f7e 100755 (executable)
@@ -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 );
index a125483..1b4071f 100644 (file)
@@ -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]'";
index 3e98551..4278f75 100644 (file)
@@ -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,
     );
 }
 
index 40c73b3..4f96e16 100644 (file)
@@ -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'} );
     }
 }
 
index 7d69dd6..3e7c910 100644 (file)
@@ -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;
index 00f88b6..577c444 100755 (executable)
@@ -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;
 }
 
 
index 485d7df..c9986f4 100755 (executable)
@@ -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(
index fce0459..284a75e 100644 (file)
@@ -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>
index 9b4a826..e7f7c2a 100755 (executable)
@@ -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;
     }
 
index 3386cd1..cef0f31 100755 (executable)
@@ -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' );
index 45c3770..f84f6c1 100644 (file)
@@ -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' );
index 5682eee..85cd62f 100755 (executable)
@@ -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 %>" />
 
index d2061da..169c25c 100755 (executable)
@@ -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'} );
index a057706..3e0f2c6 100644 (file)
 %#
 %# 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>
index 3669e46..3a57102 100644 (file)
 <&|/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>
 </&>
index b9c3b4b..f268a5d 100644 (file)
@@ -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 />};
index b74c484..8b87fd4 100644 (file)
@@ -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' };
 }
index 1830c4b..65d06f8 100755 (executable)
@@ -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>
index 28788db..d5741f4 100644 (file)
@@ -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>
index 999d3fe..8929ff7 100755 (executable)
@@ -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} };
index 61995e0..69227bf 100755 (executable)
@@ -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>
index 09f274f..f649d28 100644 (file)
@@ -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 ) {
index ecb219d..b043984 100644 (file)
@@ -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 ) {
index 44beee0..4f1df60 100755 (executable)
@@ -56,7 +56,7 @@
 
 <%INIT>
 my @types;
-if ($Scope =~ 'queue') {
+if ($Scope =~ /queue/) {
    @types = RT::Queue->ManageableRoleGroupTypes;
 }
 else { 
index 3193b48..3aac9d8 100755 (executable)
@@ -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' );
 
index dbc2d88..c2b92c1 100644 (file)
@@ -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;
index ed6623c..f90ac9f 100644 (file)
 
 .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 {
index 4d069d9..7b573f7 100644 (file)
@@ -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;
 }
 
 
index 912ac55..9610cd5 100644 (file)
@@ -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;
  
 }
     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;
 
  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;
 
 }
 
index 8dc0cc1..8b600b8 100644 (file)
@@ -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 {
index 196f0e6..dc29818 100644 (file)
     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;
     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;
index 19ee847..fb252b5 100644 (file)
  border-bottom: 1px solid #999;
  -moz-border-radius-bottomleft: 0.5em;
  -webkit-border-bottom-left-radius: 0.5em;
+ border-bottom-left-radius: 0.5em;
 }
 
 
index 06b6678..4d416e1 100644 (file)
@@ -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;
 
 }
 
index eab97b1..19af1b2 100644 (file)
@@ -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 (file)
index 0000000..7eb8715
--- /dev/null
@@ -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; }
index 820996e..8fe4f15 100644 (file)
@@ -46,5 +46,3 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 @import "jquery-ui.custom.modified.css";
-@import "ui.timepickr.css";
-@import "ui.timepickr.custom.css";
index 7a32322..3b1e1a0 100644 (file)
     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; }
index 9f77c8a..dac733d 100644 (file)
@@ -49,6 +49,7 @@
 
 @import "yui-fonts.css";
 @import "jquery-ui.css";
+@import "jquery-ui-timepicker-addon.css";
 @import "superfish.css";
 @import "superfish-navbar.css";
 @import "superfish-vertical.css";
index 9a3f24c..459156e 100644 (file)
@@ -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;
 }
index 31198e4..7cb3b56 100644 (file)
@@ -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;
index daab263..869eba7 100644 (file)
@@ -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 (file)
index e2dacf7..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-  jQuery ui.timepickr
-  http://code.google.com/p/jquery-utils/
-
-  copyright Maxime Haineault <haineault@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 (file)
index ad2aa66..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-%# BEGIN BPS TAGGED BLOCK {{{
-%#
-%# COPYRIGHT:
-%#
-%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
-%#                                          <sales@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;
-}
index be63c59..e404b61 100644 (file)
     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;
index e90b4fe..0466005 100644 (file)
@@ -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);
index 40cc0db..2ac101f 100644 (file)
 
         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 (file)
index 0000000..0a4ff02
--- /dev/null
@@ -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 (file)
index 3b2040a..0000000
+++ /dev/null
@@ -1,941 +0,0 @@
-/*
-  jQuery utils - @VERSION
-  http://code.google.com/p/jquery-utils/
-
-  (c) Maxime Haineault <haineault@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@filamentgroup.com) 
-           Maggie Wachs (maggie@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@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@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@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@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);
index 5bfce41..fe5c0a3 100644 (file)
@@ -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) {
index 9f7e04a..b5d3edd 100644 (file)
@@ -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,
index 9a2212b..016a50c 100755 (executable)
@@ -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);
index 070ce7c..571c3d3 100644 (file)
@@ -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'};
     }
 
index d07e49c..bc29111 100644 (file)
@@ -62,7 +62,7 @@
 
 <%INIT>
 my @types;
-if ($Scope =~ 'queue') {
+if ($Scope =~ /queue/) {
    @types = qw(Cc AdminCc);
 }
 elsif ($Suffix eq 'Group') {
index 171b38d..4fee865 100755 (executable)
@@ -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')
index 75efeff..eb291e4 100755 (executable)
@@ -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;
     }
      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 );
index c17c6e7..1ffbda2 100755 (executable)
@@ -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>
index 877201f..95a2341 100644 (file)
@@ -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;
index 8c19977..a349829 100644 (file)
@@ -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;
 }
index 794385d..1891079 100644 (file)
@@ -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();