From 0bff2e665b3a6389b47510e4c04a5a454f6dd7d4 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Sun, 23 Sep 2012 14:56:51 -0700 Subject: [PATCH] rt 4.0.7 --- rt/bin/rt | 2 +- rt/bin/rt.in | 2 +- rt/configure | 149 ++- rt/docs/web_deployment.pod | 2 +- rt/etc/initialdata | 2 +- rt/etc/schema.SQLite | 106 +- rt/etc/upgrade/3.3.0/schema.mysql | 53 +- rt/etc/upgrade/3.3.11/schema.mysql | 4 +- rt/etc/upgrade/3.9.5/schema.mysql | 24 +- rt/etc/upgrade/3.9.7/schema.mysql | 10 +- rt/lib/RT/Action/CreateTickets.pm | 3 +- rt/lib/RT/Articles.pm | 3 + rt/lib/RT/Config.pm | 6 +- rt/lib/RT/Crypt/GnuPG.pm | 1 + rt/lib/RT/Dashboard.pm | 30 + rt/lib/RT/Generated.pm | 2 +- rt/lib/RT/I18N.pm | 6 +- rt/lib/RT/Interface/Email.pm | 39 +- rt/lib/RT/Interface/Web.pm | 44 +- rt/lib/RT/Record.pm | 4 +- rt/lib/RT/Scrip.pm | 2 +- rt/lib/RT/Scrips.pm | 80 +- rt/lib/RT/Search/Googleish.pm | 16 +- rt/lib/RT/SearchBuilder.pm | 40 +- rt/lib/RT/Shredder.pm | 6 +- rt/lib/RT/Test.pm | 6 +- rt/lib/RT/Ticket.pm | 76 +- rt/lib/RT/Tickets.pm | 11 + rt/lib/RT/URI.pm | 19 + rt/lib/RT/User.pm | 2 +- rt/sbin/standalone_httpd | 2 +- rt/sbin/standalone_httpd.in | 2 +- rt/share/html/Admin/Queues/Modify.html | 2 +- rt/share/html/Approvals/Elements/PendingMyApproval | 2 +- rt/share/html/Approvals/autohandler | 9 +- rt/share/html/Dashboards/Subscription.html | 2 +- rt/share/html/Elements/ColumnMap | 8 +- rt/share/html/Elements/EditCustomField | 2 +- rt/share/html/Elements/Header | 3 +- rt/share/html/Elements/HeaderJavascript | 2 +- rt/share/html/Elements/ListActions | 2 +- rt/share/html/Elements/MessageBox | 3 +- rt/share/html/Elements/QueueSummaryByStatus | 10 +- rt/share/html/Elements/RT__CustomField/ColumnMap | 4 +- rt/share/html/Elements/SelectWatcherType | 2 +- rt/share/html/Elements/Tabs | 2 +- rt/share/html/Helpers/Autocomplete/Users | 3 + rt/share/html/NoAuth/css/aileron/boxes.css | 4 - rt/share/html/NoAuth/css/aileron/ticket.css | 13 +- rt/share/html/NoAuth/css/ballard/boxes.css | 5 + rt/share/html/NoAuth/css/ballard/layout.css | 4 + rt/share/html/NoAuth/css/ballard/nav.css | 3 + rt/share/html/NoAuth/css/ballard/ticket-search.css | 1 + rt/share/html/NoAuth/css/ballard/ticket.css | 3 + rt/share/html/NoAuth/css/base/forms.css | 1 + .../NoAuth/css/base/jquery-ui-timepicker-addon.css | 7 + rt/share/html/NoAuth/css/base/jquery-ui.css | 2 - .../NoAuth/css/base/jquery-ui.custom.modified.css | 24 + rt/share/html/NoAuth/css/base/main.css | 1 + rt/share/html/NoAuth/css/base/superfish-navbar.css | 2 + rt/share/html/NoAuth/css/base/superfish.css | 2 + rt/share/html/NoAuth/css/base/ticket-form.css | 31 +- rt/share/html/NoAuth/css/base/ui.timepickr.css | 56 - .../html/NoAuth/css/base/ui.timepickr.custom.css | 54 - rt/share/html/NoAuth/css/web2/nav.css | 1 + .../html/NoAuth/js/jquery-ui-1.8.4.custom.min.js | 50 + .../html/NoAuth/js/jquery-ui-patch-datepicker.js | 31 + .../html/NoAuth/js/jquery-ui-timepicker-addon.js | 1326 ++++++++++++++++++++ rt/share/html/NoAuth/js/ui.timepickr.js | 941 -------------- rt/share/html/NoAuth/js/util.js | 66 +- rt/share/html/Prefs/Other.html | 1 + rt/share/html/REST/1.0/Forms/ticket/default | 22 +- rt/share/html/Search/Chart.html | 8 +- rt/share/html/Search/Elements/SelectPersonType | 2 +- rt/share/html/Search/Results.html | 1 + rt/share/html/Ticket/Attachment/dhandler | 9 +- rt/share/html/Ticket/Elements/ShowMembers | 7 +- .../Ticket/Elements/ShowTransactionAttachments | 18 +- rt/share/html/m/_elements/raw_style | 4 + rt/share/html/m/_elements/wrapper | 2 +- 80 files changed, 2061 insertions(+), 1451 deletions(-) create mode 100644 rt/share/html/NoAuth/css/base/jquery-ui-timepicker-addon.css delete mode 100644 rt/share/html/NoAuth/css/base/ui.timepickr.css delete mode 100644 rt/share/html/NoAuth/css/base/ui.timepickr.custom.css create mode 100644 rt/share/html/NoAuth/js/jquery-ui-timepicker-addon.js delete mode 100644 rt/share/html/NoAuth/js/ui.timepickr.js diff --git a/rt/bin/rt b/rt/bin/rt index 32f459a7e..89873f5d6 100755 --- a/rt/bin/rt +++ b/rt/bin/rt @@ -420,7 +420,7 @@ sub show { } elsif (my $spec = is_object_spec($_, $type)) { push @objects, $spec; - $rawprint = 1 if $_ =~ /\/content$/ or $_ !~ /^ticket/; + $rawprint = 1 if $_ =~ /\/content$/ or $_ =~ /\/links/ or $_ !~ /^ticket/; } else { my $datum = /^-/ ? "option" : "argument"; diff --git a/rt/bin/rt.in b/rt/bin/rt.in index e54a07add..2a9f643c8 100644 --- a/rt/bin/rt.in +++ b/rt/bin/rt.in @@ -420,7 +420,7 @@ sub show { } elsif (my $spec = is_object_spec($_, $type)) { push @objects, $spec; - $rawprint = 1 if $_ =~ /\/content$/ or $_ !~ /^ticket/; + $rawprint = 1 if $_ =~ /\/content$/ or $_ =~ /\/links/ or $_ !~ /^ticket/; } else { my $datum = /^-/ ? "option" : "argument"; diff --git a/rt/configure b/rt/configure index 1862c5fe6..76ef85b92 100755 --- a/rt/configure +++ b/rt/configure @@ -1,7 +1,7 @@ #! /bin/sh # From configure.ac Revision. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67 for RT rt-4.0.6. +# Generated by GNU Autoconf 2.68 for RT rt-4.0.7. # # Report bugs to . # @@ -92,6 +92,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -216,11 +217,18 @@ IFS=$as_save_IFS # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : @@ -552,8 +560,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='RT' PACKAGE_TARNAME='rt' -PACKAGE_VERSION='rt-4.0.6' -PACKAGE_STRING='RT rt-4.0.6' +PACKAGE_VERSION='rt-4.0.7' +PACKAGE_STRING='RT rt-4.0.7' PACKAGE_BUGREPORT='rt-bugs@bestpractical.com' PACKAGE_URL='' @@ -1165,7 +1173,7 @@ Try \`$0 --help' for more information" $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac @@ -1303,7 +1311,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures RT rt-4.0.6 to adapt to many kinds of systems. +\`configure' configures RT rt-4.0.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1364,7 +1372,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of RT rt-4.0.6:";; + short | recursive ) echo "Configuration of RT rt-4.0.7:";; esac cat <<\_ACEOF @@ -1488,8 +1496,8 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -RT configure rt-4.0.6 -generated by GNU Autoconf 2.67 +RT configure rt-4.0.7 +generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation @@ -1535,7 +1543,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile @@ -1581,7 +1589,7 @@ fi # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link @@ -1589,8 +1597,8 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by RT $as_me rt-4.0.6, which was -generated by GNU Autoconf 2.67. Invocation command line was +It was created by RT $as_me rt-4.0.7, which was +generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -1848,7 +1856,7 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;} || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi done @@ -1946,7 +1954,7 @@ rt_version_major=4 rt_version_minor=0 -rt_version_patch=6 +rt_version_patch=7 test "x$rt_version_major" = 'x' && rt_version_major=0 test "x$rt_version_minor" = 'x' && rt_version_minor=0 @@ -1998,7 +2006,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then : +if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -2079,7 +2087,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' set dummy perl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_PERL+set}" = set; then : +if ${ac_cv_path_PERL+:} false; then : $as_echo_n "(cached) " >&6 else case $PERL in @@ -2800,7 +2808,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2840,7 +2848,7 @@ if test -z "$ac_cv_prog_CC"; then set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2893,7 +2901,7 @@ if test -z "$CC"; then set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2933,7 +2941,7 @@ if test -z "$CC"; then set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2992,7 +3000,7 @@ if test -z "$CC"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -3036,7 +3044,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -3091,7 +3099,7 @@ fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -3206,7 +3214,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -3249,7 +3257,7 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -3308,7 +3316,7 @@ $as_echo "$ac_try_echo"; } >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi fi fi @@ -3319,7 +3327,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : +if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3360,7 +3368,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -3370,7 +3378,7 @@ OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : +if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3407,7 +3415,7 @@ ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : +if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag @@ -3485,7 +3493,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no @@ -3583,7 +3591,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for aginitlib in -lgraph" >&5 $as_echo_n "checking for aginitlib in -lgraph... " >&6; } -if test "${ac_cv_lib_graph_aginitlib+set}" = set; then : +if ${ac_cv_lib_graph_aginitlib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -3617,7 +3625,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_graph_aginitlib" >&5 $as_echo "$ac_cv_lib_graph_aginitlib" >&6; } -if test "x$ac_cv_lib_graph_aginitlib" = x""yes; then : +if test "x$ac_cv_lib_graph_aginitlib" = xyes; then : RT_GRAPHVIZ="1" fi @@ -3643,7 +3651,7 @@ fi set dummy gdlib-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_RT_GD+set}" = set; then : +if ${ac_cv_prog_RT_GD+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RT_GD"; then @@ -3699,7 +3707,7 @@ fi set dummy gpg; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_RT_GPG+set}" = set; then : +if ${ac_cv_prog_RT_GPG+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RT_GPG"; then @@ -3984,10 +3992,21 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && + if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} @@ -4055,7 +4074,7 @@ LTLIBOBJS=$ac_ltlibobjs -: ${CONFIG_STATUS=./config.status} +: "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" @@ -4156,6 +4175,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -4462,8 +4482,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by RT $as_me rt-4.0.6, which was -generated by GNU Autoconf 2.67. Invocation command line was +This file was extended by RT $as_me rt-4.0.7, which was +generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -4515,8 +4535,8 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -RT config.status rt-4.0.6 -configured by $0, generated by GNU Autoconf 2.67, +RT config.status rt-4.0.7 +configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. @@ -4658,7 +4678,7 @@ do "t/data/configs/apache2.2+mod_perl.conf") CONFIG_FILES="$CONFIG_FILES t/data/configs/apache2.2+mod_perl.conf" ;; "t/data/configs/apache2.2+fastcgi.conf") CONFIG_FILES="$CONFIG_FILES t/data/configs/apache2.2+fastcgi.conf" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -4679,9 +4699,10 @@ fi # after its creation but before its name has been assigned to `$tmp'. $debug || { - tmp= + tmp= ac_tmp= trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } @@ -4689,12 +4710,13 @@ $debug || { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" + test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -4716,7 +4738,7 @@ else ac_cs_awk_cr=$ac_cr fi -echo 'BEGIN {' >"$tmp/subs1.awk" && +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF @@ -4744,7 +4766,7 @@ done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h @@ -4792,7 +4814,7 @@ t delim rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" @@ -4824,7 +4846,7 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF @@ -4864,7 +4886,7 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -4883,7 +4905,7 @@ do for ac_f do case $ac_f in - -) ac_f="$tmp/stdin";; + -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. @@ -4892,7 +4914,7 @@ do [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -4918,8 +4940,8 @@ $as_echo "$as_me: creating $ac_file" >&6;} esac case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -5049,21 +5071,22 @@ s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} - rm -f "$tmp/stdin" + rm -f "$ac_tmp/stdin" case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; diff --git a/rt/docs/web_deployment.pod b/rt/docs/web_deployment.pod index 4c3f73fb5..5d2cd4c00 100644 --- a/rt/docs/web_deployment.pod +++ b/rt/docs/web_deployment.pod @@ -23,7 +23,7 @@ to use L, a high performance preforking server: /opt/rt4/sbin/rt-server --server Starman --port 8080 B: After you run the standalone server as root, you will need to -remove your C directory, or the non-standalone servers +remove your C directory, or the non-standalone servers (Apache, etc), which run as a non-privileged user, will not be able to write to it and will not work. diff --git a/rt/etc/initialdata b/rt/etc/initialdata index cc07cec59..7ab746db1 100644 --- a/rt/etc/initialdata +++ b/rt/etc/initialdata @@ -1,4 +1,4 @@ -# Initial data for a fresh RT3 Installation. +# Initial data for a fresh RT installation. @Users = ( { Name => 'root', diff --git a/rt/etc/schema.SQLite b/rt/etc/schema.SQLite index 138971cfb..6897be2d6 100644 --- a/rt/etc/schema.SQLite +++ b/rt/etc/schema.SQLite @@ -3,7 +3,7 @@ CREATE TABLE Attachments ( id INTEGER PRIMARY KEY , TransactionId INTEGER , - Parent integer NULL , + Parent integer NULL DEFAULT 0 , MessageId varchar(160) NULL , Subject varchar(255) NULL , Filename varchar(255) NULL , @@ -11,7 +11,7 @@ CREATE TABLE Attachments ( ContentEncoding varchar(80) NULL , Content LONGTEXT NULL , Headers LONGTEXT NULL , - Creator integer NULL , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL ) ; @@ -30,12 +30,12 @@ CREATE TABLE Queues ( CommentAddress varchar(120) NULL , Lifecycle varchar(32) NULL , SubjectTag varchar(120) NULL , - InitialPriority integer NULL , - FinalPriority integer NULL , - DefaultDueIn integer NULL , - Creator integer NULL , + InitialPriority integer NULL DEFAULT 0 , + FinalPriority integer NULL DEFAULT 0 , + DefaultDueIn integer NULL DEFAULT 0 , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL , - LastUpdatedBy integer NULL , + LastUpdatedBy integer NULL DEFAULT 0 , LastUpdated DATETIME NULL , Disabled int2 NOT NULL DEFAULT 0 @@ -51,11 +51,11 @@ CREATE TABLE Links ( Base varchar(240) NULL , Target varchar(240) NULL , Type varchar(20) NOT NULL , - LocalTarget integer NULL , - LocalBase integer NULL , - LastUpdatedBy integer NULL , + LocalTarget integer NULL DEFAULT 0 , + LocalBase integer NULL DEFAULT 0 , + LastUpdatedBy integer NULL DEFAULT 0 , LastUpdated DATETIME NULL , - Creator integer NULL , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL ) ; @@ -106,9 +106,9 @@ CREATE TABLE ScripConditions ( Argument varchar(255) NULL , ApplicableTransTypes varchar(60) NULL , - Creator integer NULL , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL , - LastUpdatedBy integer NULL , + LastUpdatedBy integer NULL DEFAULT 0 , LastUpdated DATETIME NULL ) ; @@ -119,8 +119,8 @@ CREATE TABLE ScripConditions ( CREATE TABLE Transactions ( id INTEGER PRIMARY KEY , ObjectType varchar(255) NULL , - ObjectId integer NULL , - TimeTaken integer NULL , + ObjectId integer NULL DEFAULT 0 , + TimeTaken integer NULL DEFAULT 0 , Type varchar(20) NULL , Field varchar(40) NULL , OldValue varchar(255) NULL , @@ -130,7 +130,7 @@ CREATE TABLE Transactions ( NewReference integer NULL , Data varchar(255) NULL , - Creator integer NULL , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL ) ; @@ -143,19 +143,19 @@ CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); CREATE TABLE Scrips ( id INTEGER PRIMARY KEY , Description varchar(255), - ScripCondition integer NULL , - ScripAction integer NULL , + ScripCondition integer NULL DEFAULT 0 , + ScripAction integer NULL DEFAULT 0 , ConditionRules text NULL , ActionRules text NULL , CustomIsApplicableCode text NULL , CustomPrepareCode text NULL , CustomCommitCode text NULL , Stage varchar(32) NULL , - Queue integer NULL , - Template integer NULL , - Creator integer NULL , + Queue integer NULL DEFAULT 0 , + Template integer NULL DEFAULT 0 , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL , - LastUpdatedBy integer NULL , + LastUpdatedBy integer NULL DEFAULT 0 , LastUpdated DATETIME NULL ) ; @@ -167,7 +167,7 @@ CREATE TABLE ACL ( id INTEGER PRIMARY KEY , PrincipalType varchar(25) NOT NULL, - PrincipalId INTEGER, + PrincipalId INTEGER DEFAULT 0, RightName varchar(25) NOT NULL , ObjectType varchar(25) NOT NULL , ObjectId INTEGER default 0, @@ -185,8 +185,8 @@ CREATE TABLE ACL ( CREATE TABLE GroupMembers ( id INTEGER PRIMARY KEY , - GroupId integer NULL, - MemberId integer NULL, + GroupId integer NULL DEFAULT 0, + MemberId integer NULL DEFAULT 0, Creator integer NOT NULL DEFAULT 0 , Created DATETIME NULL , LastUpdatedBy integer NOT NULL DEFAULT 0 , @@ -250,9 +250,9 @@ CREATE TABLE Users ( Timezone char(50) NULL , PGPKey text NULL, - Creator integer NULL , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL , - LastUpdatedBy integer NULL , + LastUpdatedBy integer NULL DEFAULT 0 , LastUpdated DATETIME NULL ) ; @@ -270,20 +270,20 @@ CREATE INDEX Users4 ON Users (EmailAddress); CREATE TABLE Tickets ( id INTEGER PRIMARY KEY , - EffectiveId integer NULL , - Queue integer NULL , + EffectiveId integer NULL DEFAULT 0 , + Queue integer NULL DEFAULT 0 , Type varchar(16) NULL , - IssueStatement integer NULL , - Resolution integer NULL , - Owner integer NULL , + IssueStatement integer NULL DEFAULT 0 , + Resolution integer NULL DEFAULT 0 , + Owner integer NULL DEFAULT 0 , Subject varchar(200) NULL DEFAULT '[no subject]' , - InitialPriority integer NULL , - FinalPriority integer NULL , - Priority integer NULL , - TimeEstimated integer NULL , - TimeWorked integer NULL , + InitialPriority integer NULL DEFAULT 0 , + FinalPriority integer NULL DEFAULt 0 , + Priority integer NULL DEFAULT 0 , + TimeEstimated integer NULL DEFAULT 0 , + TimeWorked integer NULL DEFAULT 0 , Status varchar(64) NULL , - TimeLeft integer NULL , + TimeLeft integer NULL DEFAULT 0 , Told DATETIME NULL , Starts DATETIME NULL , Started DATETIME NULL , @@ -291,9 +291,9 @@ CREATE TABLE Tickets ( Resolved DATETIME NULL , - LastUpdatedBy integer NULL , + LastUpdatedBy integer NULL DEFAULT 0 , LastUpdated DATETIME NULL , - Creator integer NULL , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL , Disabled int2 NOT NULL DEFAULT 0 @@ -315,9 +315,9 @@ CREATE TABLE ScripActions ( Description varchar(255) NULL , ExecModule varchar(60) NULL , Argument varchar(255) NULL , - Creator integer NULL , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL , - LastUpdatedBy integer NULL , + LastUpdatedBy integer NULL DEFAULT 0 , LastUpdated DATETIME NULL ) ; @@ -333,11 +333,11 @@ CREATE TABLE Templates ( Description varchar(255) NULL , Type varchar(16) NULL , Language varchar(16) NULL , - TranslationOf integer NULL , + TranslationOf integer NULL DEFAULT 0 , Content blob NULL , LastUpdated DATETIME NULL , - LastUpdatedBy integer NULL , - Creator integer NULL , + LastUpdatedBy integer NULL DEFAULT 0 , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL ) ; @@ -437,10 +437,10 @@ CREATE TABLE Attributes ( Content LONGTEXT NULL , ContentType varchar(16), ObjectType varchar(25) NOT NULL , - ObjectId INTEGER default 0, - Creator integer NULL , + ObjectId INTEGER , + Creator integer NULL DEFAULT 0 , Created DATETIME NULL , - LastUpdatedBy integer NULL , + LastUpdatedBy integer NULL DEFAULT 0 , LastUpdated DATETIME NULL ) ; @@ -483,22 +483,22 @@ Parent integer NOT NULL DEFAULT 0, Name varchar(255) NOT NULL DEFAULT '', Description varchar(255) NOT NULL DEFAULT '', ObjectType varchar(64) NOT NULL DEFAULT '', -ObjectId integer NOT NULL +ObjectId integer NOT NULL DEFAULT 0 ); CREATE TABLE ObjectTopics ( id INTEGER PRIMARY KEY, -Topic integer NOT NULL, +Topic integer NOT NULL DEFAULT 0, ObjectType varchar(64) NOT NULL DEFAULT '', -ObjectId integer NOT NULL +ObjectId integer NOT NULL DEFAULT 0 ); CREATE TABLE ObjectClasses ( id INTEGER PRIMARY KEY, -Class integer NOT NULL, +Class integer NOT NULL DEFAULT 0, ObjectType varchar(64) NOT NULL DEFAULT '', -ObjectId integer NOT NULL, +ObjectId integer NOT NULL DEFAULT 0, Creator integer NOT NULL DEFAULT 0, Created TIMESTAMP NULL, LastUpdatedBy integer NOT NULL DEFAULT 0, diff --git a/rt/etc/upgrade/3.3.0/schema.mysql b/rt/etc/upgrade/3.3.0/schema.mysql index f6998363e..d8b04991e 100644 --- a/rt/etc/upgrade/3.3.0/schema.mysql +++ b/rt/etc/upgrade/3.3.0/schema.mysql @@ -1,37 +1,32 @@ -alter Table Transactions ADD Column (ObjectType varchar(64) not null); -update Transactions set ObjectType = 'RT::Ticket'; -alter table Transactions drop column EffectiveTicket; -alter table Transactions add column ReferenceType varchar(255) NULL; -alter table Transactions add column OldReference integer NULL; -alter table Transactions add column NewReference integer NULL; -alter table Transactions drop index transactions1; -alter table Transactions change Ticket ObjectId integer NOT NULL DEFAULT 0 ; +drop index transactions1 ON Transactions; -CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); - -alter table TicketCustomFieldValues rename ObjectCustomFieldValues; +alter Table Transactions + ADD COLUMN (ObjectType varchar(64) not null), + DROP COLUMN EffectiveTicket, + ADD COLUMN ReferenceType varchar(255) NULL, + ADD COLUMN OldReference integer NULL, + ADD COLUMN NewReference integer NULL, + CHANGE Ticket ObjectId integer NOT NULL DEFAULT 0; -alter table ObjectCustomFieldValues change Ticket ObjectId integer NOT NULL DEFAULT 0 ; +UPDATE Transactions set ObjectType = 'RT::Ticket'; +CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); -alter table ObjectCustomFieldValues add column ObjectType varchar(255) not null; +alter table TicketCustomFieldValues rename ObjectCustomFieldValues, + change Ticket ObjectId integer NOT NULL DEFAULT 0 , + add column ObjectType varchar(255) not null, + add column Current bool default 1, + add column LargeContent LONGTEXT NULL, + add column ContentType varchar(80) NULL, + add column ContentEncoding varchar(80) NULL; update ObjectCustomFieldValues set ObjectType = 'RT::Ticket'; -alter table ObjectCustomFieldValues add column Current bool default 1; - -alter table ObjectCustomFieldValues add column LargeContent LONGTEXT NULL; - -alter table ObjectCustomFieldValues add column ContentType varchar(80) NULL; - -alter table ObjectCustomFieldValues add column ContentEncoding varchar(80) NULL; - # These could fail if there's no such index and there's no "drop index if exists" syntax #alter table ObjectCustomFieldValues drop index ticketcustomfieldvalues1; #alter table ObjectCustomFieldValues drop index ticketcustomfieldvalues2; -alter table ObjectCustomFieldValues add index ObjectCustomFieldValues1 (Content); - -alter table ObjectCustomFieldValues add index ObjectCustomFieldValues2 (CustomField,ObjectType,ObjectId); +alter table ObjectCustomFieldValues add index ObjectCustomFieldValues1 (Content), + add index ObjectCustomFieldValues2 (CustomField,ObjectType,ObjectId); CREATE TABLE ObjectCustomFields ( @@ -50,10 +45,10 @@ CREATE TABLE ObjectCustomFields ( INSERT into ObjectCustomFields (id, CustomField, ObjectId, SortOrder, Creator, LastUpdatedBy) SELECT null, id, Queue, SortOrder, Creator, LastUpdatedBy from CustomFields; -alter table CustomFields add column LookupType varchar(255) NOT NULL; -alter table CustomFields add column Repeated int2 NOT NULL DEFAULT 0 ; -alter table CustomFields add column Pattern varchar(255) NULL; -alter table CustomFields add column MaxValues integer; +alter table CustomFields add column LookupType varchar(255) NOT NULL, + add column Repeated int2 NOT NULL DEFAULT 0 , + add column Pattern varchar(255) NULL, + add column MaxValues integer; # See above # alter table CustomFields drop index CustomFields1; @@ -62,4 +57,4 @@ UPDATE CustomFields SET MaxValues = 1 WHERE Type LIKE '%Single'; UPDATE CustomFields SET Type = 'Select' WHERE Type LIKE 'Select%'; UPDATE CustomFields SET Type = 'Freeform' WHERE Type LIKE 'Freeform%'; UPDATE CustomFields Set LookupType = 'RT::Queue-RT::Ticket'; -alter table CustomFields drop column Queue; +alter table CustomFields drop column Queue; diff --git a/rt/etc/upgrade/3.3.11/schema.mysql b/rt/etc/upgrade/3.3.11/schema.mysql index cc35d40f2..eff84783f 100644 --- a/rt/etc/upgrade/3.3.11/schema.mysql +++ b/rt/etc/upgrade/3.3.11/schema.mysql @@ -1,5 +1,5 @@ -ALTER TABLE ObjectCustomFieldValues ADD COLUMN SortOrder INTEGER NOT NULL DEFAULT 0; -ALTER TABLE ObjectCustomFieldValues ADD COLUMN Disabled int2 NOT NULL DEFAULT 0; +ALTER TABLE ObjectCustomFieldValues ADD COLUMN SortOrder INTEGER NOT NULL DEFAULT 0, + ADD COLUMN Disabled int2 NOT NULL DEFAULT 0; UPDATE ObjectCustomFieldValues SET Disabled = 1 WHERE Current = 0; ALTER TABLE ObjectCustomFieldValues DROP COLUMN Current; diff --git a/rt/etc/upgrade/3.9.5/schema.mysql b/rt/etc/upgrade/3.9.5/schema.mysql index 4bd0907c0..fe5018c78 100644 --- a/rt/etc/upgrade/3.9.5/schema.mysql +++ b/rt/etc/upgrade/3.9.5/schema.mysql @@ -6,15 +6,15 @@ AND CustomFieldValues.id = Attributes.ObjectId); DELETE FROM Attributes WHERE Name = 'Category' AND ObjectType = 'RT::CustomFieldValue'; -ALTER TABLE Groups ADD COLUMN Creator integer NOT NULL DEFAULT 0; -ALTER TABLE Groups ADD COLUMN Created DATETIME NULL; -ALTER TABLE Groups ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; -ALTER TABLE Groups ADD COLUMN LastUpdated DATETIME NULL; -ALTER TABLE GroupMembers ADD COLUMN Creator integer NOT NULL DEFAULT 0; -ALTER TABLE GroupMembers ADD COLUMN Created DATETIME NULL; -ALTER TABLE GroupMembers ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; -ALTER TABLE GroupMembers ADD COLUMN LastUpdated DATETIME NULL; -ALTER TABLE ACL ADD COLUMN Creator integer NOT NULL DEFAULT 0; -ALTER TABLE ACL ADD COLUMN Created DATETIME NULL; -ALTER TABLE ACL ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; -ALTER TABLE ACL ADD COLUMN LastUpdated DATETIME NULL; +ALTER TABLE Groups ADD COLUMN Creator integer NOT NULL DEFAULT 0, + ADD COLUMN Created DATETIME NULL, + ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0, + ADD COLUMN LastUpdated DATETIME NULL; +ALTER TABLE GroupMembers ADD COLUMN Creator integer NOT NULL DEFAULT 0, + ADD COLUMN Created DATETIME NULL, + ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0, + ADD COLUMN LastUpdated DATETIME NULL; +ALTER TABLE ACL ADD COLUMN Creator integer NOT NULL DEFAULT 0, + ADD COLUMN Created DATETIME NULL, + ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0, + ADD COLUMN LastUpdated DATETIME NULL; diff --git a/rt/etc/upgrade/3.9.7/schema.mysql b/rt/etc/upgrade/3.9.7/schema.mysql index 1be165647..4cbed6cc7 100644 --- a/rt/etc/upgrade/3.9.7/schema.mysql +++ b/rt/etc/upgrade/3.9.7/schema.mysql @@ -1,6 +1,6 @@ ALTER TABLE Users ADD COLUMN AuthToken VARCHAR(16) CHARACTER SET ascii NULL; -ALTER TABLE CustomFields ADD COLUMN BasedOn INTEGER NULL; -ALTER TABLE CustomFields ADD COLUMN RenderType VARCHAR(64) NULL; -ALTER TABLE CustomFields ADD COLUMN ValuesClass VARCHAR(64) CHARACTER SET ascii NULL; -ALTER TABLE Queues ADD COLUMN SubjectTag VARCHAR(120) NULL; -ALTER TABLE Queues ADD COLUMN Lifecycle VARCHAR(32) NULL; +ALTER TABLE CustomFields ADD COLUMN BasedOn INTEGER NULL, + ADD COLUMN RenderType VARCHAR(64) NULL, + ADD COLUMN ValuesClass VARCHAR(64) CHARACTER SET ascii NULL; +ALTER TABLE Queues ADD COLUMN SubjectTag VARCHAR(120) NULL, + ADD COLUMN Lifecycle VARCHAR(32) NULL; diff --git a/rt/lib/RT/Action/CreateTickets.pm b/rt/lib/RT/Action/CreateTickets.pm index 31489c8ff..efd2bdaf6 100644 --- a/rt/lib/RT/Action/CreateTickets.pm +++ b/rt/lib/RT/Action/CreateTickets.pm @@ -567,7 +567,8 @@ sub Parse { $self->_ParseMultilineTemplate(%args); } elsif ( $args{'Content'} =~ /(?:\t|,)/i ) { $self->_ParseXSVTemplate(%args); - + } else { + RT->Logger->error("Invalid Template Content (Couldn't find ===, and is not a csv/tsv template) - unable to parse: $args{Content}"); } } diff --git a/rt/lib/RT/Articles.pm b/rt/lib/RT/Articles.pm index 8dd661d2e..47d0ebea2 100644 --- a/rt/lib/RT/Articles.pm +++ b/rt/lib/RT/Articles.pm @@ -360,6 +360,7 @@ sub LimitCustomField { QUOTEVALUE => $args{'QUOTEVALUE'}, ENTRYAGGREGATOR => 'AND', #$args{'ENTRYAGGREGATOR'}, SUBCLAUSE => $clause, + CASESENSITIVE => 0, ); $self->SUPER::Limit( ALIAS => $ObjectValuesAlias, @@ -380,6 +381,7 @@ sub LimitCustomField { QUOTEVALUE => $args{'QUOTEVALUE'}, ENTRYAGGREGATOR => $args{'ENTRYAGGREGATOR'}, SUBCLAUSE => $clause, + CASESENSITIVE => 0, ); $self->SUPER::Limit( ALIAS => $ObjectValuesAlias, @@ -389,6 +391,7 @@ sub LimitCustomField { QUOTEVALUE => $args{'QUOTEVALUE'}, ENTRYAGGREGATOR => $args{'ENTRYAGGREGATOR'}, SUBCLAUSE => $clause, + CASESENSITIVE => 0, ); } } diff --git a/rt/lib/RT/Config.pm b/rt/lib/RT/Config.pm index f87ef84c9..014c76468 100644 --- a/rt/lib/RT/Config.pm +++ b/rt/lib/RT/Config.pm @@ -411,8 +411,8 @@ our %META = ( Description => q|What tickets to display in the 'More about requestor' box|, #loc Values => [qw(Active Inactive All None)], ValuesLabel => { - Active => "Show the Requestor's 10 highest priority open tickets", #loc - Inactive => "Show the Requestor's 10 highest priority closed tickets", #loc + Active => "Show the Requestor's 10 highest priority active tickets", #loc + Inactive => "Show the Requestor's 10 highest priority inactive tickets", #loc All => "Show the Requestor's 10 highest priority tickets", #loc None => "Show no tickets for the Requestor", #loc }, @@ -749,7 +749,7 @@ our %META = ( my %seen; foreach my $encoding ( grep defined && length, splice @$value ) { - next if $seen{ $encoding }++; + next if $seen{ $encoding }; if ( $encoding eq '*' ) { unshift @$value, '*'; next; diff --git a/rt/lib/RT/Crypt/GnuPG.pm b/rt/lib/RT/Crypt/GnuPG.pm index ab444d068..c5fb12bef 100644 --- a/rt/lib/RT/Crypt/GnuPG.pm +++ b/rt/lib/RT/Crypt/GnuPG.pm @@ -1683,6 +1683,7 @@ my %ignore_keyword = map { $_ => 1 } qw( BEGIN_ENCRYPTION SIG_ID VALIDSIG ENC_TO BEGIN_DECRYPTION END_DECRYPTION GOODMDC TRUST_UNDEFINED TRUST_NEVER TRUST_MARGINAL TRUST_FULLY TRUST_ULTIMATE + DECRYPTION_INFO ); sub ParseStatus { diff --git a/rt/lib/RT/Dashboard.pm b/rt/lib/RT/Dashboard.pm index 14ffa6ad3..2e2bbc489 100644 --- a/rt/lib/RT/Dashboard.pm +++ b/rt/lib/RT/Dashboard.pm @@ -454,6 +454,36 @@ sub CurrentUserCanCreateAny { return 0; } +=head2 Delete + +Deletes the dashboard and related subscriptions. +Returns a tuple of status and message, where status is true upon success. + +=cut + +sub Delete { + my $self = shift; + my $id = $self->id; + my ( $status, $msg ) = $self->SUPER::Delete(@_); + if ( $status ) { + # delete all the subscriptions + my $subscriptions = RT::Attributes->new( RT->SystemUser ); + $subscriptions->Limit( + FIELD => 'Name', + VALUE => 'Subscription', + ); + $subscriptions->Limit( + FIELD => 'Description', + VALUE => "Subscription to dashboard $id", + ); + while ( my $subscription = $subscriptions->Next ) { + $subscription->Delete(); + } + } + + return ( $status, $msg ); +} + RT::Base->_ImportOverlays(); 1; diff --git a/rt/lib/RT/Generated.pm b/rt/lib/RT/Generated.pm index 2abcf3b6e..9fd946f5b 100644 --- a/rt/lib/RT/Generated.pm +++ b/rt/lib/RT/Generated.pm @@ -50,7 +50,7 @@ package RT; use warnings; use strict; -our $VERSION = '4.0.6'; +our $VERSION = '4.0.7'; diff --git a/rt/lib/RT/I18N.pm b/rt/lib/RT/I18N.pm index cadf7cc7c..e453cfa04 100644 --- a/rt/lib/RT/I18N.pm +++ b/rt/lib/RT/I18N.pm @@ -227,7 +227,7 @@ sub SetMIMEEntityToEncoding { my $body = $entity->bodyhandle; - if ( $enc ne $charset && $body ) { + if ( $body && ($enc ne $charset || $enc =~ /^utf-?8(?:-strict)?$/i) ) { my $string = $body->as_string or return; $RT::Logger->debug( "Converting '$charset' to '$enc' for " @@ -335,7 +335,7 @@ sub DecodeMIMEWordsToEncoding { } # now we have got a decoded subject, try to convert into the encoding - unless ( $charset eq $to_charset ) { + if ( $charset ne $to_charset || $charset =~ /^utf-?8(?:-strict)?$/i ) { Encode::from_to( $enc_str, $charset, $to_charset ); } @@ -537,7 +537,7 @@ sub SetMIMEHeadToEncoding { my @values = $head->get_all($tag); $head->delete($tag); foreach my $value (@values) { - if ( $charset ne $enc ) { + if ( $charset ne $enc || $enc =~ /^utf-?8(?:-strict)?$/i ) { Encode::_utf8_off($value); Encode::from_to( $value, $charset => $enc ); } diff --git a/rt/lib/RT/Interface/Email.pm b/rt/lib/RT/Interface/Email.pm index 02a1ec0c0..4c3ee9986 100755 --- a/rt/lib/RT/Interface/Email.pm +++ b/rt/lib/RT/Interface/Email.pm @@ -787,7 +787,7 @@ sub GetForwardFrom { my $ticket = $args{Ticket} || $txn->Object; if ( RT->Config->Get('ForwardFromUser') ) { - return ( $txn || $ticket )->CurrentUser->UserObj->EmailAddress; + return ( $txn || $ticket )->CurrentUser->EmailAddress; } else { return $ticket->QueueObj->CorrespondAddress @@ -1221,8 +1221,16 @@ sub SetInReplyTo { if @references > 10; my $mail = $args{'Message'}; - $mail->head->set( 'In-Reply-To' => join ' ', @rtid? (@rtid) : (@id) ) if @id || @rtid; - $mail->head->set( 'References' => join ' ', @references ); + $mail->head->set( 'In-Reply-To' => Encode::encode_utf8(join ' ', @rtid? (@rtid) : (@id)) ) if @id || @rtid; + $mail->head->set( 'References' => Encode::encode_utf8(join ' ', @references) ); +} + +sub ExtractTicketId { + my $entity = shift; + + my $subject = $entity->head->get('Subject') || ''; + chomp $subject; + return ParseTicketId( $subject ); } sub ParseTicketId { @@ -1448,7 +1456,7 @@ sub Gateway { } # }}} - $args{'ticket'} ||= ParseTicketId( $Subject ); + $args{'ticket'} ||= ExtractTicketId( $Message ); $SystemTicket = RT::Ticket->new( RT->SystemUser ); $SystemTicket->Load( $args{'ticket'} ) if ( $args{'ticket'} ) ; @@ -1704,17 +1712,20 @@ sub _RunUnsafeAction { return ( 0, "Ticket not taken" ); } } elsif ( $args{'Action'} =~ /^resolve$/i ) { - my ( $status, $msg ) = $args{'Ticket'}->SetStatus('resolved'); - unless ($status) { + my $new_status = $args{'Ticket'}->FirstInactiveStatus; + if ($new_status) { + my ( $status, $msg ) = $args{'Ticket'}->SetStatus($new_status); + unless ($status) { - #Warn the sender that we couldn't actually submit the comment. - MailError( - To => $args{'ErrorsTo'}, - Subject => "Ticket not resolved", - Explanation => $msg, - MIMEObj => $args{'Message'} - ); - return ( 0, "Ticket not resolved" ); + #Warn the sender that we couldn't actually submit the comment. + MailError( + To => $args{'ErrorsTo'}, + Subject => "Ticket not resolved", + Explanation => $msg, + MIMEObj => $args{'Message'} + ); + return ( 0, "Ticket not resolved" ); + } } } else { return ( 0, "Not supported unsafe action $args{'Action'}", $args{'Ticket'} ); diff --git a/rt/lib/RT/Interface/Web.pm b/rt/lib/RT/Interface/Web.pm index 94da3072d..1aae7581e 100644 --- a/rt/lib/RT/Interface/Web.pm +++ b/rt/lib/RT/Interface/Web.pm @@ -261,7 +261,15 @@ sub HandleRequest { $HTML::Mason::Commands::m->comp( '/Elements/SetupSessionCookie', %$ARGS ); SendSessionCookie(); - $HTML::Mason::Commands::session{'CurrentUser'} = RT::CurrentUser->new() unless _UserLoggedIn(); + + if ( _UserLoggedIn() ) { + # make user info up to date + $HTML::Mason::Commands::session{'CurrentUser'} + ->Load( $HTML::Mason::Commands::session{'CurrentUser'}->id ); + } + else { + $HTML::Mason::Commands::session{'CurrentUser'} = RT::CurrentUser->new(); + } # Process session-related callbacks before any auth attempts $HTML::Mason::Commands::m->callback( %$ARGS, CallbackName => 'Session', CallbackPage => '/autohandler' ); @@ -287,7 +295,7 @@ sub HandleRequest { my $m = $HTML::Mason::Commands::m; # REST urls get a special 401 response - if ($m->request_comp->path =~ '^/REST/\d+\.\d+/') { + if ($m->request_comp->path =~ m{^/REST/\d+\.\d+/}) { $HTML::Mason::Commands::r->content_type("text/plain"); $m->error_format("text"); $m->out("RT/$RT::VERSION 401 Credentials required\n"); @@ -457,7 +465,7 @@ sub MaybeShowInstallModePage { my $m = $HTML::Mason::Commands::m; if ( $m->base_comp->path =~ RT->Config->Get('WebNoAuthRegex') ) { $m->call_next(); - } elsif ( $m->request_comp->path !~ '^(/+)Install/' ) { + } elsif ( $m->request_comp->path !~ m{^(/+)Install/} ) { RT::Interface::Web::Redirect( RT->Config->Get('WebURL') . "Install/index.html" ); } else { $m->call_next(); @@ -557,7 +565,7 @@ sub ShowRequestedPage { unless ( $HTML::Mason::Commands::session{'CurrentUser'}->Privileged ) { # if the user is trying to access a ticket, redirect them - if ( $m->request_comp->path =~ '^(/+)Ticket/Display.html' && $ARGS->{'id'} ) { + if ( $m->request_comp->path =~ m{^(/+)Ticket/Display.html} && $ARGS->{'id'} ) { RT::Interface::Web::Redirect( RT->Config->Get('WebURL') . "SelfService/Display.html?id=" . $ARGS->{'id'} ); } @@ -659,7 +667,7 @@ sub AttemptExternalAuth { delete $HTML::Mason::Commands::session{'CurrentUser'}; $user = $orig_user; - if ( RT->Config->Get('WebExternalOnly') ) { + unless ( RT->Config->Get('WebFallbackToInternalAuth') ) { TangentForLoginWithError('You are not an authorized user'); } } @@ -970,7 +978,7 @@ sub MobileClient { my $self = shift; -if (($ENV{'HTTP_USER_AGENT'} || '') =~ /(?:hiptop|Blazer|Novarra|Vagabond|SonyEricsson|Symbian|NetFront|UP.Browser|UP.Link|Windows CE|MIDP|J2ME|DoCoMo|J-PHONE|PalmOS|PalmSource|iPhone|iPod|AvantGo|Nokia|Android|WebOS|S60)/io && !$HTML::Mason::Commands::session{'NotMobile'}) { +if (($ENV{'HTTP_USER_AGENT'} || '') =~ /(?:hiptop|Blazer|Novarra|Vagabond|SonyEricsson|Symbian|NetFront|UP.Browser|UP.Link|Windows CE|MIDP|J2ME|DoCoMo|J-PHONE|PalmOS|PalmSource|iPhone|iPod|AvantGo|Nokia|Android|WebOS|S60|Mobile)/io && !$HTML::Mason::Commands::session{'NotMobile'}) { return 1; } else { return undef; @@ -1183,6 +1191,14 @@ our %is_whitelisted_component = ( # information for the search. Because it's a straight-up read, in # addition to embedding its own auth, it's fine. '/NoAuth/rss/dhandler' => 1, + + # While these can be used for denial-of-service against RT + # (construct a very inefficient query and trick lots of users into + # running them against RT) it's incredibly useful to be able to link + # to a search result or bookmark a result page. + '/Search/Results.html' => 1, + '/Search/Simple.html' => 1, + '/m/tickets/search' => 1, ); sub IsCompCSRFWhitelisted { @@ -1237,7 +1253,19 @@ sub IsRefererCSRFWhitelisted { my $configs; for my $config ( $base_url, RT->Config->Get('ReferrerWhitelist') ) { push @$configs,$config; - return 1 if $referer->host_port eq $config; + + my $host_port = $referer->host_port; + if ($config =~ /\*/) { + # Turn a literal * into a domain component or partial component match. + # Refer to http://tools.ietf.org/html/rfc2818#page-5 + my $regex = join "[a-zA-Z0-9\-]*", + map { quotemeta($_) } + split /\*/, $config; + + return 1 if $host_port =~ /^$regex$/i; + } else { + return 1 if $host_port eq $config; + } } return (0,$referer,$configs); @@ -1962,7 +1990,7 @@ sub MakeMIMEEntity { ); my $Message = MIME::Entity->build( Type => 'multipart/mixed', - "Message-Id" => RT::Interface::Email::GenMessageId, + "Message-Id" => Encode::encode_utf8( RT::Interface::Email::GenMessageId ), map { $_ => Encode::encode_utf8( $args{ $_} ) } grep defined $args{$_}, qw(Subject From Cc) ); diff --git a/rt/lib/RT/Record.pm b/rt/lib/RT/Record.pm index e134178be..fd238de16 100755 --- a/rt/lib/RT/Record.pm +++ b/rt/lib/RT/Record.pm @@ -639,6 +639,8 @@ sub __Value { my $value = $self->SUPER::__Value($field); + return undef if (!defined $value); + if ( $args{'decode_utf8'} ) { if ( !utf8::is_utf8($value) ) { utf8::decode($value); @@ -1675,7 +1677,7 @@ sub _AddCustomFieldValue { 0, $self->loc( "Custom field [_1] does not apply to this object", - $args{'Field'} + ref $args{'Field'} ? $args{'Field'}->id : $args{'Field'} ) ); } diff --git a/rt/lib/RT/Scrip.pm b/rt/lib/RT/Scrip.pm index 950661624..8f97e747f 100755 --- a/rt/lib/RT/Scrip.pm +++ b/rt/lib/RT/Scrip.pm @@ -545,7 +545,7 @@ sub _Set { } } - return $self->__Set(@_); + return $self->SUPER::_Set(@_); } diff --git a/rt/lib/RT/Scrips.pm b/rt/lib/RT/Scrips.pm index 13a4b7d7d..fa33f7ec7 100755 --- a/rt/lib/RT/Scrips.pm +++ b/rt/lib/RT/Scrips.pm @@ -178,16 +178,6 @@ Commit all of this object's prepared scrips sub Commit { my $self = shift; - # RT::Scrips->_SetupSourceObjects will clobber - # the CurrentUser, but we need to keep this ticket - # so that the _TransactionBatch cache is maintained - # and doesn't run twice. sigh. - $self->_StashCurrentUser( TicketObj => $self->{TicketObj} ) if $self->{TicketObj}; - - #We're really going to need a non-acled ticket for the scrips to work - $self->_SetupSourceObjects( TicketObj => $self->{'TicketObj'}, - TransactionObj => $self->{'TransactionObj'} ); - foreach my $scrip (@{$self->Prepared}) { $RT::Logger->debug( "Committing scrip #". $scrip->id @@ -199,8 +189,6 @@ sub Commit { TransactionObj => $self->{'TransactionObj'} ); } - # Apply the bandaid. - $self->_RestoreCurrentUser( TicketObj => $self->{TicketObj} ) if $self->{TicketObj}; } @@ -221,12 +209,6 @@ sub Prepare { Type => undef, @_ ); - # RT::Scrips->_SetupSourceObjects will clobber - # the CurrentUser, but we need to keep this ticket - # so that the _TransactionBatch cache is maintained - # and doesn't run twice. sigh. - $self->_StashCurrentUser( TicketObj => $args{TicketObj} ) if $args{TicketObj}; - #We're really going to need a non-acled ticket for the scrips to work $self->_SetupSourceObjects( TicketObj => $args{'TicketObj'}, Ticket => $args{'Ticket'}, @@ -259,10 +241,6 @@ sub Prepare { } - # Apply the bandaid. - $self->_RestoreCurrentUser( TicketObj => $args{TicketObj} ) if $args{TicketObj}; - - return (@{$self->Prepared}); }; @@ -279,40 +257,6 @@ sub Prepared { return ($self->{'prepared_scrips'} || []); } -=head2 _StashCurrentUser TicketObj => RT::Ticket - -Saves aside the current user of the original ticket that was passed to these scrips. -This is used to make sure that we don't accidentally leak the RT_System current user -back to the calling code. - -=cut - -sub _StashCurrentUser { - my $self = shift; - my %args = @_; - - $self->{_TicketCurrentUser} = $args{TicketObj}->CurrentUser; -} - -=head2 _RestoreCurrentUser TicketObj => RT::Ticket - -Uses the current user saved by _StashCurrentUser to reset a Ticket object -back to the caller's current user and avoid leaking an RT_System ticket to -calling code. - -=cut - -sub _RestoreCurrentUser { - my $self = shift; - my %args = @_; - unless ( $self->{_TicketCurrentUser} ) { - RT->Logger->debug("Called _RestoreCurrentUser without a stashed current user object"); - return; - } - $args{TicketObj}->CurrentUser($self->{_TicketCurrentUser}); - -} - =head2 _SetupSourceObjects { TicketObj , Ticket, Transaction, TransactionObj } Setup a ticket and transaction for this Scrip collection to work with as it runs through the @@ -334,14 +278,22 @@ sub _SetupSourceObjects { @_ ); - if ( $self->{'TicketObj'} = $args{'TicketObj'} ) { - # This clobbers the passed in TicketObj by turning it into one - # whose current user is RT_System. Anywhere in the Web UI - # currently calling into this is thus susceptable to a privilege - # leak; the only current call site is ->Apply, which bandaids - # over the top of this by re-asserting the CurrentUser - # afterwards. - $self->{'TicketObj'}->CurrentUser( $self->CurrentUser ); + if ( $args{'TicketObj'} ) { + # This loads a clean copy of the Ticket object to ensure that we + # don't accidentally escalate the privileges of the passed in + # ticket (this function can be invoked from the UI). + # We copy the TransactionBatch transactions so that Scrips + # running against the new Ticket will have access to them. We + # use RanTransactionBatch to guard against running + # TransactionBatch Scrips more than once. + $self->{'TicketObj'} = RT::Ticket->new( $self->CurrentUser ); + $self->{'TicketObj'}->Load( $args{'TicketObj'}->Id ); + if ( $args{'TicketObj'}->TransactionBatch ) { + # try to ensure that we won't infinite loop if something dies, triggering DESTROY while + # we have the _TransactionBatch objects; + $self->{'TicketObj'}->RanTransactionBatch(1); + $self->{'TicketObj'}->{'_TransactionBatch'} = $args{'TicketObj'}->{'_TransactionBatch'}; + } } else { $self->{'TicketObj'} = RT::Ticket->new( $self->CurrentUser ); diff --git a/rt/lib/RT/Search/Googleish.pm b/rt/lib/RT/Search/Googleish.pm index a1254836a..1b4071f4d 100644 --- a/rt/lib/RT/Search/Googleish.pm +++ b/rt/lib/RT/Search/Googleish.pm @@ -110,7 +110,7 @@ sub QueryToSQL { (\w+) # A straight word (?:\. # With an optional .foo ($RE{delimited}{-delim=>q['"]} - |\w+ + |[\w-]+ # Allow \w + dashes ) # Which could be ."foo bar", too )? ) @@ -225,6 +225,11 @@ sub GuessType { return "default"; } +# $_[0] is $self +# $_[1] is escaped value without surrounding single quotes +# $_[2] is a boolean of "was quoted by the user?" +# ensure this is false before you do smart matching like $_[1] eq "me" +# $_[3] is escaped subkey, if any (see HandleCf) sub HandleDefault { return subject => "Subject LIKE '$_[1]'"; } sub HandleSubject { return subject => "Subject LIKE '$_[1]'"; } sub HandleFulltext { return content => "Content LIKE '$_[1]'"; } @@ -242,7 +247,14 @@ sub HandleStatus { } } sub HandleOwner { - return owner => (!$_[2] and $_[1] eq "me") ? "Owner.id = '__CurrentUser__'" : "Owner = '$_[1]'"; + if (!$_[2] and $_[1] eq "me") { + return owner => "Owner.id = '__CurrentUser__'"; + } + elsif (!$_[2] and $_[1] =~ /\w+@\w+/) { + return owner => "Owner.EmailAddress = '$_[1]'"; + } else { + return owner => "Owner = '$_[1]'"; + } } sub HandleWatcher { return watcher => (!$_[2] and $_[1] eq "me") ? "Watcher.id = '__CurrentUser__'" : "Watcher = '$_[1]'"; diff --git a/rt/lib/RT/SearchBuilder.pm b/rt/lib/RT/SearchBuilder.pm index 3e9855110..4278f7587 100644 --- a/rt/lib/RT/SearchBuilder.pm +++ b/rt/lib/RT/SearchBuilder.pm @@ -211,29 +211,35 @@ sub LimitCustomField { @_ ); my $alias = $self->Join( - TYPE => 'left', - ALIAS1 => 'main', - FIELD1 => 'id', - TABLE2 => 'ObjectCustomFieldValues', - FIELD2 => 'ObjectId' + TYPE => 'left', + ALIAS1 => 'main', + FIELD1 => 'id', + TABLE2 => 'ObjectCustomFieldValues', + FIELD2 => 'ObjectId' ); $self->Limit( - ALIAS => $alias, - FIELD => 'CustomField', - OPERATOR => '=', - VALUE => $args{'CUSTOMFIELD'}, + ALIAS => $alias, + FIELD => 'CustomField', + OPERATOR => '=', + VALUE => $args{'CUSTOMFIELD'}, ) if ($args{'CUSTOMFIELD'}); $self->Limit( - ALIAS => $alias, - FIELD => 'ObjectType', - OPERATOR => '=', - VALUE => $self->_SingularClass, + ALIAS => $alias, + FIELD => 'ObjectType', + OPERATOR => '=', + VALUE => $self->_SingularClass, ); $self->Limit( - ALIAS => $alias, - FIELD => 'Content', - OPERATOR => $args{'OPERATOR'}, - VALUE => $args{'VALUE'}, + ALIAS => $alias, + FIELD => 'Content', + OPERATOR => $args{'OPERATOR'}, + VALUE => $args{'VALUE'}, + ); + $self->Limit( + ALIAS => $alias, + FIELD => 'Disabled', + OPERATOR => '=', + VALUE => 0, ); } diff --git a/rt/lib/RT/Shredder.pm b/rt/lib/RT/Shredder.pm index 40c73b36d..4f96e162d 100644 --- a/rt/lib/RT/Shredder.pm +++ b/rt/lib/RT/Shredder.pm @@ -539,9 +539,9 @@ sub WipeoutAll { my $self = $_[0]; - while ( my ($k, $v) = each %{ $self->{'cache'} } ) { - next if $v->{'State'} & (WIPED | IN_WIPING); - $self->Wipeout( Object => $v->{'Object'} ); + foreach my $cache_val ( values %{ $self->{'cache'} } ) { + next if $cache_val->{'State'} & (WIPED | IN_WIPING); + $self->Wipeout( Object => $cache_val->{'Object'} ); } } diff --git a/rt/lib/RT/Test.pm b/rt/lib/RT/Test.pm index 7d69dd60d..3e7c910ec 100644 --- a/rt/lib/RT/Test.pm +++ b/rt/lib/RT/Test.pm @@ -131,14 +131,14 @@ sub import { if (RT->Config->Get('DevelMode')) { require Module::Refresh; } - $class->bootstrap_db( %args ); - RT::InitPluginPaths(); + RT::InitClasses(); + + $class->bootstrap_db( %args ); __reconnect_rt() unless $args{nodb}; - RT::InitClasses(); RT::InitLogging(); RT->Plugins; diff --git a/rt/lib/RT/Ticket.pm b/rt/lib/RT/Ticket.pm index 00f88b657..577c44429 100755 --- a/rt/lib/RT/Ticket.pm +++ b/rt/lib/RT/Ticket.pm @@ -1124,7 +1124,7 @@ sub AddWatcher { return (0, $self->loc("Couldn't parse address from '[_1]' string", $args{'Email'} )) unless $addr; - if ( lc $self->CurrentUser->UserObj->EmailAddress + if ( lc $self->CurrentUser->EmailAddress eq lc RT::User->CanonicalizeEmailAddress( $addr->address ) ) { $args{'PrincipalId'} = $self->CurrentUser->id; @@ -1305,7 +1305,7 @@ sub DeleteWatcher { } } else { - $RT::Logger->warn("$self -> DeleteWatcher got passed a bogus type"); + $RT::Logger->warning("$self -> DeleteWatcher got passed a bogus type"); return ( 0, $self->loc('Error in parameters to Ticket->DeleteWatcher') ); } @@ -1989,6 +1989,31 @@ sub FirstActiveStatus { return $next; } +=head2 FirstInactiveStatus + +Returns the first inactive status that the ticket could transition to, +according to its current Queue's lifecycle. May return undef if there +is no such possible status to transition to, or we are already in it. +This is used in resolve action in UnsafeEmailCommands, for instance. + +=cut + +sub FirstInactiveStatus { + my $self = shift; + + my $lifecycle = $self->QueueObj->Lifecycle; + my $status = $self->Status; + my @inactive = $lifecycle->Inactive; + # no change if no inactive statuses in the lifecycle + return undef unless @inactive; + + # no change if the ticket is already has first status from the list of inactive + return undef if lc $status eq lc $inactive[0]; + + my ($next) = grep $lifecycle->IsInactive($_), $lifecycle->Transitions($status); + return $next; +} + =head2 SetStarted Takes a date in ISO format or undef @@ -2315,7 +2340,9 @@ sub _RecordNote { my $msgid = $args{'MIMEObj'}->head->get('Message-ID'); unless (defined $msgid && $msgid =~ /<(rt-.*?-\d+-\d+)\.(\d+-0-0)\@\Q$org\E>/) { $args{'MIMEObj'}->head->set( - 'RT-Message-ID' => RT::Interface::Email::GenMessageId( Ticket => $self ) + 'RT-Message-ID' => Encode::encode_utf8( + RT::Interface::Email::GenMessageId( Ticket => $self ) + ) ); } @@ -3340,6 +3367,28 @@ sub SeenUpTo { return $txns->First; } +=head2 RanTransactionBatch + +Acts as a guard around running TransactionBatch scrips. + +Should be false until you enter the code that runs TransactionBatch scrips + +Accepts an optional argument to indicate that TransactionBatch Scrips should no longer be run on this object. + +=cut + +sub RanTransactionBatch { + my $self = shift; + my $val = shift; + + if ( defined $val ) { + return $self->{_RanTransactionBatch} = $val; + } else { + return $self->{_RanTransactionBatch}; + } + +} + =head2 TransactionBatch @@ -3376,6 +3425,22 @@ sub ApplyTransactionBatch { sub _ApplyTransactionBatch { my $self = shift; + + return if $self->RanTransactionBatch; + $self->RanTransactionBatch(1); + + my $still_exists = RT::Ticket->new( RT->SystemUser ); + $still_exists->Load( $self->Id ); + if (not $still_exists->Id) { + # The ticket has been removed from the database, but we still + # have pending TransactionBatch txns for it. Unfortunately, + # because it isn't in the DB anymore, attempting to run scrips + # on it may produce unpredictable results; simply drop the + # batched transactions. + $RT::Logger->warning("TransactionBatch was fired on a ticket that no longer exists; unable to run scrips! Call ->ApplyTransactionBatch before shredding the ticket, for consistent results."); + return; + } + my $batch = $self->TransactionBatch; my %seen; @@ -3423,10 +3488,7 @@ sub DESTROY { return; } - my $batch = $self->TransactionBatch; - return unless $batch && @$batch; - - return $self->_ApplyTransactionBatch; + return $self->ApplyTransactionBatch; } diff --git a/rt/lib/RT/Tickets.pm b/rt/lib/RT/Tickets.pm index 485d7df53..c9986f41e 100755 --- a/rt/lib/RT/Tickets.pm +++ b/rt/lib/RT/Tickets.pm @@ -436,6 +436,10 @@ sub _LinkLimit { my $is_null = 0; $is_null = 1 if !$value || $value =~ /^null$/io; + unless ($is_null) { + $value = RT::URI->new( $sb->CurrentUser )->CanonicalizeURI( $value ); + } + my $direction = $meta->[1] || ''; my ($matchfield, $linkfield) = ('', ''); if ( $direction eq 'To' ) { @@ -1651,6 +1655,7 @@ sub _CustomFieldLimit { FIELD => $column, OPERATOR => $op, VALUE => $value, + CASESENSITIVE => 0, %rest ) ); $self->_CloseParen; @@ -1713,6 +1718,7 @@ sub _CustomFieldLimit { FIELD => 'Content', OPERATOR => $op, VALUE => $value, + CASESENSITIVE => 0, %rest ); } @@ -1739,6 +1745,7 @@ sub _CustomFieldLimit { OPERATOR => $op, VALUE => $value, ENTRYAGGREGATOR => 'AND', + CASESENSITIVE => 0, ) ); } } @@ -1748,6 +1755,7 @@ sub _CustomFieldLimit { FIELD => 'Content', OPERATOR => $op, VALUE => $value, + CASESENSITIVE => 0, %rest ); @@ -1774,6 +1782,7 @@ sub _CustomFieldLimit { OPERATOR => $op, VALUE => $value, ENTRYAGGREGATOR => 'AND', + CASESENSITIVE => 0, ) ); $self->_CloseParen; } @@ -1830,6 +1839,7 @@ sub _CustomFieldLimit { FIELD => $column, OPERATOR => $op, VALUE => $value, + CASESENSITIVE => 0, ) ); } else { @@ -1839,6 +1849,7 @@ sub _CustomFieldLimit { FIELD => 'Content', OPERATOR => $op, VALUE => $value, + CASESENSITIVE => 0, ); } $self->_SQLLimit( diff --git a/rt/lib/RT/URI.pm b/rt/lib/RT/URI.pm index fce04598a..284a75ee0 100644 --- a/rt/lib/RT/URI.pm +++ b/rt/lib/RT/URI.pm @@ -91,7 +91,26 @@ sub new { return ($self); } +=head2 CanonicalizeURI +Returns the canonical form of the given URI by calling L and then L. + +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 diff --git a/rt/lib/RT/User.pm b/rt/lib/RT/User.pm index 9b4a82683..e7f7c2ad6 100755 --- a/rt/lib/RT/User.pm +++ b/rt/lib/RT/User.pm @@ -932,7 +932,7 @@ sub IsPassword { # crypt() output return 0 unless crypt(encode_utf8($value), $stored) eq $stored; } else { - $RT::Logger->warn("Unknown password form"); + $RT::Logger->warning("Unknown password form"); return 0; } diff --git a/rt/sbin/standalone_httpd b/rt/sbin/standalone_httpd index 3386cd1fe..cef0f3102 100755 --- a/rt/sbin/standalone_httpd +++ b/rt/sbin/standalone_httpd @@ -172,7 +172,7 @@ if (caller) { require Plack::Runner; my $is_fastcgi = $0 =~ m/fcgi$/; -my $r = Plack::Runner->new( $0 =~ 'standalone' ? ( server => 'Standalone' ) : +my $r = Plack::Runner->new( $0 =~ /standalone/ ? ( server => 'Standalone' ) : $is_fastcgi ? ( server => 'FCGI' ) : (), env => 'deployment' ); diff --git a/rt/sbin/standalone_httpd.in b/rt/sbin/standalone_httpd.in index 45c377088..f84f6c103 100644 --- a/rt/sbin/standalone_httpd.in +++ b/rt/sbin/standalone_httpd.in @@ -172,7 +172,7 @@ if (caller) { require Plack::Runner; my $is_fastcgi = $0 =~ m/fcgi$/; -my $r = Plack::Runner->new( $0 =~ 'standalone' ? ( server => 'Standalone' ) : +my $r = Plack::Runner->new( $0 =~ /standalone/ ? ( server => 'Standalone' ) : $is_fastcgi ? ( server => 'FCGI' ) : (), env => 'deployment' ); diff --git a/rt/share/html/Admin/Queues/Modify.html b/rt/share/html/Admin/Queues/Modify.html index 5682eee28..85cd62f16 100755 --- a/rt/share/html/Admin/Queues/Modify.html +++ b/rt/share/html/Admin/Queues/Modify.html @@ -51,7 +51,7 @@ -
+ diff --git a/rt/share/html/Approvals/Elements/PendingMyApproval b/rt/share/html/Approvals/Elements/PendingMyApproval index d2061da84..169c25cb6 100755 --- a/rt/share/html/Approvals/Elements/PendingMyApproval +++ b/rt/share/html/Approvals/Elements/PendingMyApproval @@ -74,7 +74,7 @@ $tickets->LimitOwner( VALUE => $session{'CurrentUser'}->Id ); # also consider AdminCcs as potential approvers. my $group_tickets = RT::Tickets->new( $session{'CurrentUser'} ); -$group_tickets->LimitWatcher( VALUE => $session{'CurrentUser'}->UserObj->EmailAddress, TYPE => 'AdminCc' ); +$group_tickets->LimitWatcher( VALUE => $session{'CurrentUser'}->EmailAddress, TYPE => 'AdminCc' ); my $created_before = RT::Date->new( $session{'CurrentUser'} ); my $created_after = RT::Date->new( $session{'CurrentUser'} ); diff --git a/rt/share/html/Approvals/autohandler b/rt/share/html/Approvals/autohandler index a05770654..3e0f2c6db 100644 --- a/rt/share/html/Approvals/autohandler +++ b/rt/share/html/Approvals/autohandler @@ -46,8 +46,13 @@ %# %# END BPS TAGGED BLOCK }}} <%init> -$m->call_next(%ARGS) if $session{'CurrentUser'}->UserObj->HasRight( +if ( $session{'CurrentUser'}->UserObj->HasRight( Right => 'ShowApprovalsTab', Object => $RT::System, -); +) ) { + $m->call_next(%ARGS); +} +else { + Abort("No permission to view approval"); +} diff --git a/rt/share/html/Dashboards/Subscription.html b/rt/share/html/Dashboards/Subscription.html index 3669e4687..3a57102c7 100644 --- a/rt/share/html/Dashboards/Subscription.html +++ b/rt/share/html/Dashboards/Subscription.html @@ -171,7 +171,7 @@ <&|/l&>Recipient: -
<% loc("Leave blank to send to your current email address ([_1])", $session{'CurrentUser'}->UserObj->EmailAddress) %>
+
<% loc("Leave blank to send to your current email address ([_1])", $session{'CurrentUser'}->EmailAddress) %>
diff --git a/rt/share/html/Elements/ColumnMap b/rt/share/html/Elements/ColumnMap index b9c3b4bc8..f268a5d1c 100644 --- a/rt/share/html/Elements/ColumnMap +++ b/rt/share/html/Elements/ColumnMap @@ -118,7 +118,7 @@ my $COLUMN_MAP = { CheckBox => { title => sub { my $name = $_[1] || 'SelectedTickets'; - my $checked = $m->request_args->{ $name .'All' }? 'checked="checked"': ''; + my $checked = $DECODED_ARGS->{ $name .'All' }? 'checked="checked"': ''; return \qq{} - if $m->request_args->{ $name . 'All'}; + if $DECODED_ARGS->{ $name . 'All'}; - my $arg = $m->request_args->{ $name }; + my $arg = $DECODED_ARGS->{ $name }; my $checked = ''; if ( $arg && ref $arg ) { $checked = 'checked="checked"' if grep $_ == $id, @$arg; @@ -149,7 +149,7 @@ my $COLUMN_MAP = { my $id = $_[0]->id; my $name = $_[2] || 'SelectedTicket'; - my $arg = $m->request_args->{ $name }; + my $arg = $DECODED_ARGS->{ $name }; my $checked = ''; $checked = 'checked="checked"' if $arg && $arg == $id; return \qq{}; diff --git a/rt/share/html/Elements/EditCustomField b/rt/share/html/Elements/EditCustomField index b74c4844e..8b87fd425 100644 --- a/rt/share/html/Elements/EditCustomField +++ b/rt/share/html/Elements/EditCustomField @@ -71,7 +71,7 @@ if ( $Object && $Object->id ) { # Always fill $Default with submited values if it's empty if ( ( !defined $Default || !length $Default ) && $DefaultsFromTopArguments ) { - my %TOP = $m->request_args; + my %TOP = %$DECODED_ARGS; $Default = $TOP{ $NamePrefix .$CustomField->Id . '-Values' } || $TOP{ $NamePrefix .$CustomField->Id . '-Value' }; } diff --git a/rt/share/html/Elements/Header b/rt/share/html/Elements/Header index 1830c4bf2..65d06f879 100755 --- a/rt/share/html/Elements/Header +++ b/rt/share/html/Elements/Header @@ -130,7 +130,8 @@ if ($m->comp_exists($stylesheet_plugin) ) { # $m->callback( %ARGS, CallbackName => 'Head' ); $head .= $m->scomp( '/Elements/Callback', _CallbackName => 'Head', %ARGS ); -my $etc = qq[ class="\L$style" ]; +my $sbs = RT->Config->Get("UseSideBySideLayout", $session{'CurrentUser'}) ? ' sidebyside' : ''; +my $etc = qq[ class="\L$style$sbs" ]; $etc .= qq[ id="comp-$id"] if $id; diff --git a/rt/share/html/Elements/HeaderJavascript b/rt/share/html/Elements/HeaderJavascript index 28788db57..d5741f4e6 100644 --- a/rt/share/html/Elements/HeaderJavascript +++ b/rt/share/html/Elements/HeaderJavascript @@ -67,7 +67,7 @@ $onload => undef % } % if ( $RichText and RT->Config->Get('MessageBoxRichText', $session{'CurrentUser'})) { - jQuery().ready(function () { ReplaceAllTextareas(<%$m->request_args->{'CKeditorEncoded'} || 0 |n,j%>) }); + jQuery().ready(function () { ReplaceAllTextareas(<%$DECODED_ARGS->{'CKeditorEncoded'} || 0 |n,j%>) }); % } --> <%ARGS> diff --git a/rt/share/html/Elements/ListActions b/rt/share/html/Elements/ListActions index 999d3fe5b..8929ff731 100755 --- a/rt/share/html/Elements/ListActions +++ b/rt/share/html/Elements/ListActions @@ -65,7 +65,7 @@ if ( ref( $session{'Actions'}{''} ) eq 'ARRAY' ) { unshift @actions, @{ delete $session{'Actions'}{''} }; } -my $actions_pointer = $m->request_args->{'results'}; +my $actions_pointer = $DECODED_ARGS->{'results'}; if ($actions_pointer && ref( $session{'Actions'}->{$actions_pointer} ) eq 'ARRAY' ) { unshift @actions, @{ delete $session{'Actions'}->{$actions_pointer} }; diff --git a/rt/share/html/Elements/MessageBox b/rt/share/html/Elements/MessageBox index 61995e057..69227bfa9 100755 --- a/rt/share/html/Elements/MessageBox +++ b/rt/share/html/Elements/MessageBox @@ -46,7 +46,7 @@ %# %# END BPS TAGGED BLOCK }}} % $m->callback( %ARGS, CallbackName => 'AfterTextArea' ); @@ -89,4 +89,5 @@ $Width => RT->Config->Get('MessageBoxWidth', $session{'CurrentUser'} $Height => RT->Config->Get('MessageBoxHeight', $session{'CurrentUser'} ) || 15 $Wrap => RT->Config->Get('MessageBoxWrap', $session{'CurrentUser'} ) || 'SOFT' $IncludeSignature => RT->Config->Get('MessageBoxIncludeSignature'); +$IncludeArticle => 1; diff --git a/rt/share/html/Elements/QueueSummaryByStatus b/rt/share/html/Elements/QueueSummaryByStatus index 09f274f74..f649d2850 100644 --- a/rt/share/html/Elements/QueueSummaryByStatus +++ b/rt/share/html/Elements/QueueSummaryByStatus @@ -122,9 +122,13 @@ my $statuses = {}; use RT::Report::Tickets; my $report = RT::Report::Tickets->new( RT->SystemUser ); -my $query = @queues - ? join(' OR ', map "Queue = ".$_->{id}, @queues) - : 'id < 0'; +my $query = + "(". + join(" OR ", map {s{(['\\])}{\\$1}g; "Status = '$_'"} @statuses) #' + .") AND (". + join(' OR ', map "Queue = ".$_->{id}, @queues) + .")"; +$query = 'id < 0' unless @queues; $report->SetupGroupings( Query => $query, GroupBy => [qw(Status Queue)] ); while ( my $entry = $report->Next ) { diff --git a/rt/share/html/Elements/RT__CustomField/ColumnMap b/rt/share/html/Elements/RT__CustomField/ColumnMap index ecb219d9e..b04398434 100644 --- a/rt/share/html/Elements/RT__CustomField/ColumnMap +++ b/rt/share/html/Elements/RT__CustomField/ColumnMap @@ -118,7 +118,7 @@ my $COLUMN_MAP = { RemoveCheckBox => { title => sub { my $name = 'RemoveCustomField'; - my $checked = $m->request_args->{ $name .'All' }? 'checked="checked"': ''; + my $checked = $DECODED_ARGS->{ $name .'All' }? 'checked="checked"': ''; return \qq{ a > .sf-sub-indicator { -moz-border-radius-topright: 17px; -webkit-border-top-right-radius: 17px; -webkit-border-bottom-left-radius: 17px; + border-top-right-radius: 17px; + border-bottom-left-radius: 17px; } .sf-shadow ul.sf-shadow-off { background: transparent; diff --git a/rt/share/html/NoAuth/css/base/ticket-form.css b/rt/share/html/NoAuth/css/base/ticket-form.css index daab263b1..869eba774 100644 --- a/rt/share/html/NoAuth/css/base/ticket-form.css +++ b/rt/share/html/NoAuth/css/base/ticket-form.css @@ -82,21 +82,17 @@ iframe.richtext-editor { .messagebox-container.action-response iframe { background-color: #fcc !important; -} - -/* -% if ( RT->Config->Get("UseSideBySideLayout", $session{'CurrentUser'}) ) { -*/ +} -#ticket-create-metadata, -#ticket-update-metadata { +.sidebyside #ticket-create-metadata, +.sidebyside #ticket-update-metadata { float: right; width: 40%; clear: right; } -#ticket-create-message, -#ticket-update-message { +.sidebyside #ticket-create-message, +.sidebyside #ticket-update-message { float: left; width: 58%; clear: left; @@ -104,10 +100,10 @@ iframe.richtext-editor { @media (max-width: 950px) { /* Revert to a single column when we're less than 1000px wide */ - #ticket-create-metadata, - #ticket-update-metadata, - #ticket-create-message, - #ticket-update-message + .sidebyside #ticket-create-metadata, + .sidebyside #ticket-update-metadata, + .sidebyside #ticket-create-message, + .sidebyside #ticket-update-message { float: none; width: auto; @@ -115,15 +111,12 @@ iframe.richtext-editor { } } -#comp-Ticket-Update #body { +.sidebyside #comp-Ticket-Update #body { padding-top: 3em; } -#ticket-create-message .button[name="AddMoreAttach"], -#ticket-update-message .button[name="AddMoreAttach"] { +.sidebyside #ticket-create-message .button[name="AddMoreAttach"], +.sidebyside #ticket-update-message .button[name="AddMoreAttach"] { float: right; } -/* -% } -*/ diff --git a/rt/share/html/NoAuth/css/base/ui.timepickr.css b/rt/share/html/NoAuth/css/base/ui.timepickr.css deleted file mode 100644 index e2dacf7a9..000000000 --- a/rt/share/html/NoAuth/css/base/ui.timepickr.css +++ /dev/null @@ -1,56 +0,0 @@ -/* - jQuery ui.timepickr - http://code.google.com/p/jquery-utils/ - - copyright Maxime Haineault - http://haineault.com - - MIT License (http://www.opensource.org/licenses/mit-license.php -*/ -.ui-timepickr { - position:absolute; - width:480px; -} - -.ui-timepickr-row { - margin:0; - padding:0; - margin-top:2px; - display:none; - position:relative; -} - -.ui-timepickr-button { - float:left; - margin:0; - padding:0; - list-style:none; - list-style-type:none; -} - -.ui-timepickr-button span { - font-size:.7em; - padding:4px 6px 4px 6px; - margin-left:2px; - text-align:center; - cursor:pointer; - display:block; - text-align:center; - - - /* system theme (default) */ - border-width:1px; - border-style:solid; - /*border-color:ThreeDLightShadow ThreeDShadow ThreeDShadow ThreeDLightShadow; - color:ButtonText; - background:ButtonFace;*/ -} - -.ui-timepickr-button span.ui-state-hover { - /*color:HighlightText; - background:Highlight;*/ -} - -.ui-state-hover span { - /*background:#c30;*/ -} diff --git a/rt/share/html/NoAuth/css/base/ui.timepickr.custom.css b/rt/share/html/NoAuth/css/base/ui.timepickr.custom.css deleted file mode 100644 index ad2aa66ce..000000000 --- a/rt/share/html/NoAuth/css/base/ui.timepickr.custom.css +++ /dev/null @@ -1,54 +0,0 @@ -%# BEGIN BPS TAGGED BLOCK {{{ -%# -%# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC -%# -%# -%# (Except where explicitly superseded by other copyright notices) -%# -%# -%# LICENSE: -%# -%# This work is made available to you under the terms of Version 2 of -%# the GNU General Public License. A copy of that license should have -%# been provided with this software, but in any event can be snarfed -%# from www.gnu.org. -%# -%# This work is distributed in the hope that it will be useful, but -%# WITHOUT ANY WARRANTY; without even the implied warranty of -%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%# General Public License for more details. -%# -%# You should have received a copy of the GNU General Public License -%# along with this program; if not, write to the Free Software -%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -%# 02110-1301 or visit their web page on the internet at -%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -%# -%# -%# CONTRIBUTION SUBMISSION POLICY: -%# -%# (The following paragraph is not intended to limit the rights granted -%# to you to modify and distribute this software under the terms of -%# the GNU General Public License and is only of importance to you if -%# you choose to contribute your changes and enhancements to the -%# community by submitting them to Best Practical Solutions, LLC.) -%# -%# By intentionally submitting any modifications, corrections or -%# derivatives to this work, or any other work intended for use with -%# Request Tracker, to Best Practical Solutions, LLC, you confirm that -%# you are the copyright holder for those contributions and you grant -%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -%# royalty-free, perpetual, license to use, copy, create derivative -%# works based on those contributions, and sublicense and distribute -%# those contributions and any derivatives thereof. -%# -%# END BPS TAGGED BLOCK }}} -.ui-timepickr { - font-size: 1.1em; -} - -.ui-timepickr-button span { - background: white; -} diff --git a/rt/share/html/NoAuth/css/web2/nav.css b/rt/share/html/NoAuth/css/web2/nav.css index be63c5984..e404b61c8 100644 --- a/rt/share/html/NoAuth/css/web2/nav.css +++ b/rt/share/html/NoAuth/css/web2/nav.css @@ -239,6 +239,7 @@ border: 1px solid #ccc; -moz-border-radius-bottomleft: 0.5em; -webkit-border-bottom-left-radius: 0.5em; + border-bottom-left-radius: 0.5em; border-right: none; border-top: none; list-style-type: none; diff --git a/rt/share/html/NoAuth/js/jquery-ui-1.8.4.custom.min.js b/rt/share/html/NoAuth/js/jquery-ui-1.8.4.custom.min.js index e90b4fe4b..0466005dc 100644 --- a/rt/share/html/NoAuth/js/jquery-ui-1.8.4.custom.min.js +++ b/rt/share/html/NoAuth/js/jquery-ui-1.8.4.custom.min.js @@ -222,3 +222,53 @@ c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(t function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b)); return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new L;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.4";window["DP_jQuery_"+y]=d})(jQuery); ; +/*! + * jQuery UI Mouse 1.8.4 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&& +this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault(); +return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&& +this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX- +a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); +/* + * jQuery UI Slider 1.8.4 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(d){d.widget("ui.slider",d.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var a=this,b=this.options;this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");b.disabled&&this.element.addClass("ui-slider-disabled ui-disabled"); +this.range=d([]);if(b.range){if(b.range===true){this.range=d("
");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("
");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("").appendTo(this.element).addClass("ui-slider-handle"); +if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length").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&&c1){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;fthis._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a= +this.options.range,b=this.options,c=this,e=!this._animateOff?b.animate:false,f,h={},g,i,j,l;if(this.options.values&&this.options.values.length)this.handles.each(function(k){f=(c.values(k)-c._valueMin())/(c._valueMax()-c._valueMin())*100;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](h,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(k===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({width:f- +g+"%"},{queue:false,duration:b.animate})}else{if(k===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({height:f-g+"%"},{queue:false,duration:b.animate})}g=f});else{i=this.value();j=this._valueMin();l=this._valueMax();f=l!==j?(i-j)/(l-j)*100:0;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](h,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"}, +b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.4"})})(jQuery); diff --git a/rt/share/html/NoAuth/js/jquery-ui-patch-datepicker.js b/rt/share/html/NoAuth/js/jquery-ui-patch-datepicker.js index 40cc0db99..2ac101f93 100644 --- a/rt/share/html/NoAuth/js/jquery-ui-patch-datepicker.js +++ b/rt/share/html/NoAuth/js/jquery-ui-patch-datepicker.js @@ -58,4 +58,35 @@ return data; }; + + $.datepicker._checkOffset_orig = $.datepicker._checkOffset; + $.datepicker._checkOffset = function(inst, offset, isFixed) { + // copied from the original + var dpHeight = inst.dpDiv.outerHeight(); + var inputHeight = inst.input ? inst.input.outerHeight() : 0; + var viewHeight = document.documentElement.clientHeight + $(document).scrollTop(); + + // save the original offset rather than the new offset because the + // original function modifies the passed arg as a side-effect + var old_offset = { top: offset.top, left: offset.left }; + offset = $.datepicker._checkOffset_orig(inst, offset, isFixed); + + // Negate any up or down positioning by adding instead of subtracting + offset.top += Math.min(old_offset.top, (old_offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? + Math.abs(dpHeight + inputHeight) : 0); + + return offset; + }; + + + $.timepicker._newInst_orig = $.timepicker._newInst; + $.timepicker._newInst = function($input, o) { + var tp_inst = $.timepicker._newInst_orig($input, o); + tp_inst._defaults.onClose = function(dateText, dp_inst) { + if ($.isFunction(o.onClose)) + o.onClose.call($input[0], dateText, dp_inst, tp_inst); + }; + return tp_inst; + }; + })(jQuery); diff --git a/rt/share/html/NoAuth/js/jquery-ui-timepicker-addon.js b/rt/share/html/NoAuth/js/jquery-ui-timepicker-addon.js new file mode 100644 index 000000000..0a4ff026e --- /dev/null +++ b/rt/share/html/NoAuth/js/jquery-ui-timepicker-addon.js @@ -0,0 +1,1326 @@ +/* +* jQuery timepicker addon +* By: Trent Richardson [http://trentrichardson.com] +* Version 1.0.0 +* Last Modified: 02/05/2012 +* +* Copyright 2012 Trent Richardson +* Dual licensed under the MIT and GPL licenses. +* http://trentrichardson.com/Impromptu/GPL-LICENSE.txt +* http://trentrichardson.com/Impromptu/MIT-LICENSE.txt +* +* HERES THE CSS: +* .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; } +* .ui-timepicker-div dl { text-align: left; } +* .ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; } +* .ui-timepicker-div dl dd { margin: 0 10px 10px 65px; } +* .ui-timepicker-div td { font-size: 90%; } +* .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; } +*/ + +(function($) { + +// Prevent "Uncaught RangeError: Maximum call stack size exceeded" +$.ui.timepicker = $.ui.timepicker || {}; +if ($.ui.timepicker.version) { + return; +} + +$.extend($.ui, { timepicker: { version: "1.0.0" } }); + +/* Time picker manager. + Use the singleton instance of this class, $.timepicker, to interact with the time picker. + Settings for (groups of) time pickers are maintained in an instance object, + allowing multiple different settings on the same page. */ + +function Timepicker() { + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + currentText: 'Now', + closeText: 'Done', + ampm: false, + amNames: ['AM', 'A'], + pmNames: ['PM', 'P'], + timeFormat: 'hh:mm tt', + timeSuffix: '', + timeOnlyTitle: 'Choose Time', + timeText: 'Time', + hourText: 'Hour', + minuteText: 'Minute', + secondText: 'Second', + millisecText: 'Millisecond', + timezoneText: 'Time Zone' + }; + this._defaults = { // Global defaults for all the datetime picker instances + showButtonPanel: true, + timeOnly: false, + showHour: true, + showMinute: true, + showSecond: false, + showMillisec: false, + showTimezone: false, + showTime: true, + stepHour: 1, + stepMinute: 1, + stepSecond: 1, + stepMillisec: 1, + hour: 0, + minute: 0, + second: 0, + millisec: 0, + timezone: '+0000', + hourMin: 0, + minuteMin: 0, + secondMin: 0, + millisecMin: 0, + hourMax: 23, + minuteMax: 59, + secondMax: 59, + millisecMax: 999, + minDateTime: null, + maxDateTime: null, + onSelect: null, + hourGrid: 0, + minuteGrid: 0, + secondGrid: 0, + millisecGrid: 0, + alwaysSetTime: true, + separator: ' ', + altFieldTimeOnly: true, + showTimepicker: true, + timezoneIso8609: false, + timezoneList: null, + addSliderAccess: false, + sliderAccessArgs: null + }; + $.extend(this._defaults, this.regional['']); +}; + +$.extend(Timepicker.prototype, { + $input: null, + $altInput: null, + $timeObj: null, + inst: null, + hour_slider: null, + minute_slider: null, + second_slider: null, + millisec_slider: null, + timezone_select: null, + hour: 0, + minute: 0, + second: 0, + millisec: 0, + timezone: '+0000', + hourMinOriginal: null, + minuteMinOriginal: null, + secondMinOriginal: null, + millisecMinOriginal: null, + hourMaxOriginal: null, + minuteMaxOriginal: null, + secondMaxOriginal: null, + millisecMaxOriginal: null, + ampm: '', + formattedDate: '', + formattedTime: '', + formattedDateTime: '', + timezoneList: null, + + /* Override the default settings for all instances of the time picker. + @param settings object - the new settings to use as defaults (anonymous object) + @return the manager object */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + //######################################################################## + // Create a new Timepicker instance + //######################################################################## + _newInst: function($input, o) { + var tp_inst = new Timepicker(), + inlineSettings = {}; + + for (var attrName in this._defaults) { + var attrValue = $input.attr('time:' + attrName); + if (attrValue) { + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, { + beforeShow: function(input, dp_inst) { + if ($.isFunction(o.beforeShow)) + return o.beforeShow(input, dp_inst, tp_inst); + }, + onChangeMonthYear: function(year, month, dp_inst) { + // Update the time as well : this prevents the time from disappearing from the $input field. + tp_inst._updateDateTime(dp_inst); + if ($.isFunction(o.onChangeMonthYear)) + o.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst); + }, + onClose: function(dateText, dp_inst) { + if (tp_inst.timeDefined === true && $input.val() != '') + tp_inst._updateDateTime(dp_inst); + if ($.isFunction(o.onClose)) + o.onClose.call($input[0], dateText, dp_inst, tp_inst); + }, + timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker'); + }); + tp_inst.amNames = $.map(tp_inst._defaults.amNames, function(val) { return val.toUpperCase(); }); + tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function(val) { return val.toUpperCase(); }); + + if (tp_inst._defaults.timezoneList === null) { + var timezoneList = []; + for (var i = -11; i <= 12; i++) + timezoneList.push((i >= 0 ? '+' : '-') + ('0' + Math.abs(i).toString()).slice(-2) + '00'); + if (tp_inst._defaults.timezoneIso8609) + timezoneList = $.map(timezoneList, function(val) { + return val == '+0000' ? 'Z' : (val.substring(0, 3) + ':' + val.substring(3)); + }); + tp_inst._defaults.timezoneList = timezoneList; + } + + tp_inst.hour = tp_inst._defaults.hour; + tp_inst.minute = tp_inst._defaults.minute; + tp_inst.second = tp_inst._defaults.second; + tp_inst.millisec = tp_inst._defaults.millisec; + tp_inst.ampm = ''; + tp_inst.$input = $input; + + if (o.altField) + tp_inst.$altInput = $(o.altField) + .css({ cursor: 'pointer' }) + .focus(function(){ $input.trigger("focus"); }); + + if(tp_inst._defaults.minDate==0 || tp_inst._defaults.minDateTime==0) + { + tp_inst._defaults.minDate=new Date(); + } + if(tp_inst._defaults.maxDate==0 || tp_inst._defaults.maxDateTime==0) + { + tp_inst._defaults.maxDate=new Date(); + } + + // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime.. + if(tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) + tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime()); + if(tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) + tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime()); + if(tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) + tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime()); + if(tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) + tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime()); + return tp_inst; + }, + + //######################################################################## + // add our sliders to the calendar + //######################################################################## + _addTimePicker: function(dp_inst) { + var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? + this.$input.val() + ' ' + this.$altInput.val() : + this.$input.val(); + + this.timeDefined = this._parseTime(currDT); + this._limitMinMaxDateTime(dp_inst, false); + this._injectTimePicker(); + }, + + //######################################################################## + // parse the time string from input value or _setTime + //######################################################################## + _parseTime: function(timeString, withDate) { + var regstr = this._defaults.timeFormat.toString() + .replace(/h{1,2}/ig, '(\\d?\\d)') + .replace(/m{1,2}/ig, '(\\d?\\d)') + .replace(/s{1,2}/ig, '(\\d?\\d)') + .replace(/l{1}/ig, '(\\d?\\d?\\d)') + .replace(/t{1,2}/ig, this._getPatternAmpm()) + .replace(/z{1}/ig, '(z|[-+]\\d\\d:?\\d\\d)?') + .replace(/\s/g, '\\s?') + this._defaults.timeSuffix + '$', + order = this._getFormatPositions(), + ampm = '', + treg; + + if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]); + + if (withDate || !this._defaults.timeOnly) { + // the time should come after x number of characters and a space. + // x = at least the length of text specified by the date format + var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat'); + // escape special regex characters in the seperator + var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); + regstr = '^.{' + dp_dateFormat.length + ',}?' + this._defaults.separator.replace(specials, "\\$&") + regstr; + } + + treg = timeString.match(new RegExp(regstr, 'i')); + + if (treg) { + if (order.t !== -1) { + if (treg[order.t] === undefined || treg[order.t].length === 0) { + ampm = ''; + this.ampm = ''; + } else { + ampm = $.inArray(treg[order.t].toUpperCase(), this.amNames) !== -1 ? 'AM' : 'PM'; + this.ampm = this._defaults[ampm == 'AM' ? 'amNames' : 'pmNames'][0]; + } + } + + if (order.h !== -1) { + if (ampm == 'AM' && treg[order.h] == '12') + this.hour = 0; // 12am = 0 hour + else if (ampm == 'PM' && treg[order.h] != '12') + this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0); // 12pm = 12 hour, any other pm = hour + 12 + else this.hour = Number(treg[order.h]); + } + + if (order.m !== -1) this.minute = Number(treg[order.m]); + if (order.s !== -1) this.second = Number(treg[order.s]); + if (order.l !== -1) this.millisec = Number(treg[order.l]); + if (order.z !== -1 && treg[order.z] !== undefined) { + var tz = treg[order.z].toUpperCase(); + switch (tz.length) { + case 1: // Z + tz = this._defaults.timezoneIso8609 ? 'Z' : '+0000'; + break; + case 5: // +hhmm + if (this._defaults.timezoneIso8609) + tz = tz.substring(1) == '0000' + ? 'Z' + : tz.substring(0, 3) + ':' + tz.substring(3); + break; + case 6: // +hh:mm + if (!this._defaults.timezoneIso8609) + tz = tz == 'Z' || tz.substring(1) == '00:00' + ? '+0000' + : tz.replace(/:/, ''); + else if (tz.substring(1) == '00:00') + tz = 'Z'; + break; + } + this.timezone = tz; + } + + return true; + + } + return false; + }, + + //######################################################################## + // pattern for standard and localized AM/PM markers + //######################################################################## + _getPatternAmpm: function() { + var markers = [], + o = this._defaults; + if (o.amNames) + $.merge(markers, o.amNames); + if (o.pmNames) + $.merge(markers, o.pmNames); + markers = $.map(markers, function(val) { return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&'); }); + return '(' + markers.join('|') + ')?'; + }, + + //######################################################################## + // figure out position of time elements.. cause js cant do named captures + //######################################################################## + _getFormatPositions: function() { + var finds = this._defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z)/g), + orders = { h: -1, m: -1, s: -1, l: -1, t: -1, z: -1 }; + + if (finds) + for (var i = 0; i < finds.length; i++) + if (orders[finds[i].toString().charAt(0)] == -1) + orders[finds[i].toString().charAt(0)] = i + 1; + + return orders; + }, + + //######################################################################## + // generate and inject html for timepicker into ui datepicker + //######################################################################## + _injectTimePicker: function() { + var $dp = this.inst.dpDiv, + o = this._defaults, + tp_inst = this, + // Added by Peter Medeiros: + // - Figure out what the hour/minute/second max should be based on the step values. + // - Example: if stepMinute is 15, then minMax is 45. + hourMax = parseInt((o.hourMax - ((o.hourMax - o.hourMin) % o.stepHour)) ,10), + minMax = parseInt((o.minuteMax - ((o.minuteMax - o.minuteMin) % o.stepMinute)) ,10), + secMax = parseInt((o.secondMax - ((o.secondMax - o.secondMin) % o.stepSecond)) ,10), + millisecMax = parseInt((o.millisecMax - ((o.millisecMax - o.millisecMin) % o.stepMillisec)) ,10), + dp_id = this.inst.id.toString().replace(/([^A-Za-z0-9_])/g, ''); + + // Prevent displaying twice + //if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0) { + if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0 && o.showTimepicker) { + var noDisplay = ' style="display:none;"', + html = '
' + + '
' + o.timeText + '
' + + '
' + + '
' + o.hourText + '
', + hourGridSize = 0, + minuteGridSize = 0, + secondGridSize = 0, + millisecGridSize = 0, + size = null; + + // Hours + html += '
'; + if (o.showHour && o.hourGrid > 0) { + html += '
'; + + 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 += ''; + } + + html += '
' + tmph + '
'; + } + html += '
'; + + // Minutes + html += '
' + o.minuteText + '
'+ + '
'; + + if (o.showMinute && o.minuteGrid > 0) { + html += '
'; + + for (var m = o.minuteMin; m <= minMax; m += parseInt(o.minuteGrid,10)) { + minuteGridSize++; + html += ''; + } + + html += '
' + ((m < 10) ? '0' : '') + m + '
'; + } + html += '
'; + + // Seconds + html += '
' + o.secondText + '
'+ + '
'; + + if (o.showSecond && o.secondGrid > 0) { + html += '
'; + + for (var s = o.secondMin; s <= secMax; s += parseInt(o.secondGrid,10)) { + secondGridSize++; + html += ''; + } + + html += '
' + ((s < 10) ? '0' : '') + s + '
'; + } + html += '
'; + + // Milliseconds + html += '
' + o.millisecText + '
'+ + '
'; + + if (o.showMillisec && o.millisecGrid > 0) { + html += '
'; + + for (var l = o.millisecMin; l <= millisecMax; l += parseInt(o.millisecGrid,10)) { + millisecGridSize++; + html += ''; + } + + html += '
' + ((l < 10) ? '0' : '') + l + '
'; + } + html += '
'; + + // Timezone + html += '
' + o.timezoneText + '
'; + html += '
'; + + html += '
'; + $tp = $(html); + + // if we only want time picker... + if (o.timeOnly === true) { + $tp.prepend( + '
' + + '
' + o.timeOnlyTitle + '
' + + '
'); + $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('').find("select"); + $.fn.append.apply(this.timezone_select, + $.map(o.timezoneList, function(val, idx) { + return $("