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;
         }
         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";
         }
         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;
         }
         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";
         }
         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.
 #! /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>.
 #
 #
 # 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.
 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
 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.
   # 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
        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 :
 fi
 
     if test x$as_have_required = xno; then :
@@ -552,8 +560,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='RT'
 PACKAGE_TARNAME='rt'
 # 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=''
 
 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
     $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
     ;;
 
   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
   # 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]...
 
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1364,7 +1372,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
 
 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
 
    esac
   cat <<\_ACEOF
 
@@ -1488,8 +1496,8 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
 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
 
 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
 
        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
   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
   # 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
   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.
 
 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 $@
 
 
   $ $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
       || { { $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
 
   fi
 done
 
@@ -1946,7 +1954,7 @@ rt_version_major=4
 
 rt_version_minor=0
 
 
 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
 
 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
 { $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
   $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; }
 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
   $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; }
 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
   $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; }
 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
   $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; }
 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
   $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; }
 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
   $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; }
 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
   $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; }
 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
   $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
 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
 
 # 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
 { { $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; }
 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
   { { $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
 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'.
 $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
     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; }
 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
   $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
 { { $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
 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; }
 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
   $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; }
 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
   $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; }
 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
   $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; }
 
 { $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
   $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; }
 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
 
   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; }
 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
   $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; }
 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
   $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
      :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;}
       { $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;}
   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"
 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.
 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
 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="
 # 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
 
   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="\\
 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.
   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" ;;
 
     "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
 
   esac
 done
 
@@ -4679,9 +4699,10 @@ fi
 # after its creation but before its name has been assigned to `$tmp'.
 $debug ||
 {
 # after its creation but before its name has been assigned to `$tmp'.
 $debug ||
 {
-  tmp=
+  tmp= ac_tmp=
   trap 'exit_status=$?
   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
 }
 ' 0
   trap 'as_fn_exit 1' 1 2 13 15
 }
@@ -4689,12 +4710,13 @@ $debug ||
 
 {
   tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
 
 {
   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
 }  ||
 {
   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.
 
 # 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
 
   ac_cs_awk_cr=$ac_cr
 fi
 
-echo 'BEGIN {' >"$tmp/subs1.awk" &&
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
 _ACEOF
 
 
 _ACEOF
 
 
@@ -4744,7 +4766,7 @@ done
 rm -f conf$$subs.sh
 
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 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
 _ACEOF
 sed -n '
 h
@@ -4792,7 +4814,7 @@ t delim
 rm -f conf$$subs.awk
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 _ACAWK
 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"
 
   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
   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
 
   || 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]*:*);;
   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
   :[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
     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 `:'.
       *) # 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 ||
           [\\/$]*) 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'"
       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
     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
     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
 "
 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" &&
 
 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;}
 
   { $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
   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
  ;;
   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
     /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.
 
 (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',
 
 @Users = (
     {  Name         => 'root',
index 138971c..6897be2 100644 (file)
@@ -3,7 +3,7 @@
 CREATE TABLE Attachments (
   id INTEGER PRIMARY KEY  ,
   TransactionId INTEGER  ,
 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  ,
   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  ,
   ContentEncoding varchar(80) NULL  ,
   Content LONGTEXT NULL  ,
   Headers LONGTEXT NULL  ,
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL 
   
 ) ;
   Created DATETIME NULL 
   
 ) ;
@@ -30,12 +30,12 @@ CREATE TABLE Queues (
   CommentAddress varchar(120) NULL  ,
   Lifecycle varchar(32) NULL  ,
   SubjectTag varchar(120) NULL  ,
   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  ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  ,
   Disabled int2 NOT 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  ,
   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  ,
   LastUpdated DATETIME NULL  ,
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  
   
 ) ;
   Created DATETIME NULL  
   
 ) ;
@@ -106,9 +106,9 @@ CREATE TABLE ScripConditions (
   Argument varchar(255) NULL  ,
   ApplicableTransTypes varchar(60) NULL  ,
 
   Argument varchar(255) NULL  ,
   ApplicableTransTypes varchar(60) NULL  ,
 
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
   
 ) ;
   LastUpdated DATETIME NULL  
   
 ) ;
@@ -119,8 +119,8 @@ CREATE TABLE ScripConditions (
 CREATE TABLE Transactions (
   id INTEGER PRIMARY KEY  ,
   ObjectType varchar(255) NULL  ,
 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  ,
   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  ,
 
   NewReference integer NULL  ,
   Data varchar(255) NULL  ,
 
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  
   
 ) ;
   Created DATETIME NULL  
   
 ) ;
@@ -143,19 +143,19 @@ CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId);
 CREATE TABLE Scrips (
   id INTEGER PRIMARY KEY  ,
   Description varchar(255),
 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  ,
   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  ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
   
 ) ;
   LastUpdated DATETIME NULL  
   
 ) ;
@@ -167,7 +167,7 @@ CREATE TABLE ACL (
   id INTEGER PRIMARY KEY  ,
   PrincipalType varchar(25) NOT NULL,
 
   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,
   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  ,
 
 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  ,
   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,
 
   Timezone char(50) NULL  ,
   PGPKey text NULL,
 
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
   
 ) ;
   LastUpdated DATETIME NULL  
   
 ) ;
@@ -270,20 +270,20 @@ CREATE INDEX Users4 ON Users (EmailAddress);
 
 CREATE TABLE Tickets (
   id INTEGER PRIMARY KEY  ,
 
 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  ,
   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]' ,
   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  ,
   Status varchar(64) NULL  ,
-  TimeLeft integer NULL  ,
+  TimeLeft integer NULL DEFAULT 0 ,
   Told DATETIME NULL  ,
   Starts DATETIME NULL  ,
   Started DATETIME NULL  ,
   Told DATETIME NULL  ,
   Starts DATETIME NULL  ,
   Started DATETIME NULL  ,
@@ -291,9 +291,9 @@ CREATE TABLE Tickets (
   Resolved DATETIME NULL  ,
 
 
   Resolved DATETIME NULL  ,
 
 
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  ,
   LastUpdated DATETIME NULL  ,
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
   Disabled int2 NOT 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  ,
   Description varchar(255) NULL  ,
   ExecModule varchar(60) NULL  ,
   Argument varchar(255) NULL  ,
-  Creator integer NULL  ,
+  Creator integer NULL DEFAULT 0 ,
   Created DATETIME NULL  ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
   
 ) ;
   LastUpdated DATETIME NULL  
   
 ) ;
@@ -333,11 +333,11 @@ CREATE TABLE Templates (
   Description varchar(255) NULL  ,
   Type varchar(16) NULL  ,
   Language varchar(16) NULL  ,
   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  ,
   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  
   
 ) ;
   Created DATETIME NULL  
   
 ) ;
@@ -437,10 +437,10 @@ CREATE TABLE Attributes (
   Content LONGTEXT NULL  ,
   ContentType varchar(16),
   ObjectType varchar(25) NOT NULL  ,
   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  ,
   Created DATETIME NULL  ,
-  LastUpdatedBy integer NULL  ,
+  LastUpdatedBy integer NULL DEFAULT 0 ,
   LastUpdated DATETIME NULL  
  
 ) ;
   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 '',
 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,
 );
 
 
 CREATE TABLE ObjectTopics (
 id INTEGER PRIMARY KEY,
-Topic integer NOT NULL,
+Topic integer NOT NULL DEFAULT 0,
 ObjectType varchar(64) NOT NULL DEFAULT '',
 ObjectType varchar(64) NOT NULL DEFAULT '',
-ObjectId integer NOT NULL
+ObjectId integer NOT NULL DEFAULT 0
 );
 
 CREATE TABLE ObjectClasses (
 id INTEGER PRIMARY KEY,
 );
 
 CREATE TABLE ObjectClasses (
 id INTEGER PRIMARY KEY,
-Class integer NOT NULL,
+Class integer NOT NULL DEFAULT 0,
 ObjectType varchar(64) NOT NULL DEFAULT '',
 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,
 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';
 
 
 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;
 
 # 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 (
 
 
 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;
 
 
 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;
 
 # 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';
 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;
 
 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';
 
 
 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 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);
         $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,
             QUOTEVALUE      => $args{'QUOTEVALUE'},
             ENTRYAGGREGATOR => 'AND', #$args{'ENTRYAGGREGATOR'},
             SUBCLAUSE       => $clause,
+            CASESENSITIVE   => 0,
         );
         $self->SUPER::Limit(
             ALIAS           => $ObjectValuesAlias,
         );
         $self->SUPER::Limit(
             ALIAS           => $ObjectValuesAlias,
@@ -380,6 +381,7 @@ sub LimitCustomField {
             QUOTEVALUE      => $args{'QUOTEVALUE'},
             ENTRYAGGREGATOR => $args{'ENTRYAGGREGATOR'},
             SUBCLAUSE       => $clause,
             QUOTEVALUE      => $args{'QUOTEVALUE'},
             ENTRYAGGREGATOR => $args{'ENTRYAGGREGATOR'},
             SUBCLAUSE       => $clause,
+            CASESENSITIVE   => 0,
         );
         $self->SUPER::Limit(
             ALIAS           => $ObjectValuesAlias,
         );
         $self->SUPER::Limit(
             ALIAS           => $ObjectValuesAlias,
@@ -389,6 +391,7 @@ sub LimitCustomField {
             QUOTEVALUE      => $args{'QUOTEVALUE'},
             ENTRYAGGREGATOR => $args{'ENTRYAGGREGATOR'},
             SUBCLAUSE       => $clause,
             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 => {
             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
             },
                 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 ) {
 
             my %seen;
             foreach my $encoding ( grep defined && length, splice @$value ) {
-                next if $seen{ $encoding }++;
+                next if $seen{ $encoding };
                 if ( $encoding eq '*' ) {
                     unshift @$value, '*';
                     next;
                 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
     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 {
 );
 
 sub ParseStatus {
index 14ffa6a..2e2bbc4 100644 (file)
@@ -454,6 +454,36 @@ sub CurrentUserCanCreateAny {
     return 0;
 }
 
     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;
 RT::Base->_ImportOverlays();
 
 1;
index 2abcf3b..9fd946f 100644 (file)
@@ -50,7 +50,7 @@ package RT;
 use warnings;
 use strict;
 
 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;
 
 
     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 "
         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
             }
 
             # 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 );
             }
 
                 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) {
         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 );
             }
                 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') ) {
     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
     }
     else {
         return $ticket->QueueObj->CorrespondAddress
@@ -1221,8 +1221,16 @@ sub SetInReplyTo {
         if @references > 10;
 
     my $mail = $args{'Message'};
         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 {
 }
 
 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'} ) ;
 
     $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 ) {
             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'} );
         }
     } 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::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' );
 
     # 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
             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");
                 $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();
     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();
         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
     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'} );
         }
 
             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;
 
             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');
             }
         }
                 TangentForLoginWithError('You are not an authorized user');
             }
         }
@@ -970,7 +978,7 @@ sub MobileClient {
     my $self = shift;
 
 
     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;
     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,
     # 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 {
 );
 
 sub IsCompCSRFWhitelisted {
@@ -1237,7 +1253,19 @@ sub IsRefererCSRFWhitelisted {
     my $configs;
     for my $config ( $base_url, RT->Config->Get('ReferrerWhitelist') ) {
         push @$configs,$config;
     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);
     }
 
     return (0,$referer,$configs);
@@ -1962,7 +1990,7 @@ sub MakeMIMEEntity {
     );
     my $Message = MIME::Entity->build(
         Type    => 'multipart/mixed',
     );
     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)
     );
         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);
 
 
     my $value = $self->SUPER::__Value($field);
 
+    return undef if (!defined $value);
+
     if ( $args{'decode_utf8'} ) {
         if ( !utf8::is_utf8($value) ) {
             utf8::decode($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",
             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;
 
 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
     foreach my $scrip (@{$self->Prepared}) {
         $RT::Logger->debug(
             "Committing scrip #". $scrip->id
@@ -199,8 +189,6 @@ sub Commit {
                         TransactionObj => $self->{'TransactionObj'} );
     }
 
                         TransactionObj => $self->{'TransactionObj'} );
     }
 
-    # Apply the bandaid.
-    $self->_RestoreCurrentUser( TicketObj => $self->{TicketObj} ) if $self->{TicketObj};
 }
 
 
 }
 
 
@@ -221,12 +209,6 @@ sub Prepare {
                  Type           => undef,
                  @_ );
 
                  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'},
     #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});
 
 };
     return (@{$self->Prepared});
 
 };
@@ -279,40 +257,6 @@ sub Prepared {
     return ($self->{'prepared_scrips'} || []);
 }
 
     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 
 =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 );
     }
     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+)  # A straight word
                             (?:\.  # With an optional .foo
                                 ($RE{delimited}{-delim=>q['"]}
-                                |\w+
+                                |[\w-]+  # Allow \w + dashes
                                 ) # Which could be ."foo bar", too
                             )?
                         )
                                 ) # Which could be ."foo bar", too
                             )?
                         )
@@ -225,6 +225,11 @@ sub GuessType {
     return "default";
 }
 
     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]'"; }
 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     {
     }
 }
 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]'";
 }
 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(
                  @_ );
 
     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(
     );
     $self->Limit(
-       ALIAS      => $alias,
-       FIELD      => 'CustomField',
-       OPERATOR   => '=',
-       VALUE      => $args{'CUSTOMFIELD'},
+        ALIAS      => $alias,
+        FIELD      => 'CustomField',
+        OPERATOR   => '=',
+        VALUE      => $args{'CUSTOMFIELD'},
     ) if ($args{'CUSTOMFIELD'});
     $self->Limit(
     ) if ($args{'CUSTOMFIELD'});
     $self->Limit(
-       ALIAS      => $alias,
-       FIELD      => 'ObjectType',
-       OPERATOR   => '=',
-       VALUE      => $self->_SingularClass,
+        ALIAS      => $alias,
+        FIELD      => 'ObjectType',
+        OPERATOR   => '=',
+        VALUE      => $self->_SingularClass,
     );
     $self->Limit(
     );
     $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];
 
 {
     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; }
 
 
     if (RT->Config->Get('DevelMode')) { require Module::Refresh; }
 
-    $class->bootstrap_db( %args );
-
     RT::InitPluginPaths();
     RT::InitPluginPaths();
+    RT::InitClasses();
+
+    $class->bootstrap_db( %args );
 
     __reconnect_rt()
         unless $args{nodb};
 
 
     __reconnect_rt()
         unless $args{nodb};
 
-    RT::InitClasses();
     RT::InitLogging();
 
     RT->Plugins;
     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;
 
         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;
             eq lc RT::User->CanonicalizeEmailAddress( $addr->address ) )
         {
             $args{'PrincipalId'} = $self->CurrentUser->id;
@@ -1305,7 +1305,7 @@ sub DeleteWatcher {
             }
         }
         else {
             }
         }
         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') );
         }
             return ( 0,
                      $self->loc('Error in parameters to Ticket->DeleteWatcher') );
         }
@@ -1989,6 +1989,31 @@ sub FirstActiveStatus {
     return $next;
 }
 
     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
 =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(
     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;
 }
 
     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
 
 
 =head2 TransactionBatch
 
@@ -3376,6 +3425,22 @@ sub ApplyTransactionBatch {
 
 sub _ApplyTransactionBatch {
     my $self = shift;
 
 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;
     my $batch = $self->TransactionBatch;
 
     my %seen;
@@ -3423,10 +3488,7 @@ sub DESTROY {
         return;
     }
 
         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;
 
     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' ) {
     my $direction = $meta->[1] || '';
     my ($matchfield, $linkfield) = ('', '');
     if ( $direction eq 'To' ) {
@@ -1651,6 +1655,7 @@ sub _CustomFieldLimit {
                 FIELD      => $column,
                 OPERATOR   => $op,
                 VALUE      => $value,
                 FIELD      => $column,
                 OPERATOR   => $op,
                 VALUE      => $value,
+                CASESENSITIVE => 0,
                 %rest
             ) );
             $self->_CloseParen;
                 %rest
             ) );
             $self->_CloseParen;
@@ -1713,6 +1718,7 @@ sub _CustomFieldLimit {
                         FIELD    => 'Content',
                         OPERATOR => $op,
                         VALUE    => $value,
                         FIELD    => 'Content',
                         OPERATOR => $op,
                         VALUE    => $value,
+                        CASESENSITIVE => 0,
                         %rest
                     );
                 }
                         %rest
                     );
                 }
@@ -1739,6 +1745,7 @@ sub _CustomFieldLimit {
                         OPERATOR        => $op,
                         VALUE           => $value,
                         ENTRYAGGREGATOR => 'AND',
                         OPERATOR        => $op,
                         VALUE           => $value,
                         ENTRYAGGREGATOR => 'AND',
+                        CASESENSITIVE => 0,
                     ) );
                 }
             }
                     ) );
                 }
             }
@@ -1748,6 +1755,7 @@ sub _CustomFieldLimit {
                     FIELD    => 'Content',
                     OPERATOR => $op,
                     VALUE    => $value,
                     FIELD    => 'Content',
                     OPERATOR => $op,
                     VALUE    => $value,
+                    CASESENSITIVE => 0,
                     %rest
                 );
 
                     %rest
                 );
 
@@ -1774,6 +1782,7 @@ sub _CustomFieldLimit {
                     OPERATOR        => $op,
                     VALUE           => $value,
                     ENTRYAGGREGATOR => 'AND',
                     OPERATOR        => $op,
                     VALUE           => $value,
                     ENTRYAGGREGATOR => 'AND',
+                    CASESENSITIVE => 0,
                 ) );
                 $self->_CloseParen;
             }
                 ) );
                 $self->_CloseParen;
             }
@@ -1830,6 +1839,7 @@ sub _CustomFieldLimit {
                 FIELD      => $column,
                 OPERATOR   => $op,
                 VALUE      => $value,
                 FIELD      => $column,
                 OPERATOR   => $op,
                 VALUE      => $value,
+                CASESENSITIVE => 0,
             ) );
         }
         else {
             ) );
         }
         else {
@@ -1839,6 +1849,7 @@ sub _CustomFieldLimit {
                 FIELD      => 'Content',
                 OPERATOR   => $op,
                 VALUE      => $value,
                 FIELD      => 'Content',
                 OPERATOR   => $op,
                 VALUE      => $value,
+                CASESENSITIVE => 0,
             );
         }
         $self->_SQLLimit(
             );
         }
         $self->_SQLLimit(
index fce0459..284a75e 100644 (file)
@@ -91,7 +91,26 @@ sub new {
     return ($self);
 }
 
     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>
 
 
 =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 {
         # 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;
     }
 
         return 0;
     }
 
index 3386cd1..cef0f31 100755 (executable)
@@ -172,7 +172,7 @@ if (caller) {
 require Plack::Runner;
 
 my $is_fastcgi = $0 =~ m/fcgi$/;
 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' );
                             $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$/;
 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' );
                             $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 %>" />
 
 <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'} );
 
 # 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'} );
 
 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>
 %#
 %# END BPS TAGGED BLOCK }}}
 <%init>
-$m->call_next(%ARGS) if $session{'CurrentUser'}->UserObj->HasRight(
+if ( $session{'CurrentUser'}->UserObj->HasRight(
     Right => 'ShowApprovalsTab',
     Object => $RT::System,
     Right => 'ShowApprovalsTab',
     Object => $RT::System,
-);
+) ) {
+    $m->call_next(%ARGS);
+}
+else {
+    Abort("No permission to view approval");
+}
 </%init>
 </%init>
index 3669e46..3a57102 100644 (file)
 <&|/l&>Recipient</&>:
 </td><td class="value">
 <input name="Recipient" id="Recipient" size="30" value="<%$fields{Recipient} ? $fields{Recipient} : ''%>" />
 <&|/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>
 </&>
 </td></tr>
 </table>
 </&>
index b9c3b4b..f268a5d 100644 (file)
@@ -118,7 +118,7 @@ my $COLUMN_MAP = {
     CheckBox => {
         title => sub {
             my $name = $_[1] || 'SelectedTickets';
     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, },
 
             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" />}
 
             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;
             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 $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 />};
             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 ) {
 
 # 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' };
 }
     $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 );
 
 # $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>
 $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'})) {
 % }
 
 % 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>
 % }
 --></script>
 <%ARGS>
index 999d3fe..8929ff7 100755 (executable)
@@ -65,7 +65,7 @@ if ( ref( $session{'Actions'}{''} ) eq 'ARRAY' ) {
     unshift @actions, @{ delete $session{'Actions'}{''} };
 }
 
     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} };
 
 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 %>">\
 %#
 %# 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' );
 % $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');
 $Height           => RT->Config->Get('MessageBoxHeight', $session{'CurrentUser'} ) || 15
 $Wrap             => RT->Config->Get('MessageBoxWrap', $session{'CurrentUser'} ) || 'SOFT'
 $IncludeSignature => RT->Config->Get('MessageBoxIncludeSignature');
+$IncludeArticle   => 1;
 </%ARGS>
 </%ARGS>
index 09f274f..f649d28 100644 (file)
@@ -122,9 +122,13 @@ my $statuses = {};
 
 use RT::Report::Tickets;
 my $report = RT::Report::Tickets->new( RT->SystemUser );
 
 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 ) {
 $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';
     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, },
 
             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';
             return '' if $_[0]->IsApplied;
 
             my $name = 'RemoveCustomField';
-            my $arg = $m->request_args->{ $name };
+            my $arg = $DECODED_ARGS->{ $name };
 
             my $checked = '';
             if ( $arg && ref $arg ) {
 
             my $checked = '';
             if ( $arg && ref $arg ) {
index 44beee0..4f1df60 100755 (executable)
@@ -56,7 +56,7 @@
 
 <%INIT>
 my @types;
 
 <%INIT>
 my @types;
-if ($Scope =~ 'queue') {
+if ($Scope =~ /queue/) {
    @types = RT::Queue->ManageableRoleGroupTypes;
 }
 else { 
    @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 );
     }
     } 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' );
 
     $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;
 
 
 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;
 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;
 
 .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 {
 }
 
 .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;
  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;
  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;
 
 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;
  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;
  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;
  margin-top: 1em;
  -moz-border-radius: 0.5em;
  -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
  margin-right: 0.25em;
  
 }
  margin-right: 0.25em;
  
 }
     padding-right: 0.75em;
     -moz-border-radius: 0.5em;
     -webkit-border-radius: 0.5em;
     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;
 
     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;
  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;
  
  
  -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;
     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;
     -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;
     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-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;
  -moz-border-radius-bottomleft: 0.5em;
  -webkit-border-bottom-left-radius: 0.5em;
+ border-bottom-left-radius: 0.5em;
 }
 
 div#footer #time {
 }
 
 div#footer #time {
index 196f0e6..dc29818 100644 (file)
     background-color: #fff;
     -moz-border-radius-bottomright: 0.5em;
     -webkit-border-bottom-right-radius: 0.5em;
     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;
     -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;
     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: 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;
     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: 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;
  color: #ccc;
  -moz-border-radius-bottomleft: 0.5em;
  -webkit-border-bottom-left-radius: 0.5em;
+ border-bottom-left-radius: 0.5em;
  white-space: nowrap;
 }
 
  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: 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 {
 }
 
 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;
 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;
    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 {
 }
 
 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";
 %#
 %# 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*/
 }
     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 "yui-fonts.css";
 @import "jquery-ui.css";
+@import "jquery-ui-timepicker-addon.css";
 @import "superfish.css";
 @import "superfish-navbar.css";
 @import "superfish-vertical.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;
        -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;
        -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;
 }
 .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;
 .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;
 }
 
     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;
     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 */
 
 @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;
     {
         float: none;
         width: auto;
@@ -115,15 +111,12 @@ iframe.richtext-editor {
     }
 }
 
     }
 }
 
-#comp-Ticket-Update #body {
+.sidebyside #comp-Ticket-Update #body {
     padding-top: 3em;
 }
 
     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;
 }
 
     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: 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;
     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);
 ;
 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;
     };
 
         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);
 })(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(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,
         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) {
 });
 
 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 ) ) {
 % 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,
 % 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 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
         }
 
         # people fields allow multiple values
@@ -292,8 +303,10 @@ else {
         elsif (exists $simple{$key}) {
             $key = $simple{$key};
             $set = "Set$key";
         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}) {
             ($n, $s) = $ticket->$set("$val");
         }
         elsif (exists $dates{$key}) {
@@ -331,13 +344,6 @@ else {
                 }
             }
             foreach $p (keys %new) {
                 }
             }
             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);
                 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{$_};
 
     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'};
     }
 
         $query{'SavedChartSearchId'} = $saved_search->{'SearchId'};
     }
 
index d07e49c..bc29111 100644 (file)
@@ -62,7 +62,7 @@
 
 <%INIT>
 my @types;
 
 <%INIT>
 my @types;
-if ($Scope =~ 'queue') {
+if ($Scope =~ /queue/) {
    @types = qw(Cc AdminCc);
 }
 elsif ($Suffix eq 'Group') {
    @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'} );
 
 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')
 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
 <%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;
     }
         $trans = $1;
         $attach = $2;
     }
      my $enc = $AttachmentObj->OriginalEncoding || 'utf-8';
      my $iana = Encode::find_encoding( $enc );
      $iana = $iana? $iana->mime_name : $enc;
      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 );
 
      $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 />
 <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) {
 % if ($depth < 8) {
-<& /Ticket/Elements/ShowMembers, Ticket => $link->BaseObj, depth => ($depth+1) &> 
+<& /Ticket/Elements/ShowMembers, Ticket => $link->BaseObj, depth => ($depth+1), checked => $checked &> 
 % }
 </li>
 % }
 % }
 </li>
 % }
@@ -61,9 +62,13 @@ return unless $Ticket;
 my $members = $Ticket->Members;
 return unless $members->Count;
 
 my $members = $Ticket->Members;
 return unless $members->Count;
 
+return if $checked->{$Ticket->id};
+
+$checked->{$Ticket->id} = 1;
 </%INIT>
 
 <%ARGS>
 $Ticket => undef
 $depth => 1
 </%INIT>
 
 <%ARGS>
 $Ticket => undef
 $depth => 1
+$checked => {}
 </%ARGS>
 </%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 $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');
 
     # 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 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>');
         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
 
             # 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')
 
             # 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')
                 )
                 || ( !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;
             }
 
                 $content = $message->Content;
             }
 
-            my $content_type = lc $message->ContentType;
             $RT::Logger->debug(
                 "Rendering attachment #". $message->id
                 ." of '$content_type' type"
             $RT::Logger->debug(
                 "Rendering attachment #". $message->id
                 ." of '$content_type' type"
@@ -231,9 +232,8 @@ my $render_attachment = sub {
                 $m->out( $content );
             }
 
                 $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: $@" ) }
                 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
     }
 
     # 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;
         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;
     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;
     -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;
 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;
     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;
     padding-right: 0.6em;
     -moz-border-radius: 0.5em;
     -webkit-border-radius: 0.5em;
+    border-radius: 0.5em;
     background-color: #006699;
     color: #fff;
 }
     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: 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;
 }
     padding: 0.5em;
     background-color: #fff;
 }
index 794385d..1891079 100644 (file)
@@ -3,7 +3,7 @@ $title => ''
 $show_home_button => 1
 </%args>
 <%init>
 $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();
     $session{'NotMobile'} = 1;
     RT::Interface::Web::Redirect(RT->Config->Get('WebURL'));
     $m->abort();