diff options
Diffstat (limited to 'rt')
128 files changed, 3358 insertions, 17041 deletions
diff --git a/rt/FREESIDE_MODIFIED b/rt/FREESIDE_MODIFIED new file mode 100644 index 000000000..1b0c47c06 --- /dev/null +++ b/rt/FREESIDE_MODIFIED @@ -0,0 +1,31 @@ + sbin/rt-setup-database.in +config.layout +config.layout.in + etc/RT_SiteConfig.pm +lib/RT/Interface/Web_Vendor.pm +lib/RT/URI/freeside.pm +lib/RT/URI/freeside/Internal.pm +lib/RT/URI/freeside/XMLRPC.pm + html/Elements/Header + html/Elements/Menu + html/Elements/PageLayout + html/Elements/SimpleSearch + html/Elements/Tabs + html/Elements/Footer + html/Elements/CollectionAsTable/Row #backport from 3.3-TESTING +html/Ticket/Elements/AddCustomers +html/Ticket/Elements/EditCustomers +html/Ticket/Elements/ShowCustomers + html/Ticket/Elements/ShowSummary + html/Ticket/Elements/Tabs +html/Ticket/ModifyCustomers.html +html/NoAuth/images/small-logo.png + html/NoAuth/webrt.css + +html/Elements/TitleBoxStart +html/Search/Bulk.html + +html/Elements/FreesideNewCust +html/Elements/FreesideSearch +html/Elements/FreesideSvcSearch + diff --git a/rt/HOWTO/README b/rt/HOWTO/README deleted file mode 100644 index 942096b0a..000000000 --- a/rt/HOWTO/README +++ /dev/null @@ -1,14 +0,0 @@ -Here you'll find plain text documentation of how to handle various -project procedures. Files contained herein: - -change.txt - How changes are integrated, including generating and - distributing aedist change sets, and updating the CVS repository. - -release.txt - Steps to go through when releasing a new version of RT. - - -These procedures are based on documentation from the scons project -as http://www.scons.org/ - diff --git a/rt/HOWTO/change.txt b/rt/HOWTO/change.txt deleted file mode 100644 index de316450c..000000000 --- a/rt/HOWTO/change.txt +++ /dev/null @@ -1,67 +0,0 @@ -Handling a change set: - - -- Start the change: - - aedist -r [if it's a remote submission] - - -or- - - aedb {cnum} [if it's initiated locally] - - -- Normal development cycle: - - aecd -c {cnum} - aecp . # Copy the baseline to your working dir - # work on your change - aenf {new file names} - - aecpu -unch # Remove unchanged files, for faster diffs - aeb # Currently does nothing - aet # Currently does nothing - aed # Diff your change - aede # End the change - - -- As the reviewer: - - aerpass {cnum} - - -- As the integrator: - - aeib {cnum} - aeb - aet - aed - cd ~ # Get out of the current working directory - aeipass - - - - - -- Update the aedist baseline on the web site: - - aedist -s -bl -p rt.2.1 > rt.2.1.ae - scp rt.2.1.ae jesse@fsck.com:/home/ftp/pub/rt/devel/rt.2.1.ae - rm rt.2.1.ae - - [This will eventually be automated.] - - -- Distribute the change to CVS: - - WARNING. DOES NOT YET WORK - - export CVS_RSH=ssh - ae2cvs -n -aegis -p rt.2.1 -c {cnum} -u ~/SCons/scons - ae2cvs -X -aegis -p rt.2.1 -c {cnum} -u ~/SCons/scons - - If you need the "ae2cvs" Perl script, you can find a copy - checked in to the bin/subdirectory. - - [This may eventually be automated.] - - - - -- Grabbing the latest dev sources over ssh - - ssh fsck.com "aedist -s -p rt.2.1 -naa -bl -entire-source" | aedist -r - - diff --git a/rt/HOWTO/release.txt b/rt/HOWTO/release.txt deleted file mode 100644 index 285041c5b..000000000 --- a/rt/HOWTO/release.txt +++ /dev/null @@ -1,124 +0,0 @@ -Things to do to release a new version of rt: - - Build and test candidate packages - - Read through the README and src/README.txt files for any updates - - Prepare ChangeLog - - date -R the latest release - - should be current if this has been updated as each - change went in. - - [ Should be automated ] - - - TODO: nothing below this line is accurate for RT - - END THE BRANCH - - ae_p rt.2 - aede {5} - aerpass {5} - aeib {5} - aeb - aet - aet -reg - aed - aeipass - - START THE NEW BRANCH - - aenbr -p rt.2 {6} - aenc -p rt.2.{6} - - Call it something like, "Initialize the new - branch." Cause = internal_enhancement. Exempt - it from all tests (*_exempt = true). - - ae_p rt.2.{6} - - aedb 100 - - aecd - - # Change the hard-coded package version numbers - # in the following files. - aecp rttruct debian/changelog rpm/rt.spec - - vi rttruct debian/changelog rpm/rt.spec - - # Optionally, do the same in the following: - [optional] aecp HOWTO/change.txt - [optional] aecp HOWTO/release.txt - [optional] aecp debian/rt.postinst - - [optional] vi HOWTO/change.txt - [optional] vi HOWTO/release.txt - [optional] vi debian/rt.postinst - - aeb - - aet -reg - - aed - - aede - - etc. - - - Read through the FAQ for any updates - - Test downloading from the web site download page - - - In the Bugs Tracker, add a Group for the new release (0.05) - - Announce to the following mailing lists (template below): - - rt-announce@lists.fsck.com - - - Notify www.cmtoday.com/contribute.html - - [This guy wants an announcement no more frequently than - once a month, so save it for a future release if it's - been too soon since the previous one.] - - Notify freshmeat.net - - [Wait until the morning so the announcement hits the - main freshmeat.net page while people in the U.S. are - awake and working] - - - - -======================= - -Template release announcement: - - - -Version 2.1.XXX of rt has been released and is available for download -from the rt web site: - - http://bestpractical.com/rt/ - - - -WHAT'S NEW IN THIS RELEASE? - -Version 2.1.XXX of rt contains the following important changes: - - - XXX - -For a complete list of changes in version 2.1.XXX, see the CHANGES.txt -file in the release itself. - - -WHAT IS RT? - - FILL THIS IN diff --git a/rt/HOWTO/version-control.txt b/rt/HOWTO/version-control.txt deleted file mode 100644 index 06babfdf1..000000000 --- a/rt/HOWTO/version-control.txt +++ /dev/null @@ -1,41 +0,0 @@ -Using Aegis for RT development - - 1. The main line of RT development will be under the control - of the Aegis change management system, as administered by - Best Practical Solutions, LLC - - 2. We will use aedist to generate change sets for each change - checked in to the main Aegis repository. These change sets will be - either distributed by a mailing list or made available via the web, - or both. - - 3. Remote developers using Aegis will send aedist output for - their changes to rt-patches@bestpractical.com for review and - integration. - - 4. The aedist output should be sent to rt-patches@bestpractical.com - after the change has completed its local aede, but before aerpass. - - 5. If the change is rejected, the developer can aedeu to reopen - the change and fix whatever problems caused the review to not pass. - - 6. A baseline snapshot (aedist -bl) of the main Aegis repository - will be generated at least daily and made available via http - to provide a central location for synchronizing remote Aegis - repositories. - - 7. Changes to the main Aegis repository will also be propagated - automatically to the tracking CVS repository. - -Using CVS for RT development - - 1. CVS is accessed via anonymous cvs with the following CVSROOT: - - :pserver:anoncvs@cvs.fsck.com:/raid/cvsroot/rt-2-1 - - 2. Remote developers using CVS will send patches (cvs -diff - output) to rt-patches@bestpractical.com for integration into the - main Aegis repository. This allows anonymous CVS access to be used - for RT development by developers who are unable to use Aegis. - - diff --git a/rt/Makefile b/rt/Makefile index 0895874fb..644722109 100644 --- a/rt/Makefile +++ b/rt/Makefile @@ -1,19 +1,20 @@ # BEGIN LICENSE BLOCK # -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# Copyright (c) 1996-2002 Jesse Vincent <jesse@bestpractical.com> # # (Except where explictly superceded by other copyright notices) # # 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. +# 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. # +# # Unless otherwise specified, all modifications, corrections or # extensions to this work which alter its source code become the # property of Best Practical Solutions, LLC when submitted for @@ -21,6 +22,8 @@ # # # END LICENSE BLOCK + + # # DO NOT HAND-EDIT the file named 'Makefile'. This file is autogenerated. # Have a look at "configure" and "Makefile.in" instead @@ -36,7 +39,7 @@ SITE_CONFIG_FILE = $(CONFIG_FILE_PATH)/RT_SiteConfig.pm RT_VERSION_MAJOR = 3 RT_VERSION_MINOR = 0 -RT_VERSION_PATCH = 9 +RT_VERSION_PATCH = 4 RT_VERSION = $(RT_VERSION_MAJOR).$(RT_VERSION_MINOR).$(RT_VERSION_PATCH) TAG = rt-$(RT_VERSION_MAJOR)-$(RT_VERSION_MINOR)-$(RT_VERSION_PATCH) @@ -98,8 +101,8 @@ RT_MODPERL_HANDLER = $(RT_BIN_PATH)/webmux.pl RT_FASTCGI_HANDLER = $(RT_BIN_PATH)/mason_handler.fcgi # RT_WIN32_FASTCGI_HANDLER is the mason handler script for FastCGI RT_WIN32_FASTCGI_HANDLER = $(RT_BIN_PATH)/mason_handler.svc -# RT's CLI -RT_CLI_BIN = $(RT_BIN_PATH)/rt +# RT's admin CLI +RT_CLI_ADMIN_BIN = $(RT_BIN_PATH)/rtadmin # RT's mail gateway RT_MAILGATE_BIN = $(RT_BIN_PATH)/rt-mailgate # RT's cron tool @@ -112,7 +115,6 @@ SETGID_BINARIES = $(DESTDIR)/$(RT_FASTCGI_HANDLER) \ BINARIES = $(DESTDIR)/$(RT_MODPERL_HANDLER) \ $(DESTDIR)/$(RT_MAILGATE_BIN) \ - $(DESTDIR)/$(RT_CLI_BIN) \ $(DESTDIR)/$(RT_CRON_BIN) \ $(SETGID_BINARIES) SYSTEM_BINARIES = $(DESTDIR)/$(RT_SBIN_PATH)/ @@ -126,7 +128,6 @@ SYSTEM_BINARIES = $(DESTDIR)/$(RT_SBIN_PATH)/ # DB_TYPE defines what sort of database RT trys to talk to # "mysql" is known to work. # "Pg" is known to work -# "Informix" is known to work DB_TYPE = mysql @@ -137,8 +138,7 @@ DB_TYPE = mysql # For mysql, you probably want 'root' # For Pg, you probably want 'postgres' -# For Oracle, you want 'system' -# For Informix, you want 'informix' +# For oracle, you want 'system' DB_DBA = root @@ -211,7 +211,7 @@ upgrade-instruct: @echo " $(RT_SBIN_PATH)/rt-setup-database --action insert --datafile etc/upgrade/<version>" -upgrade: config-install dirs files-install fixperms upgrade-instruct +upgrade: dirs upgrade-noclobber upgrade-instruct upgrade-noclobber: config-install libs-install html-install bin-install local-install doc-install fixperms @@ -312,16 +312,13 @@ config-install: test: $(PERL) -Ilib lib/t/00smoke.t -regression-install: config-install - $(PERL) -pi -e 's/Set\(\$$DatabaseName.*\);/Set\(\$$DatabaseName, "rt3regression"\);/' $(DESTDIR)/$(CONFIG_FILE) - -regression-nosetgid-quiet: regression-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl +regression-nosetgid-quiet: config-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl $(PERL) sbin/regression_harness -regression-nosetgid: regression-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl +regression-nosetgid: config-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms-nosetgid apachectl $(PERL) lib/t/02regression.t -regression: regression-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods fixperms apachectl +regression: config-install dirs files-install libs-install sbin-install bin-install regression-instruct regression-reset-db testify-pods apachectl $(PERL) lib/t/02regression.t regression-quiet: @@ -400,9 +397,7 @@ bin-install: -cp -rp \ bin/rt-mailgate \ bin/mason_handler.fcgi \ - bin/mason_handler.scgi \ bin/mason_handler.svc \ - bin/rt \ bin/webmux.pl \ bin/rt-crontool \ $(DESTDIR)/$(RT_BIN_PATH) @@ -1,46 +1,88 @@ -RT is an enterprise-grade issue tracking system. It allows organizations -to keep track of what needs to get done, who is working on which tasks, -what's already been done, and when tasks were (or weren't) completed. - -RT doesn't cost anything to use, no matter how much you use it; it -is freely available under the terms of Version 2 of the GNU General -Public License. - -RT is commercially-supported software. To purchase support, training, -custom development, or professional services, please get in touch with -us at sales@bestpractical.com. +# BEGIN LICENSE BLOCK +# +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# +# (Except where explictly superceded by other copyright notices) +# +# 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. +# +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. +# +# +# END LICENSE BLOCK +RT is an enterprise-grade issue tracking system. It allows +organizations to keep track of their to-do lists, who is working +on which tasks, what's already been done, and when tasks were +completed. It is available under the terms of version 2 of the GNU +General Public License (GPL), so it doesn't cost anything to set +up and use. - Jesse Vincent - Best Practical Solutions, LLC - March, 2005 + Jesse Vincent + Best Practical Solutions, LLC + March 2003 REQUIRED PACKAGES: ------------------ -o Perl 5.8.3 or later (http://www.perl.com). +o Perl 5.8.0 or later (http://www.perl.com). - Perl versions prior to 5.8.3 contain bugs that could result - in data corruption. We recommend strongly that you use 5.8.3 - or newer. + (If you intend to use the FastCGI or SpeedyCGI support, you + need to make sure that perl has been built with support for + setgid perl scripts.)` -o A supported SQL database + Perl 5.6.1 is currently deprecated and will be officially desupported + in a future release - Currently supported: Mysql 4.0.13 or later with InnoDB support. +o A DB backend; MySQL is recommended ( http://www.mysql.com ) + Currently supported: Mysql 4.0.13 or later. Postgres 7.2 or later. - Oracle 9iR2 or later. - SQLite 3.0. (Not recommended for production) + + Mysql 3.23.46 or newer with support for InnoDB + is currently deprecated and will be officially + desupported in a future release. o Apache version 1.3.x or 2.x (http://httpd.apache.org) - with mod_perl -- (http://perl.apache.org ) - or a webserver with FastCGI support (www.fastcgi.com) + with mod_perl -- (http://perl.apache.org ) + or a webserver with FastCGI support (www.fastcgi.com) + + mod_perl 2.0 isn't quite ready for prime_time just yet; + Best Practical Solutions strongly recommends that sites use + Apache 1.3 or FastCGI. Compiling mod_perl on Apache 1.3.x as a DSO has been known - to have massive stability problems and is not recommended. + to have massive stability problems and is not recommended. + + mod_perl 1.x must be build with EVERYTHING=1 + + RT's FastCGI handler runs setgid to the 'rt' group to + protect RT's database password. You may need to install + a special "suidperl" package or reconfigure your perl + setup to support "setuid scripts" if you intend to use RT + with FastCGI. + + Debian GNU/* 3.0+: the package which installs suidperl is + called perl-suid, and should work without any tweaking. + + FreeBSD 4.2+: the package is called sperl, and should + install a suidperl that just works + + Conectiva Linux 6.0+: suidperl is installed by default when + perl is installed, but the program /bin/suidperl is not setuid. + You must use chmod to make it setuid. - mod_perl 1.x must be built with EVERYTHING=1 - RT's FastCGI handler needs to access RT's configuration file. o Various and sundry perl modules A tool included with RT takes care of the installation of @@ -48,189 +90,133 @@ o Various and sundry perl modules The tool supplied with RT uses Perl's CPAN system (http://www.cpan.org) to install modules. Some operating - systems package all or some of the modules required, and + systems package all or some of the modules required and you may be better off installing the modules that way. GENERAL INSTALLATION -------------------- -This is a rough guide to installing RT. For more detail, you'll -want to read a more comprehensive installation guide at: +This is a rough guide to installing RT. For more detail, you'll want +to read 'Chapter 2: Installing' in RT's manual, available at +http://www.bestpractical.com/rt - http://wiki.bestpractical.com/index.cgi?InstallationGuides +1 Unpack this distribution SOMWHERE OTHER THAN where you want to install RT -1 Unpack this distribution other than where you want to install RT + Granted, you've already got it open. To do this cleanly: - To do this cleanly, run the following command: - - tar xzvf rt.tar.gz -C /tmp + tar xzvf rt.tar.gz -C /tmp 2 Run the "configure" script. - ./configure --help to see the list of options - ./configure (with the flags you want) - - RT defaults to installing in /opt/rt3 with MySQL as its database. It - tries to guess which of www-data, www, apache or nobody your webserver - will run as, but you can override that behavior. - -3 Make sure that RT has everything it needs to run. - - Check for missing dependencies by running: - - make testdeps - -4 If the script reports any missing dependencies, install them by hand - or run the following command as a user who has permission to install perl - modules on your system: - - make fixdeps - -5 Check to make sure everything was installed properly. - - make testdeps - - It might sometimes be necessary to run "make fixdeps" several times - to install all necessary perl modules. - -6 If this is a new installation: - - As a user with permission to install RT in your chosen directory, type: - - make install - - Set up etc/RT_SiteConfig.pm in your RT installation directory. - You'll need to add any values you need to change from the defaults - in etc/RT_Config.pm - - As a user with permission to read RT's configuration file, type: - - make initialize-database + ./configure --help to see the list of options + ./configure (with the flags you want) - If the make fails, type: - - make dropdb +3 Satisfy RT's myriad dependencies. - and start over from step 6 +3.1 Check for compliance: + + perl sbin/rt-test-dependencies \ + --with-<databasename> --with-<web-environment> -7 If you're upgrading from RT 3.0 or newer: + databasename is one of: mysql, postgres + web-environment is one of: fastcgi, modperl1, modperl2 - Read through the UPGRADING document included in this distribution. - - It includes special upgrade instructions that will help you get this - new version of RT up and running smoothly. +3.2 If there are unsatisfied dependencies, install them by hand or run: - As a user with permission to install RT in your chosen installation - directory, type: + perl sbin/rt-test-dependencies \ + --with-<databasename> --with-<web-environment> --install + - make upgrade +3.3 Check to make sure everything was installed properly: - This will install new binaries, config files and libraries without - overwriting your RT database. + perl sbin/rt-test-dependencies \ + --with-<databasename> --with-<web-environment> - Update etc/RT_SiteConfig.pm in your RT installation directory. - You'll need to add any new values you need to change from the defaults - in etc/RT_Config.pm +4 Create a group called 'rt' - You may also need to update RT's database. To find out, type: +5a FOR A NEW INSTALLATION: + + As root, type: + make install (replace "make" with the local name for + Make, if you need to) - ls etc/upgrade + + make initialize-database - For each item in that directory whose name is greater than - your previously installed RT version, run: - /opt/rt3/sbin/rt-setup-database --action schema \ - --datadir etc/upgrade/<version> - /opt/rt3/sbin/rt-setup-database --action acl \ - --datadir etc/upgrade/<version> - /opt/rt3/sbin/rt-setup-database --action insert \ - --datadir etc/upgrade/<version> + If the make fails, type: + make dropdb + and start over from step 5a - Clear mason cache dir: +5b FOR UPGRADING: (Within the RT 3.0.x series) - rm -fr /opt/rt3/var/mason_data/obj + As root, type: + make upgrade (replace "make" with the local name for + Make, if you need to) - Stop and start web-server. + This will build new binaries, config files and libraries without + overwriting your RT database. + + It may then instruct you to update your RT system database objects +6 Edit etc/RT_SiteConfig.pm in your RT installation directory, by specifying + any values you need to change from the defaults in etc/RT_Config.pm -8 If you're upgrading from RT 2.0: +7 Configure the email and web gateways, as described below. - Please upgrade from RT 2.0 to RT 3.2 and then follow the instructions - for section 7. - -9 Configure the email and web gateways, as described below. +8 Stop and start your webserver, so it picks up your configuration changes. NOTE: root's password for the web interface is "password" - (without the quotes). Not changing this is a SECURITY risk! + (without the quotes.) Not changing this is a SECURITY risk -10 Set up users, groups, queues, scrips and access control. +9 Configure RT per the instructions in RT's manual. Until you do this, RT will not be able to send or receive email, nor will it be more than marginally functional. This is not an optional step. -SETTING UP THE WEB INTERFACE ----------------------------- - -RT's web interface is based around HTML::Mason, which works well with -the mod_perl perl interpreter within Apache httpd and FastCGI - -mod_perl --------- +THE WEB INTERFACE +----------------- -To install RT with mod_perl, you'll need to install the -apache database connection cache. To make sure it's installed, run -the following command: +RT's web interface is based around HTML::Mason, which works best with the mod_perl +perl interpreter within Apache httpd. Alternatively, support for the FastCGI +(and plain CGI) interface is also provided as 'bin/mason_handler.fcgi'. - perl -MCPAN -e'install Apache::DBI' - -Next, add a few lines to your Apache configuration file, so that -it knows where to find RT: +Apache + You'll need to add a few lines to your httpd.conf telling it about RT: <VirtualHost your.ip.address> ServerName your.rt.server.hostname DocumentRoot /opt/rt3/share/html AddDefaultCharset UTF-8 + # this line applies to Apache2+mod_perl2 only + PerlModule Apache2 Apache::compat + PerlModule Apache::DBI PerlRequire /opt/rt3/bin/webmux.pl + # this section applies to Apache 1 only <Location /> - SetHandler perl-script - PerlHandler RT::Mason + SetHandler perl-script + PerlHandler RT::Mason </Location> -</VirtualHost> - -FastCGI -------- - -Installation with FastCGI is a little bit more complex and is documented -in detail at http://wiki.bestpractical.com/index.cgi?FastCGIConfiguration - -In the most basic configuration, you can set up your webserver to run -as a user who is a member of the "rt" unix group so that the FastCGI script -can read RT's configuration file. It's important to understand the security -implications of this configuration, which are discussed in the document -mentioned above. - -To install RT with FastCGI, you'll need to add a few lines to your -Apache configuration file telling it about RT: - -<VirtualHost rt.example.com> - # Pass through requests to display images - Alias /NoAuth/images/ /opt/rt3/share/html/NoAuth/images/ - - # Tell FastCGI to put its temporary files somewhere sane. - FastCgiIpcDir /tmp - - FastCgiServer /opt/rt3/bin/mason_handler.fcgi -idle-timeout 120 - - AddHandler fastcgi-script fcgi - ScriptAlias / /opt/rt3/bin/mason_handler.fcgi/ - + # this section applies to Apache2+mod_perl2 only + <FilesMatch "\.html$"> + SetHandler perl-script + PerlHandler RT::Mason + </FilesMatch> + <LocationMatch "/Attachment/"> + SetHandler perl-script + PerlHandler RT::Mason + </LocationMatch> + <LocationMatch "/REST/"> + SetHandler perl-script + PerlHandler RT::Mason + </LocationMatch> </VirtualHost> @@ -238,63 +224,55 @@ Apache configuration file telling it about RT: SETTING UP THE MAIL GATEWAY --------------------------- -To let email flow to your RT server, you need to add a few lines of -configuration to your mail server's "aliases" file. These lines "pipe" -incoming email messages from your mail server to RT. - -Add the following lines to /etc/aliases (or your local equivalent) on your mail server: +An alias for the initial queue will need to be made in either your +global mail aliases file (if you are using NIS) or locally on your +machine. + +Add the following lines to /etc/aliases (or your local equivalent) : -rt: "|/opt/rt3/bin/rt-mailgate --queue general --action correspond --url http://rt.example.com/" -rt-comment: "|/opt/rt3/bin/rt-mailgate --queue general --action comment --url http://rt.example.com/" +rt: "|/opt/rt3/bin/rt-mailgate --queue general --action correspond --url http://localhost/" +rt-comment: "|/opt/rt3/bin/rt-mailgate --queue general --action comment --url http://localhost/" + | | | + <queue-name>----/ | | + | | + <correspond or comment depending on whether | | + the mail should be resent to the requestor>---/ | + | + <URL for RT's web interface>---/ -You'll need to add similar lines for each queue you want to be able -to send email to. To find out more about how to configure RT's email -gateway, type: - - perldoc /opt/rt3/bin/rt-mailgate +BUGS +---- +To report a bug, send email to rt-3.0-bugs@fsck.com. GETTING HELP ------------ If RT is mission-critical for you or if you use it heavily, we recommend that you purchase a commercial support contract. Details on support contracts -are available at http://www.bestpractical.com or by writing to -<sales@bestpractical.com>. +are available at http://www.bestpractical.com. If you're interested in having RT extended or customized or would like more information about commercial support options, please send email to <sales@bestpractical.com> to discuss rates and availability. - -RT WEBSITE ----------- - -For current information about RT, check out the RT website at - http://www.bestpractical.com/ - -You'll find screenshots, a pointer to the current version of RT, contributed -patches, and lots of other great stuff. - - - -RT-USERS MAILING LIST +RT-USERS MAILINGLIST -------------------- To keep up to date on the latest RT tips, techniques and extensions, you probably want to join the rt-users mailing list. Send a message to: - rt-users-request@lists.bestpractical.com + rt-users-request@lists.fsck.com -with the body of the message consisting of only the word: +With the body of the message consisting of only the word: - subscribe + subscribe If you're interested in hacking on RT, you'll want to subscribe to -rt-devel@lists.bestpractical.com. Subscribe to it with instructions -similar to those above. +rt-devel@lists.fsck.com. Subscribe to it with instructions similar to +those above. Address questions about the stable release to the rt-users list, and questions about the development version to the rt-devel list. If you feel @@ -302,61 +280,21 @@ your questions are best not asked publicly, send them personally to <jesse@bestpractical.com>. +RT WEBSITE +---------- -BUGS ----- +For current information about RT, check out the RT website at + http://www.bestpractical.com/ + +You'll find screenshots, a pointer to the current version of RT, contributed +patches, and lots of other great stuff. -RT's a pretty complex application, and as you get up to speed, you might -run into some trouble. Generally, it's best to ask about things you -run into on the rt-users mailinglist (or pick up a commercial support -contract from Best Practical). But, sometimes people do run into bugs. In -the exceedingly unlikely event that you hit a bug in RT, please report -it! We'd love to hear about problems you have with RT, so we can fix them. -To report a bug, send email to rt-bugs@fsck.com. +TROUBLESHOOTING +--------------- -# BEGIN BPS TAGGED BLOCK {{{ -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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 }}} +If the solution to the problem you're running into isn't obvious and you've +checked the FAQ, feel free to send mail to rt-users@fsck.com (for released +versions of RT) or rt-devel@fsck.com (for development versions). + +Thanks! diff --git a/rt/bin/mason_handler.fcgi b/rt/bin/mason_handler.fcgi index 93d1f8855..431eccbd3 100755 --- a/rt/bin/mason_handler.fcgi +++ b/rt/bin/mason_handler.fcgi @@ -27,7 +27,7 @@ use strict; use File::Basename; require ('/opt/rt3/bin/webmux.pl'); -my $h = &RT::Interface::Web::NewCGIHandler(@RT::MasonParameters); +my $h = &RT::Interface::Web::NewCGIHandler(); # Enter CGI::Fast mode, which should also work as a vanilla CGI script. require CGI::Fast; @@ -44,25 +44,11 @@ while ( my $cgi = CGI::Fast->new ) { $ENV{'ENV'} = '' if defined $ENV{'ENV'}; $ENV{'IFS'} = '' if defined $ENV{'IFS'}; - RT::ConnectToDatabase(); - - if ( ( !$h->interp->comp_exists( $cgi->path_info ) ) - && ( $h->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) { - $cgi->path_info( $cgi->path_info . "/index.html" ); - } - - eval { $h->handle_cgi_object($cgi); }; - if ($@) { - $RT::Logger->crit($@); - } - - - if ($RT::Handle->TransactionDepth) { - $RT::Handle->ForceRollback; - $RT::Logger->crit("Transaction not committed. Usually indicates a software fault. Data loss may have occurred") ; + unless ($h->interp->comp_exists($cgi->path_info)) { + $cgi->path_info($cgi->path_info . "/index.html"); } - - + $h->handle_cgi_object($cgi); + # _should_ always be tied } 1; diff --git a/rt/bin/mason_handler.scgi b/rt/bin/mason_handler.scgi index 7774189ee..8e1135c2f 100755 --- a/rt/bin/mason_handler.scgi +++ b/rt/bin/mason_handler.scgi @@ -26,18 +26,16 @@ use strict; require ('/opt/rt3/bin/webmux.pl'); -my $h = &RT::Interface::Web::NewCGIHandler(@RT::MasonParameters); +my $h = &RT::Interface::Web::NewCGIHandler(); require CGI; RT::Init(); my $cgi = CGI->new; -if ( ( !$h->interp->comp_exists( $cgi->path_info ) ) - && ( $h->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) { - $cgi->path_info( $cgi->path_info . "/index.html" ); +unless ($h->interp->comp_exists($cgi->path_info)) { + $cgi->path_info($cgi->path_info . "/index.html"); } - $h->handle_cgi_object($cgi); 1; diff --git a/rt/bin/rt b/rt/bin/rt deleted file mode 100755 index d9f8a3f05..000000000 --- a/rt/bin/rt +++ /dev/null @@ -1,1816 +0,0 @@ -#!/usr/bin/perl -w -# BEGIN LICENSE BLOCK -# -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -# -# (Except where explictly superceded by other copyright notices) -# -# 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. -# -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -# -# -# END LICENSE BLOCK - -use strict; - -# This program is intentionally written to have as few non-core module -# dependencies as possible. It should stay that way. - -use Cwd; -use LWP; -use HTTP::Request::Common; - -# We derive configuration information from hardwired defaults, dotfiles, -# and the RT* environment variables (in increasing order of precedence). -# Session information is stored in ~/.rt_sessions. - -my $VERSION = 0.02; -my $HOME = eval{(getpwuid($<))[7]} - || $ENV{HOME} || $ENV{LOGDIR} || $ENV{HOMEPATH} - || "."; -my %config = ( - ( - debug => 0, - user => eval{(getpwuid($<))[0]} || $ENV{USER} || $ENV{USERNAME}, - passwd => undef, - server => 'http://localhost/rt/', - ), - config_from_file($ENV{RTCONFIG} || ".rtrc"), - config_from_env() -); -my $session = new Session("$HOME/.rt_sessions"); -my $REST = "$config{server}/REST/1.0"; - -sub whine; -sub DEBUG { warn @_ if $config{debug} >= shift } - -# These regexes are used by command handlers to parse arguments. -# (XXX: Ask Autrijus how i18n changes these definitions.) - -my $name = '[\w.-]+'; -my $field = '[a-zA-Z][a-zA-Z0-9_-]*'; -my $label = '[a-zA-Z0-9@_.+-]+'; -my $labels = "(?:$label,)*$label"; -my $idlist = '(?:(?:\d+-)?\d+,)*(?:\d+-)?\d+'; - -# Our command line looks like this: -# -# rt <action> [options] [arguments] -# -# We'll parse just enough of it to decide upon an action to perform, and -# leave the rest to per-action handlers to interpret appropriately. - -my %handlers = ( -# handler => [ ...aliases... ], - version => ["version", "ver"], - logout => ["logout"], - help => ["help", "man"], - show => ["show", "cat"], - edit => ["create", "edit", "new", "ed"], - list => ["search", "list", "ls"], - comment => ["comment", "correspond"], - link => ["link", "ln"], - merge => ["merge"], - grant => ["grant", "revoke"], -); - -# Once we find and call an appropriate handler, we're done. - -my (%actions, $action); -foreach my $fn (keys %handlers) { - foreach my $alias (@{ $handlers{$fn} }) { - $actions{$alias} = \&{"$fn"}; - } -} -if (@ARGV && exists $actions{$ARGV[0]}) { - $action = shift @ARGV; -} -$actions{$action || "help"}->($action || ()); -exit; - -# Handler functions. -# ------------------ -# -# The following subs are handlers for each entry in %actions. - -sub version { - print "rt $VERSION\n"; -} - -sub logout { - submit("$REST/logout") if defined $session->cookie; -} - -sub help { - my ($action, $type) = @_; - my (%help, $key); - - # What help topics do we know about? - local $/ = undef; - foreach my $item (@{ Form::parse(<DATA>) }) { - my $title = $item->[2]{Title}; - my @titles = ref $title eq 'ARRAY' ? @$title : $title; - - foreach $title (grep $_, @titles) { - $help{$title} = $item->[2]{Text}; - } - } - - # What does the user want help with? - undef $action if ($action && $actions{$action} eq \&help); - unless ($action || $type) { - # If we don't know, we'll look for clues in @ARGV. - foreach (@ARGV) { - if (exists $help{$_}) { $key = $_; last; } - } - unless ($key) { - # Tolerate possibly plural words. - foreach (@ARGV) { - if ($_ =~ s/s$// && exists $help{$_}) { $key = $_; last; } - } - } - } - - if ($type && $action) { - $key = "$type.$action"; - } - $key ||= $type || $action || "introduction"; - - # Find a suitable topic to display. - while (!exists $help{$key}) { - if ($type && $action) { - if ($key eq "$type.$action") { $key = $action; } - elsif ($key eq $action) { $key = $type; } - else { $key = "introduction"; } - } - else { - $key = "introduction"; - } - } - - print STDERR $help{$key}, "\n\n"; -} - -# Displays a list of objects that match some specified condition. - -sub list { - my ($q, $type, %data, $orderby); - my $bad = 0; - - while (@ARGV) { - $_ = shift @ARGV; - - if (/^-t$/) { - $bad = 1, last unless defined($type = get_type_argument()); - } - elsif (/^-S$/) { - $bad = 1, last unless get_var_argument(\%data); - } - elsif (/^-o$/) { - $orderby = shift @ARGV; - } - elsif (/^-([isl])$/) { - $data{format} = $1; - } - elsif (/^-f$/) { - if ($ARGV[0] !~ /^(?:(?:$field,)*$field)$/) { - whine "No valid field list in '-f $ARGV[0]'."; - $bad = 1; last; - } - $data{fields} = shift @ARGV; - } - elsif (!defined $q && !/^-/) { - $q = $_; - } - else { - my $datum = /^-/ ? "option" : "argument"; - whine "Unrecognised $datum '$_'."; - $bad = 1; last; - } - } - - $type ||= "ticket"; - unless ($type && defined $q) { - my $item = $type ? "query string" : "object type"; - whine "No $item specified."; - $bad = 1; - } - return help("list", $type) if $bad; - - my $r = submit("$REST/search/$type", { query => $q, %data, orderby => $orderby || "" }); - print $r->content; -} - -# Displays selected information about a single object. - -sub show { - my ($type, @objects, %data); - my $slurped = 0; - my $bad = 0; - - while (@ARGV) { - $_ = shift @ARGV; - - if (/^-t$/) { - $bad = 1, last unless defined($type = get_type_argument()); - } - elsif (/^-S$/) { - $bad = 1, last unless get_var_argument(\%data); - } - elsif (/^-([isl])$/) { - $data{format} = $1; - } - elsif (/^-$/ && !$slurped) { - chomp(my @lines = <STDIN>); - foreach (@lines) { - unless (is_object_spec($_, $type)) { - whine "Invalid object on STDIN: '$_'."; - $bad = 1; last; - } - push @objects, $_; - } - $slurped = 1; - } - elsif (/^-f$/) { - if ($ARGV[0] !~ /^(?:(?:$field,)*$field)$/) { - whine "No valid field list in '-f $ARGV[0]'."; - $bad = 1; last; - } - $data{fields} = shift @ARGV; - } - elsif (my $spec = is_object_spec($_, $type)) { - push @objects, $spec; - } - else { - my $datum = /^-/ ? "option" : "argument"; - whine "Unrecognised $datum '$_'."; - $bad = 1; last; - } - } - - unless (@objects) { - whine "No objects specified."; - $bad = 1; - } - return help("show", $type) if $bad; - - my $r = submit("$REST/show", { id => \@objects, %data }); - print $r->content; -} - -# To create a new object, we ask the server for a form with the defaults -# filled in, allow the user to edit it, and send the form back. -# -# To edit an object, we must ask the server for a form representing that -# object, make changes requested by the user (either on the command line -# or interactively via $EDITOR), and send the form back. - -sub edit { - my ($action) = @_; - my (%data, $type, @objects); - my ($cl, $text, $edit, $input, $output); - - use vars qw(%set %add %del); - %set = %add = %del = (); - my $slurped = 0; - my $bad = 0; - - while (@ARGV) { - $_ = shift @ARGV; - - if (/^-e$/) { $edit = 1 } - elsif (/^-i$/) { $input = 1 } - elsif (/^-o$/) { $output = 1 } - elsif (/^-t$/) { - $bad = 1, last unless defined($type = get_type_argument()); - } - elsif (/^-S$/) { - $bad = 1, last unless get_var_argument(\%data); - } - elsif (/^-$/ && !($slurped || $input)) { - chomp(my @lines = <STDIN>); - foreach (@lines) { - unless (is_object_spec($_, $type)) { - whine "Invalid object on STDIN: '$_'."; - $bad = 1; last; - } - push @objects, $_; - } - $slurped = 1; - } - elsif (/^set$/i) { - my $vars = 0; - - while (@ARGV && $ARGV[0] =~ /^($field)([+-]?=)(.*)$/) { - my ($key, $op, $val) = ($1, $2, $3); - my $hash = ($op eq '=') ? \%set : ($op =~ /^\+/) ? \%add : \%del; - - vpush($hash, lc $key, $val); - shift @ARGV; - $vars++; - } - unless ($vars) { - whine "No variables to set."; - $bad = 1; last; - } - $cl = $vars; - } - elsif (/^(?:add|del)$/i) { - my $vars = 0; - my $hash = ($_ eq "add") ? \%add : \%del; - - while (@ARGV && $ARGV[0] =~ /^($field)=(.*)$/) { - my ($key, $val) = ($1, $2); - - vpush($hash, lc $key, $val); - shift @ARGV; - $vars++; - } - unless ($vars) { - whine "No variables to set."; - $bad = 1; last; - } - $cl = $vars; - } - elsif (my $spec = is_object_spec($_, $type)) { - push @objects, $spec; - } - else { - my $datum = /^-/ ? "option" : "argument"; - whine "Unrecognised $datum '$_'."; - $bad = 1; last; - } - } - - if ($action =~ /^ed(?:it)?$/) { - unless (@objects) { - whine "No objects specified."; - $bad = 1; - } - } - else { - if (@objects) { - whine "You shouldn't specify objects as arguments to $action."; - $bad = 1; - } - unless ($type) { - whine "What type of object do you want to create?"; - $bad = 1; - } - @objects = ("$type/new"); - } - return help($action, $type) if $bad; - - # We need a form to make changes to. We usually ask the server for - # one, but we can avoid that if we are fed one on STDIN, or if the - # user doesn't want to edit the form by hand, and the command line - # specifies only simple variable assignments. - - if ($input) { - local $/ = undef; - $text = <STDIN>; - } - elsif ($edit || %add || %del || !$cl) { - my $r = submit("$REST/show", { id => \@objects, format => 'l' }); - $text = $r->content; - } - - # If any changes were specified on the command line, apply them. - if ($cl) { - if ($text) { - # We're updating forms from the server. - my $forms = Form::parse($text); - - foreach my $form (@$forms) { - my ($c, $o, $k, $e) = @$form; - my ($key, $val); - - next if ($e || !@$o); - - local %add = %add; - local %del = %del; - local %set = %set; - - # Make changes to existing fields. - foreach $key (@$o) { - if (exists $add{lc $key}) { - $val = delete $add{lc $key}; - vpush($k, $key, $val); - $k->{$key} = vsplit($k->{$key}) if $val =~ /[,\n]/; - } - if (exists $del{lc $key}) { - $val = delete $del{lc $key}; - my %val = map {$_=>1} @{ vsplit($val) }; - $k->{$key} = vsplit($k->{$key}); - @{$k->{$key}} = grep {!exists $val{$_}} @{$k->{$key}}; - } - if (exists $set{lc $key}) { - $k->{$key} = delete $set{lc $key}; - } - } - - # Then update the others. - foreach $key (keys %set) { vpush($k, $key, $set{$key}) } - foreach $key (keys %add) { - vpush($k, $key, $add{$key}); - $k->{$key} = vsplit($k->{$key}); - } - push @$o, (keys %add, keys %set); - } - - $text = Form::compose($forms); - } - else { - # We're rolling our own set of forms. - my @forms; - foreach (@objects) { - my ($type, $ids, $args) = - m{^($name)/($idlist|$labels)(?:(/.*))?$}o; - - $args ||= ""; - foreach my $obj (expand_list($ids)) { - my %set = (%set, id => "$type/$obj$args"); - push @forms, ["", [keys %set], \%set]; - } - } - $text = Form::compose(\@forms); - } - } - - if ($output) { - print $text; - exit; - } - - my $synerr = 0; - -EDIT: - # We'll let the user edit the form before sending it to the server, - # unless we have enough information to submit it non-interactively. - if ($edit || (!$input && !$cl)) { - my $newtext = vi($text); - # We won't resubmit a bad form unless it was changed. - $text = ($synerr && $newtext eq $text) ? undef : $newtext; - } - - if ($text) { - my $r = submit("$REST/edit", {content => $text, %data}); - if ($r->code == 409) { - # If we submitted a bad form, we'll give the user a chance - # to correct it and resubmit. - if ($edit || (!$input && !$cl)) { - $text = $r->content; - $synerr = 1; - goto EDIT; - } - else { - print $r->content; - exit -1; - } - } - print $r->content; - } -} - -# We roll "comment" and "correspond" into the same handler. - -sub comment { - my ($action) = @_; - my (%data, $id, @files, @bcc, @cc, $msg, $wtime, $edit); - my $bad = 0; - - while (@ARGV) { - $_ = shift @ARGV; - - if (/^-e$/) { - $edit = 1; - } - elsif (/^-[abcmw]$/) { - unless (@ARGV) { - whine "No argument specified with $_."; - $bad = 1; last; - } - - if (/-a/) { - unless (-f $ARGV[0] && -r $ARGV[0]) { - whine "Cannot read attachment: '$ARGV[0]'."; - exit -1; - } - push @files, shift @ARGV; - } - elsif (/-([bc])/) { - my $a = $_ eq "-b" ? \@bcc : \@cc; - @$a = split /\s*,\s*/, shift @ARGV; - } - elsif (/-m/) { $msg = shift @ARGV } - elsif (/-w/) { $wtime = shift @ARGV } - } - elsif (!$id && m|^(?:ticket/)?($idlist)$|) { - $id = $1; - } - else { - my $datum = /^-/ ? "option" : "argument"; - whine "Unrecognised $datum '$_'."; - $bad = 1; last; - } - } - - unless ($id) { - whine "No object specified."; - $bad = 1; - } - return help($action, "ticket") if $bad; - - my $form = [ - "", - [ "Ticket", "Action", "Cc", "Bcc", "Attachment", "TimeWorked", "Text" ], - { - Ticket => $id, - Action => $action, - Cc => [ @cc ], - Bcc => [ @bcc ], - Attachment => [ @files ], - TimeWorked => $wtime || '', - Text => $msg || '', - } - ]; - - my $text = Form::compose([ $form ]); - - if ($edit || !$msg) { - my $error = 0; - my ($c, $o, $k, $e); - - do { - my $ntext = vi($text); - exit if ($error && $ntext eq $text); - $text = $ntext; - $form = Form::parse($text); - $error = 0; - - ($c, $o, $k, $e) = @{ $form->[0] }; - if ($e) { - $error = 1; - $c = "# Syntax error."; - goto NEXT; - } - elsif (!@$o) { - exit; - } - @files = @{ vsplit($k->{Attachment}) }; - - NEXT: - $text = Form::compose([[$c, $o, $k, $e]]); - } while ($error); - } - - my $i = 1; - foreach my $file (@files) { - $data{"attachment_$i"} = bless([ $file ], "Attachment"); - $i++; - } - $data{content} = $text; - - my $r = submit("$REST/ticket/comment/$id", \%data); - print $r->content; -} - -# Merge one ticket into another. - -sub merge { - my @id; - my $bad = 0; - - while (@ARGV) { - $_ = shift @ARGV; - - if (/^\d+$/) { - push @id, $_; - } - else { - whine "Unrecognised argument: '$_'."; - $bad = 1; last; - } - } - - unless (@id == 2) { - my $evil = @id > 2 ? "many" : "few"; - whine "Too $evil arguments specified."; - $bad = 1; - } - return help("merge", "ticket") if $bad; - - my $r = submit("$REST/ticket/merge/$id[0]", {into => $id[1]}); - print $r->content; -} - -# Link one ticket to another. - -sub link { - my ($bad, $del, %data) = (0, 0, ()); - my %ltypes = map { lc $_ => $_ } qw(DependsOn DependedOnBy RefersTo - ReferredToBy HasMember MemberOf); - - while (@ARGV && $ARGV[0] =~ /^-/) { - $_ = shift @ARGV; - - if (/^-d$/) { - $del = 1; - } - else { - whine "Unrecognised option: '$_'."; - $bad = 1; last; - } - } - - if (@ARGV == 3) { - my ($from, $rel, $to) = @ARGV; - if ($from !~ /^\d+$/ || $to !~ /^\d+$/) { - my $bad = $from =~ /^\d+$/ ? $to : $from; - whine "Invalid ticket ID '$bad' specified."; - $bad = 1; - } - unless (exists $ltypes{lc $rel}) { - whine "Invalid relationship '$rel' specified."; - $bad = 1; - } - %data = (id => $from, rel => $rel, to => $to, del => $del); - } - else { - my $bad = @ARGV < 3 ? "few" : "many"; - whine "Too $bad arguments specified."; - $bad = 1; - } - return help("link", "ticket") if $bad; - - my $r = submit("$REST/ticket/link", \%data); - print $r->content; -} - -# Grant/revoke a user's rights. - -sub grant { - my ($cmd) = @_; - - my $revoke = 0; - while (@ARGV) { - } - - $revoke = 1 if $cmd->{action} eq 'revoke'; -} - -# Client <-> Server communication. -# -------------------------------- -# -# This function composes and sends an HTTP request to the RT server, and -# interprets the response. It takes a request URI, and optional request -# data (a string, or a reference to a set of key-value pairs). - -sub submit { - my ($uri, $content) = @_; - my ($req, $data); - my $ua = new LWP::UserAgent(agent => "RT/3.0b", env_proxy => 1); - - # Did the caller specify any data to send with the request? - $data = []; - if (defined $content) { - unless (ref $content) { - # If it's just a string, make sure LWP handles it properly. - # (By pretending that it's a file!) - $content = [ content => [undef, "", Content => $content] ]; - } - elsif (ref $content eq 'HASH') { - my @data; - foreach my $k (keys %$content) { - if (ref $content->{$k} eq 'ARRAY') { - foreach my $v (@{ $content->{$k} }) { - push @data, $k, $v; - } - } - else { push @data, $k, $content->{$k} } - } - $content = \@data; - } - $data = $content; - } - - # Should we send authentication information to start a new session? - if (!defined $session->cookie) { - push @$data, ( user => $config{user} ); - push @$data, ( pass => $config{passwd} || read_passwd() ); - } - - # Now, we construct the request. - if (@$data) { - $req = POST($uri, $data, Content_Type => 'form-data'); - } - else { - $req = GET($uri); - } - $session->add_cookie_header($req); - - # Then we send the request and parse the response. - DEBUG(3, $req->as_string); - my $res = $ua->request($req); - DEBUG(3, $res->as_string); - - if ($res->is_success) { - # The content of the response we get from the RT server consists - # of an HTTP-like status line followed by optional header lines, - # a blank line, and arbitrary text. - - my ($head, $text) = split /\n\n/, $res->content, 2; - my ($status, @headers) = split /\n/, $head; - $text =~ s/\n*$/\n/; - - # "RT/3.0.1 401 Credentials required" - if ($status !~ m#^RT/\d+(?:\.\d+)+(?:-?\w+)? (\d+) ([\w\s]+)$#) { - warn "rt: Malformed RT response from $config{server}.\n"; - warn "(Rerun with RTDEBUG=3 for details.)\n" if $config{debug} < 3; - exit -1; - } - - # Our caller can pretend that the server returned a custom HTTP - # response code and message. (Doing that directly is apparently - # not sufficiently portable and uncomplicated.) - $res->code($1); - $res->message($2); - $res->content($text); - $session->update($res) if ($res->is_success || $res->code != 401); - - if (!$res->is_success) { - # We can deal with authentication failures ourselves. Either - # we sent invalid credentials, or our session has expired. - if ($res->code == 401) { - my %d = @$data; - if (exists $d{user}) { - warn "rt: Incorrect username or password.\n"; - exit -1; - } - elsif ($req->header("Cookie")) { - # We'll retry the request with credentials, unless - # we only wanted to logout in the first place. - $session->delete; - return submit(@_) unless $uri eq "$REST/logout"; - } - } - # Conflicts should be dealt with by the handler and user. - # For anything else, we just die. - elsif ($res->code != 409) { - warn "rt: ", $res->content; - exit; - } - } - } - else { - warn "rt: Server error: ", $res->message, " (", $res->code, ")\n"; - exit -1; - } - - return $res; -} - -# Session management. -# ------------------- -# -# Maintains a list of active sessions in the ~/.rt_sessions file. -{ - package Session; - my ($s, $u); - - # Initialises the session cache. - sub new { - my ($class, $file) = @_; - my $self = { - file => $file || "$HOME/.rt_sessions", - sids => { } - }; - - # The current session is identified by the currently configured - # server and user. - ($s, $u) = @config{"server", "user"}; - - bless $self, $class; - $self->load(); - - return $self; - } - - # Returns the current session cookie. - sub cookie { - my ($self) = @_; - my $cookie = $self->{sids}{$s}{$u}; - return defined $cookie ? "RT_SID=$cookie" : undef; - } - - # Deletes the current session cookie. - sub delete { - my ($self) = @_; - delete $self->{sids}{$s}{$u}; - } - - # Adds a Cookie header to an outgoing HTTP request. - sub add_cookie_header { - my ($self, $request) = @_; - my $cookie = $self->cookie(); - - $request->header(Cookie => $cookie) if defined $cookie; - } - - # Extracts the Set-Cookie header from an HTTP response, and updates - # session information accordingly. - sub update { - my ($self, $response) = @_; - my $cookie = $response->header("Set-Cookie"); - - if (defined $cookie && $cookie =~ /^RT_SID=([0-9A-Fa-f]+);/) { - $self->{sids}{$s}{$u} = $1; - } - } - - # Loads the session cache from the specified file. - sub load { - my ($self, $file) = @_; - $file ||= $self->{file}; - local *F; - - open(F, $file) && do { - $self->{file} = $file; - my $sids = $self->{sids} = {}; - while (<F>) { - chomp; - next if /^$/ || /^#/; - next unless m#^https?://[^ ]+ \w+ [0-9A-Fa-f]+$#; - my ($server, $user, $cookie) = split / /, $_; - $sids->{$server}{$user} = $cookie; - } - return 1; - }; - return 0; - } - - # Writes the current session cache to the specified file. - sub save { - my ($self, $file) = shift; - $file ||= $self->{file}; - local *F; - - open(F, ">$file") && do { - my $sids = $self->{sids}; - foreach my $server (keys %$sids) { - foreach my $user (keys %{ $sids->{$server} }) { - my $sid = $sids->{$server}{$user}; - if (defined $sid) { - print F "$server $user $sid\n"; - } - } - } - close(F); - chmod 0600, $file; - return 1; - }; - return 0; - } - - sub DESTROY { - my $self = shift; - $self->save; - } -} - -# Form handling. -# -------------- -# -# Forms are RFC822-style sets of (field, value) specifications with some -# initial comments and interspersed blank lines allowed for convenience. -# Sets of forms are separated by --\n (in a cheap parody of MIME). -# -# Each form is parsed into an array with four elements: commented text -# at the start of the form, an array with the order of keys, a hash with -# key/value pairs, and optional error text if the form syntax was wrong. - -# Returns a reference to an array of parsed forms. -sub Form::parse { - my $state = 0; - my @forms = (); - my @lines = split /\n/, $_[0]; - my ($c, $o, $k, $e) = ("", [], {}, ""); - - LINE: - while (@lines) { - my $line = shift @lines; - - next LINE if $line eq ''; - - if ($line eq '--') { - # We reached the end of one form. We'll ignore it if it was - # empty, and store it otherwise, errors and all. - if ($e || $c || @$o) { - push @forms, [ $c, $o, $k, $e ]; - $c = ""; $o = []; $k = {}; $e = ""; - } - $state = 0; - } - elsif ($state != -1) { - if ($state == 0 && $line =~ /^#/) { - # Read an optional block of comments (only) at the start - # of the form. - $state = 1; - $c = $line; - while (@lines && $lines[0] =~ /^#/) { - $c .= "\n".shift @lines; - } - $c .= "\n"; - } - elsif ($state <= 1 && $line =~ /^($field):(?:\s+(.*))?$/) { - # Read a field: value specification. - my $f = $1; - my @v = ($2 || ()); - - # Read continuation lines, if any. - while (@lines && ($lines[0] eq '' || $lines[0] =~ /^\s+/)) { - push @v, shift @lines; - } - pop @v while (@v && $v[-1] eq ''); - - # Strip longest common leading indent from text. - my $ws = ""; - foreach my $ls (map {/^(\s+)/} @v[1..$#v]) { - $ws = $ls if (!$ws || length($ls) < length($ws)); - } - s/^$ws// foreach @v; - - push(@$o, $f) unless exists $k->{$f}; - vpush($k, $f, join("\n", @v)); - - $state = 1; - } - elsif ($line !~ /^#/) { - # We've found a syntax error, so we'll reconstruct the - # form parsed thus far, and add an error marker. (>>) - $state = -1; - $e = Form::compose([[ "", $o, $k, "" ]]); - $e.= $line =~ /^>>/ ? "$line\n" : ">> $line\n"; - } - } - else { - # We saw a syntax error earlier, so we'll accumulate the - # contents of this form until the end. - $e .= "$line\n"; - } - } - push(@forms, [ $c, $o, $k, $e ]) if ($e || $c || @$o); - - foreach my $l (keys %$k) { - $k->{$l} = vsplit($k->{$l}) if (ref $k->{$l} eq 'ARRAY'); - } - - return \@forms; -} - -# Returns text representing a set of forms. -sub Form::compose { - my ($forms) = @_; - my @text; - - foreach my $form (@$forms) { - my ($c, $o, $k, $e) = @$form; - my $text = ""; - - if ($c) { - $c =~ s/\n*$/\n/; - $text = "$c\n"; - } - if ($e) { - $text .= $e; - } - elsif ($o) { - my @lines; - - foreach my $key (@$o) { - my ($line, $sp); - my $v = $k->{$key}; - my @values = ref $v eq 'ARRAY' ? @$v : $v; - - $sp = " "x(length("$key: ")); - $sp = " "x4 if length($sp) > 16; - - foreach $v (@values) { - if ($v =~ /\n/) { - $v =~ s/^/$sp/gm; - $v =~ s/^$sp//; - - if ($line) { - push @lines, "$line\n\n"; - $line = ""; - } - elsif (@lines && $lines[-1] !~ /\n\n$/) { - $lines[-1] .= "\n"; - } - push @lines, "$key: $v\n\n"; - } - elsif ($line && - length($line)+length($v)-rindex($line, "\n") >= 70) - { - $line .= ",\n$sp$v"; - } - else { - $line = $line ? "$line, $v" : "$key: $v"; - } - } - - $line = "$key:" unless @values; - if ($line) { - if ($line =~ /\n/) { - if (@lines && $lines[-1] !~ /\n\n$/) { - $lines[-1] .= "\n"; - } - $line .= "\n"; - } - push @lines, "$line\n"; - } - } - - $text .= join "", @lines; - } - else { - chomp $text; - } - push @text, $text; - } - - return join "\n--\n\n", @text; -} - -# Configuration. -# -------------- - -# Returns configuration information from the environment. -sub config_from_env { - my %env; - - foreach my $k ("DEBUG", "USER", "PASSWD", "SERVER") { - if (exists $ENV{"RT$k"}) { - $env{lc $k} = $ENV{"RT$k"}; - } - } - - return %env; -} - -# Finds a suitable configuration file and returns information from it. -sub config_from_file { - my ($rc) = @_; - - if ($rc =~ m#^/#) { - # We'll use an absolute path if we were given one. - return parse_config_file($rc); - } - else { - # Otherwise we'll use the first file we can find in the current - # directory, or in one of its (increasingly distant) ancestors. - - my @dirs = split /\//, cwd; - while (@dirs) { - my $file = join('/', @dirs, $rc); - if (-r $file) { - return parse_config_file($file); - } - - # Remove the last directory component each time. - pop @dirs; - } - - # Still nothing? We'll fall back to some likely defaults. - for ("$HOME/$rc", "/etc/rt.conf") { - return parse_config_file($_) if (-r $_); - } - } - - return (); -} - -# Makes a hash of the specified configuration file. -sub parse_config_file { - my %cfg; - my ($file) = @_; - - open(CFG, $file) && do { - while (<CFG>) { - chomp; - next if (/^#/ || /^\s*$/); - - if (/^(user|passwd|server)\s+([^ ]+)$/) { - $cfg{$1} = $2; - } - else { - die "rt: $file:$.: unknown configuration directive.\n"; - } - } - }; - - return %cfg; -} - -# Helper functions. -# ----------------- - -sub whine { - my $sub = (caller(1))[3]; - $sub =~ s/^main:://; - warn "rt: $sub: @_\n"; - return; -} - -sub read_passwd { - eval 'require Term::ReadKey'; - if ($@) { - die "No password specified (and Term::ReadKey not installed).\n"; - } - - print "Password: "; - Term::ReadKey::ReadMode('noecho'); - chomp(my $passwd = Term::ReadKey::ReadLine(0)); - Term::ReadKey::ReadMode('restore'); - print "\n"; - - return $passwd; -} - -sub vi { - my ($text) = @_; - my $file = "/tmp/rt.form.$$"; - my $editor = $ENV{EDITOR} || $ENV{VISUAL} || "vi"; - - local *F; - local $/ = undef; - - open(F, ">$file") || die "$file: $!\n"; print F $text; close(F); - system($editor, $file) && die "Couldn't run $editor.\n"; - open(F, $file) || die "$file: $!\n"; $text = <F>; close(F); - unlink($file); - - return $text; -} - -# Add a value to a (possibly multi-valued) hash key. -sub vpush { - my ($hash, $key, $val) = @_; - my @val = ref $val eq 'ARRAY' ? @$val : $val; - - if (exists $hash->{$key}) { - unless (ref $hash->{$key} eq 'ARRAY') { - my @v = $hash->{$key} ne '' ? $hash->{$key} : (); - $hash->{$key} = \@v; - } - push @{ $hash->{$key} }, @val; - } - else { - $hash->{$key} = $val; - } -} - -# "Normalise" a hash key that's known to be multi-valued. -sub vsplit { - my ($val) = @_; - my ($word, @words); - my @values = ref $val eq 'ARRAY' ? @$val : $val; - - foreach my $line (map {split /\n/} @values) { - # XXX: This should become a real parser, à la Text::ParseWords. - $line =~ s/^\s+//; - $line =~ s/\s+$//; - push @words, split /\s*,\s*/, $line; - } - - return \@words; -} - -sub expand_list { - my ($list) = @_; - my ($elt, @elts, %elts); - - foreach $elt (split /,/, $list) { - if ($elt =~ /^(\d+)-(\d+)$/) { push @elts, ($1..$2) } - else { push @elts, $elt } - } - - @elts{@elts}=(); - return sort {$a<=>$b} keys %elts; -} - -sub get_type_argument { - my $type; - - if (@ARGV) { - $type = shift @ARGV; - unless ($type =~ /^[A-Za-z0-9_.-]+$/) { - # We want whine to mention our caller, not us. - @_ = ("Invalid type '$type' specified."); - goto &whine; - } - } - else { - @_ = ("No type argument specified with -t."); - goto &whine; - } - - $type =~ s/s$//; # "Plural". Ugh. - return $type; -} - -sub get_var_argument { - my ($data) = @_; - - if (@ARGV) { - my $kv = shift @ARGV; - if (my ($k, $v) = $kv =~ /^($field)=(.*)$/) { - push @{ $data->{$k} }, $v; - } - else { - @_ = ("Invalid variable specification: '$kv'."); - goto &whine; - } - } - else { - @_ = ("No variable argument specified with -S."); - goto &whine; - } -} - -sub is_object_spec { - my ($spec, $type) = @_; - - $spec =~ s|^(?:$type/)?|$type/| if defined $type; - return $spec if ($spec =~ m{^$name/(?:$idlist|$labels)(?:/.*)?$}o); - return; -} - -__DATA__ - -Title: intro -Title: introduction -Text: - - ** THIS IS AN UNSUPPORTED PREVIEW RELEASE ** - ** PLEASE REPORT BUGS TO rt-bugs@fsck.com ** - - This is a command-line interface to RT 3. - - It allows you to interact with an RT server over HTTP, and offers an - interface to RT's functionality that is better-suited to automation - and integration with other tools. - - In general, each invocation of this program should specify an action - to perform on one or more objects, and any other arguments required - to complete the desired action. - - For more information: - - - rt help actions (a list of possible actions) - - rt help objects (how to specify objects) - - rt help usage (syntax information) - - - rt help config (configuration details) - - rt help examples (a few useful examples) - - rt help topics (a list of help topics) - --- - -Title: usage -Title: syntax -Text: - - Syntax: - - rt <action> [options] [arguments] - - Each invocation of this program must specify an action (e.g. "edit", - "create"), options to modify behaviour, and other arguments required - by the specified action. (For example, most actions expect a list of - numeric object IDs to act upon.) - - The details of the syntax and arguments for each action are given by - "rt help <action>". Some actions may be referred to by more than one - name ("create" is the same as "new", for example). - - Objects are identified by a type and an ID (which can be a name or a - number, depending on the type). For some actions, the object type is - implied (you can only comment on tickets); for others, the user must - specify it explicitly. See "rt help objects" for details. - - In syntax descriptions, mandatory arguments that must be replaced by - appropriate value are enclosed in <>, and optional arguments are - indicated by [] (for example, <action> and [options] above). - - For more information: - - - rt help objects (how to specify objects) - - rt help actions (a list of actions) - - rt help types (a list of object types) - --- - -Title: conf -Title: config -Title: configuration -Text: - - This program has two major sources of configuration information: its - configuration files, and the environment. - - The program looks for configuration directives in a file named .rtrc - (or $RTCONFIG; see below) in the current directory, and then in more - distant ancestors, until it reaches /. If no suitable configuration - files are found, it will also check for ~/.rtrc and /etc/rt.conf. - - Configuration directives: - - The following directives may occur, one per line: - - - server <URL> URL to RT server. - - user <username> RT username. - - passwd <passwd> RT user's password. - - Blank and #-commented lines are ignored. - - Environment variables: - - The following environment variables override any corresponding - values defined in configuration files: - - - RTUSER - - RTPASSWD - - RTSERVER - - RTDEBUG Numeric debug level. (Set to 3 for full logs.) - - RTCONFIG Specifies a name other than ".rtrc" for the - configuration file. - --- - -Title: objects -Text: - - Syntax: - - <type>/<id>[/<attributes>] - - Every object in RT has a type (e.g. "ticket", "queue") and a numeric - ID. Some types of objects can also be identified by name (like users - and queues). Furthermore, objects may have named attributes (such as - "ticket/1/history"). - - An object specification is like a path in a virtual filesystem, with - object types as top-level directories, object IDs as subdirectories, - and named attributes as further subdirectories. - - A comma-separated list of names, numeric IDs, or numeric ranges can - be used to specify more than one object of the same type. Note that - the list must be a single argument (i.e., no spaces). For example, - "user/root,1-3,5,7-10,ams" is a list of ten users; the same list - can also be written as "user/ams,root,1,2,3,5,7,8-20". - - Examples: - - ticket/1 - ticket/1/attachments - ticket/1/attachments/3 - ticket/1/attachments/3/content - ticket/1-3/links - ticket/1-3,5-7/history - - user/ams - user/ams/rights - user/ams,rai,1/rights - - For more information: - - - rt help <action> (action-specific details) - - rt help <type> (type-specific details) - --- - -Title: actions -Title: commands -Text: - - You can currently perform the following actions on all objects: - - - list (list objects matching some condition) - - show (display object details) - - edit (edit object details) - - create (create a new object) - - Each type may define actions specific to itself; these are listed in - the help item about that type. - - For more information: - - - rt help <action> (action-specific details) - - rt help types (a list of possible types) - --- - -Title: types -Text: - - You can currently operate on the following types of objects: - - - tickets - - users - - groups - - queues - - For more information: - - - rt help <type> (type-specific details) - - rt help objects (how to specify objects) - - rt help actions (a list of possible actions) - --- - -Title: ticket -Text: - - Tickets are identified by a numeric ID. - - The following generic operations may be performed upon tickets: - - - list - - show - - edit - - create - - In addition, the following ticket-specific actions exist: - - - link - - merge - - comment - - correspond - - Attributes: - - The following attributes can be used with "rt show" or "rt edit" - to retrieve or edit other information associated with tickets: - - links A ticket's relationships with others. - history All of a ticket's transactions. - history/type/<type> Only a particular type of transaction. - history/id/<id> Only the transaction of the specified id. - attachments A list of attachments. - attachments/<id> The metadata for an individual attachment. - attachments/<id>/content The content of an individual attachment. - --- - -Title: user -Title: group -Text: - - Users and groups are identified by name or numeric ID. - - The following generic operations may be performed upon them: - - - list - - show - - edit - - create - - In addition, the following type-specific actions exist: - - - grant - - revoke - - Attributes: - - The following attributes can be used with "rt show" or "rt edit" - to retrieve or edit other information associated with users and - groups: - - rights Global rights granted to this user. - rights/<queue> Queue rights for this user. - --- - -Title: queue -Text: - - Queues are identified by name or numeric ID. - - Currently, they can be subjected to the following actions: - - - show - - edit - - create - --- - -Title: logout -Text: - - Syntax: - - rt logout - - Terminates the currently established login session. You will need to - provide authentication credentials before you can continue using the - server. (See "rt help config" for details about authentication.) - --- - -Title: ls -Title: list -Title: search -Text: - - Syntax: - - rt <ls|list|search> [options] "query string" - - Displays a list of objects matching the specified conditions. - ("ls", "list", and "search" are synonyms.) - - Conditions are expressed in the SQL-like syntax used internally by - RT3. (For more information, see "rt help query".) The query string - must be supplied as one argument. - - (Right now, the server doesn't support listing anything but tickets. - Other types will be supported in future; this client will be able to - take advantage of that support without any changes.) - - Options: - - The following options control how much information is displayed - about each matching object: - - -i Numeric IDs only. (Useful for |rt edit -; see examples.) - -s Short description. - -l Longer description. - - In addition, - - -o +/-<field> Orders the returned list by the specified field. - -S var=val Submits the specified variable with the request. - -t type Specifies the type of object to look for. (The - default is "ticket".) - - Examples: - - rt ls "Priority > 5 and Status='new'" - rt ls -o +Subject "Priority > 5 and Status='new'" - rt ls -o -Created "Priority > 5 and Status='new'" - rt ls -i "Priority > 5"|rt edit - set status=resolved - rt ls -t ticket "Subject like '[PATCH]%'" - --- - -Title: show -Text: - - Syntax: - - rt show [options] <object-ids> - - Displays details of the specified objects. - - For some types, object information is further classified into named - attributes (for example, "1-3/links" is a valid ticket specification - that refers to the links for tickets 1-3). Consult "rt help <type>" - and "rt help objects" for further details. - - This command writes a set of forms representing the requested object - data to STDOUT. - - Options: - - - Read IDs from STDIN instead of the command-line. - -t type Specifies object type. - -f a,b,c Restrict the display to the specified fields. - -S var=val Submits the specified variable with the request. - - Examples: - - rt show -t ticket -f id,subject,status 1-3 - rt show ticket/3/attachments/29 - rt show ticket/3/attachments/29/content - rt show ticket/1-3/links - rt show -t user 2 - --- - -Title: new -Title: edit -Title: create -Text: - - Syntax: - - rt edit [options] <object-ids> set field=value [field=value] ... - add field=value [field=value] ... - del field=value [field=value] ... - - Edits information corresponding to the specified objects. - - If, instead of "edit", an action of "new" or "create" is specified, - then a new object is created. In this case, no numeric object IDs - may be specified, but the syntax and behaviour remain otherwise - unchanged. - - This command typically starts an editor to allow you to edit object - data in a form for submission. If you specified enough information - on the command-line, however, it will make the submission directly. - - The command line may specify field-values in three different ways. - "set" sets the named field to the given value, "add" adds a value - to a multi-valued field, and "del" deletes the corresponding value. - Each "field=value" specification must be given as a single argument. - - For some types, object information is further classified into named - attributes (for example, "1-3/links" is a valid ticket specification - that refers to the links for tickets 1-3). These attributes may also - be edited. Consult "rt help <type>" and "rt help object" for further - details. - - Options: - - - Read numeric IDs from STDIN instead of the command-line. - (Useful with rt ls ... | rt edit -; see examples below.) - -i Read a completed form from STDIN before submitting. - -o Dump the completed form to STDOUT instead of submitting. - -e Allows you to edit the form even if the command-line has - enough information to make a submission directly. - -S var=val - Submits the specified variable with the request. - -t type Specifies object type. - - Examples: - - # Interactive (starts $EDITOR with a form). - rt edit ticket/3 - rt create -t ticket - - # Non-interactive. - rt edit ticket/1-3 add cc=foo@example.com set priority=3 - rt ls -t tickets -i 'Priority > 5' | rt edit - set status=resolved - rt edit ticket/4 set priority=3 owner=bar@example.com \ - add cc=foo@example.com bcc=quux@example.net - rt create -t ticket subject='new ticket' priority=10 \ - add cc=foo@example.com - --- - -Title: comment -Title: correspond -Text: - - Syntax: - - rt <comment|correspond> [options] <ticket-id> - - Adds a comment (or correspondence) to the specified ticket (the only - difference being that comments aren't sent to the requestors.) - - This command will typically start an editor and allow you to type a - comment into a form. If, however, you specified all the necessary - information on the command line, it submits the comment directly. - - (See "rt help forms" for more information about forms.) - - Options: - - -m <text> Specify comment text. - -a <file> Attach a file to the comment. (May be used more - than once to attach multiple files.) - -c <addrs> A comma-separated list of Cc addresses. - -b <addrs> A comma-separated list of Bcc addresses. - -w <time> Specify the time spent working on this ticket. - -e Starts an editor before the submission, even if - arguments from the command line were sufficient. - - Examples: - - rt comment -t 'Not worth fixing.' -a stddisclaimer.h 23 - --- - -Title: merge -Text: - - Syntax: - - rt merge <from-id> <to-id> - - Merges the two specified tickets. - --- - -Title: link -Text: - - Syntax: - - rt link [-d] <id-A> <relationship> <id-B> - - Creates (or, with -d, deletes) a link between the specified tickets. - The relationship can (irrespective of case) be any of: - - DependsOn/DependedOnBy: A depends upon B (or vice versa). - RefersTo/ReferredToBy: A refers to B (or vice versa). - MemberOf/HasMember: A is a member of B (or vice versa). - - To view a ticket's relationships, use "rt show ticket/3/links". (See - "rt help ticket" and "rt help show".) - - Options: - - -d Deletes the specified link. - - Examples: - - rt link 2 dependson 3 - rt link -d 4 referredtoby 6 # 6 no longer refers to 4 - --- - -Title: grant -Title: revoke -Text: - --- - -Title: query -Text: - - RT3 uses an SQL-like syntax to specify object selection constraints. - See the <RT:...> documentation for details. - - (XXX: I'm going to have to write it, aren't I?) - --- - -Title: form -Title: forms -Text: - - This program uses RFC822 header-style forms to represent object data - in a form that's suitable for processing both by humans and scripts. - - A form is a set of (field, value) specifications, with some initial - commented text and interspersed blank lines allowed for convenience. - Field names may appear more than once in a form; a comma-separated - list of multiple field values may also be specified directly. - - Field values can be wrapped as in RFC822, with leading whitespace. - The longest sequence of leading whitespace common to all the lines - is removed (preserving further indentation). There is no limit on - the length of a value. - - Multiple forms are separated by a line containing only "--\n". - - (XXX: A more detailed specification will be provided soon. For now, - the server-side syntax checking will suffice.) - --- - -Title: topics -Text: - - Use "rt help <topic>" for help on any of the following subjects: - - - tickets, users, groups, queues. - - show, edit, ls/list/search, new/create. - - - query (search query syntax) - - forms (form specification) - - - objects (how to specify objects) - - types (a list of object types) - - actions/commands (a list of actions) - - usage/syntax (syntax details) - - conf/config/configuration (configuration details) - - examples (a few useful examples) - --- - -Title: example -Title: examples -Text: - - This section will be filled in with useful examples, once it becomes - more clear what examples may be useful. - - For the moment, please consult examples provided with each action. - --- diff --git a/rt/bin/rt-commit-handler.in b/rt/bin/rt-commit-handler.in deleted file mode 100644 index 02b01abff..000000000 --- a/rt/bin/rt-commit-handler.in +++ /dev/null @@ -1,846 +0,0 @@ -#!@PERL@ -w -# BEGIN LICENSE BLOCK -# -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -# -# (Except where explictly superceded by other copyright notices) -# -# 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. -# -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -# -# -# END LICENSE BLOCK - -# {{{ Docs -# -*-Perl-*- -# -#ident "@(#)ccvs/contrib:$Name: $:$Id: rt-commit-handler.in,v 1.1 2003-07-15 13:16:15 ivan Exp $" -# -# Perl filter to handle the log messages from the checkin of files in multiple -# directories. This script will group the lists of files by log message, and -# send one piece of mail per unique message, no matter how many files are -# committed. - -=head1 NAME rt-commit-handler - -=head1 USAGE - - - -=head2 Regular use - -Stick the following in in CVSROOT/commitinfo - - ALL @RT_BIN_PATH@/rt-commit-handler --record-last-dir - -Stick the following in CVSROOT/loginfo - - ALL @RT_BIN_PATH@/rt-commit-handler --cvs-root /pathtocvs/root --rt %{Vvts} - -=head2 Invocation (advanced use) - -rt-commit-handler --cvs-root /path/to/cvs/root [-d] [-D] [-r] [-M module] \ - [[-m mailto] ...] [[-R replyto] ...] [-f logfile] - - - -d - turn on debugging - -m mailto - send mail to "mailto" (multiple) - -R replyto - set the "Reply-To:" to "replyto" (multiple) - -M modulename - set module name to "modulename" - -f logfile - write commit messages to logfile too - -D - generate diff commands - --rt - invoke RT commit handler - --cvs-root - specify your CVS root - - --record-last-dir - Record the last directory with changes in - pre-commit (commitinfo) mode - - -=cut - -# }}} - -use strict; -use Carp; -use Getopt::Long; -use Text::Wrap; -use Digest::MD5; -use MIME::Entity; - -use lib ("@RT_LIB_PATH@", "@LOCAL_LIB_PATH@"); - -use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc); - -use vars - qw(@MAILER $TMPDIR $FILE_PREFIX $LASTDIR_FILE $HASH_FILE $VERSION_FILE $MESSAGE_FILE $MAIL_FILE $DEBUG $MAILTO $REPLYTO $id $MODULE_NAME - $LOGIN $COMMITLOG $CVS_ROOT $RT_HANDLER); - -#Clean out all the nasties from the environment -CleanEnv(); - -#Load etc/config.pm and drop privs -RT::LoadConfig(); - -#Drop setgid permissions -RT::DropSetGIDPermissions(); - -# {{{ Variable setup -$TMPDIR = '/tmp'; -$FILE_PREFIX = $TMPDIR . '/#cvs.'; - -# The root of your CVS install. we should get this from some smarter place. -# It needs a trailing / - -$LASTDIR_FILE = $FILE_PREFIX . "lastdir"; -$HASH_FILE = $FILE_PREFIX . "hash"; -$VERSION_FILE = $FILE_PREFIX . "version"; -$MESSAGE_FILE = $FILE_PREFIX . "message"; -$MAIL_FILE = $FILE_PREFIX . "mail"; - -$DEBUG = 0; -$RT_HANDLER = 1; - -$MAILTO = ''; - -my @files = (); -my (@log_lines); -my $do_diff = 0; -my $id = getpgrp(); # note, you *must* use a shell which does setpgrp() -$LOGIN = getpwuid($<); - -# }}} - -die "User could not be found" unless ($LOGIN); - -# {{{ parse command line arguments (file list is seen as one arg) -# -while ( my $arg = shift @ARGV ) { - - if ( $arg eq '-d' ) { - $DEBUG = 1; - warn "Debug turned on...\n"; - } - elsif ( $arg =~ /^--record-last-dir$/i ) { - record_last_dir( $id, $ARGV[0] ); - exit(0); - } - elsif ( $arg eq '-m' ) { - $MAILTO .= ", " if $MAILTO; - $MAILTO .= shift @ARGV; - } - elsif ( $arg eq '--rt' ) { - $RT_HANDLER = 1; - } - elsif ( $arg eq '-R' ) { - $REPLYTO .= ", " if $REPLYTO; - $REPLYTO .= shift @ARGV; - } - elsif ( $arg eq '-M' ) { - die ("too many '-M' args\n") if $MODULE_NAME; - $MODULE_NAME = shift @ARGV; - } - elsif ( $arg eq '--cvs-root' ) { - $CVS_ROOT = shift @ARGV; - $CVS_ROOT .= "/" unless ( $CVS_ROOT =~ /\/$/ ); - } - elsif ( $arg eq '-f' ) { - die ("too many '-f' args\n") if $COMMITLOG; - $COMMITLOG = shift @ARGV; - - # This is a disgusting hack to untaint $COMMITLOG if we're running from - # setgid cvs. - $COMMITLOG = untaint($COMMITLOG); - } - elsif ( $arg eq '-D' ) { - $do_diff = 1; - } - else { - @files = split ( ' ', $arg ); - last; - } -} - -# }}} - -$REPLYTO = $LOGIN unless ($REPLYTO); - -# for now, the first "file" is the repository directory being committed, -# relative to the $CVSROOT location -# -my $dir = shift @files; - -# XXX there are some ugly assumptions in here about module names and -# XXX directories relative to the $CVSROOT location -- really should -# XXX read $CVSROOT/CVSROOT/modules, but that's not so easy to do, since -# XXX we have to parse it backwards. -# -# XXX For now we set the `module' name to the top-level directory name. -# -unless ($MODULE_NAME) { - ($MODULE_NAME) = split ( '/', $dir, 2 ); -} - -if ($DEBUG) { - warn "module - ", $MODULE_NAME, "\n"; - warn "dir - ", $dir, "\n"; - warn "files - ", join ( " ", @files ), "\n"; - warn "id - ", $id, "\n"; -} - -# {{{ Check for a new directory or an import command. - -# -# files[0] - "-" -# files[1] - "New" -# files[2] - "directory" -# -# files[0] - "-" -# files[1] - "Imported" -# files[2] - "sources" -# -if ( $files[0] eq "-" ) { - - #we just don't care about New Directory notes - unless ( $files[1] eq "New" && $files[2] eq "directory" ) { - - my @text = (); - - push @text, build_header(); - push @text, ""; - - while ( my $line = <STDIN> ) { - chop $line; # Drop the newline - push @text, $line; - } - - append_logfile( $COMMITLOG, @text ) if ($COMMITLOG); - - mail_notification( $id, @text ); - } - - exit 0; -} - -# }}} - -# {{{ Collect just the log message from stdin. -# - -while ( my $line = <STDIN> ) { - chop $line; # strip the newline - last if ( $line =~ /^Log Message:$/ ); -} -while ( my $line = <STDIN> ) { - chop $line; # strip the newline - $line =~ s/\s+$//; # strip trailing white space - push @log_lines, $line; -} - -my $md5 = Digest::MD5->new(); -foreach my $line (@log_lines) { - $md5->add( $line . "\n" ); -} -my $hash = $md5->hexdigest(); - -warn "hash = $hash\n" if ($DEBUG); - -if ( !-e "$MESSAGE_FILE.$id.$hash" ) { - append_logfile( "$HASH_FILE.$id", $hash ); - write_file( "$MESSAGE_FILE.$id.$hash", @log_lines ); -} - -# }}} - -# Spit out the information gathered in this pass. - -append_logfile( "$VERSION_FILE.$id.$hash", $dir . '/', @files ); - -# {{{ Check whether this is the last directory. If not, quit. - -warn "Checking current dir against last dir $LASTDIR_FILE.$id\n" if ($DEBUG); - -my @last_dir = read_file("$LASTDIR_FILE.$id"); - -unless ($CVS_ROOT) { - die "No cvs root specified with --cvs-root. Can't continue."; -} - -if ( $last_dir[0] ne $CVS_ROOT . $dir ) { - warn "Current directory $CVS_ROOT$dir is not last directory $last_dir[0].\n" - if ($DEBUG); - exit 0; -} - -# }}} - -# {{{ End Of Commits! -# - -# This is it. The commits are all finished. Lump everything together -# into a single message, fire a copy off to the mailing list, and drop -# it on the end of the Changes file. -# - -# -# Produce the final compilation of the log messages -# - -my @hashes = read_file("$HASH_FILE.$id"); -my (@text); - -push @text, build_header(); -push @text, ""; - -my ( @added_files, @modified_files, @removed_files ); - -foreach my $hash (@hashes) { - - # In case we're running setgid, make sure the hash file hasn't been hacked. - $hash =~ m/([a-z0-9]*)/ || die "*** Hacking attempt detected\n"; - $hash = $1; - - my @files = read_file("$VERSION_FILE.$id.$hash"); - my @log_lines = read_file("$MESSAGE_FILE.$id.$hash"); - - my $working_on_dir; # gets set as we iterate through the files. - foreach my $file (@files) { - - #If we've entered a new directory, make a note of that and remove the trailing / - - if ( $file =~ s'\/$'' ) { - $working_on_dir = $file; - next; - } - - my @file_entry = ( split ( ',', $file, 4 ), $working_on_dir ); - - # file_entry looks like ths: - - # 0 1 2 3 4 - # Old rev : new rev : tag: file :directory - my $entry = {}; - $entry->{'old'} = $file_entry[0]; - $entry->{'new'} = $file_entry[1]; - $entry->{'tag'} = $file_entry[2]; - $entry->{'file'} = $file_entry[3]; - $entry->{'dir'} = $file_entry[4]; - - if ( $file_entry[0] eq 'NONE' ) { - $entry->{'old'} = '0'; - push @added_files, $entry; - } - elsif ( $file_entry[1] eq 'NONE' ) { - $entry->{'new'} = '0'; - push @removed_files, $entry; - } - else { - push @modified_files, $entry; - } - } -} - -# }}} - -# {{{ start building up the body - -# Strip leading and trailing blank lines from the log message. Also -# compress multiple blank lines in the body of the message down to a -# single blank line. -# - -my $blank = 1; -@log_lines = map { - my $wasblank = $blank; - $blank = $_ eq ''; - $blank && $wasblank ? () : $_; -} @log_lines; - -pop @log_lines if $blank; - -@modified_files = order_and_summarize_diffs(@modified_files); -@added_files = order_and_summarize_diffs(@added_files); -@removed_files = order_and_summarize_diffs(@removed_files); - -push @text, "Modified Files:", format_lists(@modified_files) - if (@modified_files); - -push @text, "Added Files:", format_lists(@added_files) if (@added_files); - -push @text, "Removed Files:", format_lists(@removed_files) if (@removed_files); - -push @text, "", "Log Message", @log_lines if (@log_lines); - -push @text, ""; - -if ($RT_HANDLER) { - rt_handler( - @log_lines, "\n", - loc("To generate a diff of this commit:\n"), "\n", - format_diffs( @modified_files, @added_files, @removed_files ) - ); -} - -if ($COMMITLOG) { - append_logfile( $COMMITLOG, @text ); -} - -if ($do_diff) { - push @text, ""; - push @text, loc("To generate a diff of this commit:"); - push @text, format_diffs( @modified_files, @added_files, @removed_files ); - push @text, ""; -} - -# }}} - -# {{{ Mail out the notification. - -mail_notification( $id, @text ); - -# }}} - -# {{{ clean up - -unless ($DEBUG) { - $hash = untaint($hash); - $id = untaint($id); - unlink "$VERSION_FILE.$id.$hash"; - unlink "$MESSAGE_FILE.$id.$hash"; - unlink "$MAIL_FILE.$id"; - unlink "$LASTDIR_FILE.$id"; - unlink "$HASH_FILE.$id"; -} - -# }}} - -exit 0; - -# {{{ Subroutines -# - -# {{{ append_logfile -sub append_logfile { - my $filename = shift; - my (@lines) = @_; - - $filename = untaint($filename); - - open( FILE, ">>$filename" ) - || die ("Cannot open file $filename for append.\n"); - foreach my $line (@lines) { - print FILE $line . "\n"; - } - close(FILE); -} - -# }}} - -# {{{ write_file -sub write_file { - my $filename = shift; - my (@lines) = @_; - - $filename = untaint($filename); - - open( FILE, ">$filename" ) - || die ("Cannot open file $filename for write.\n"); - foreach my $line (@lines) { - print FILE $line . "\n"; - } - close(FILE); -} - -# }}} - -# {{{ read_file -sub read_file { - my $filename = shift; - my (@lines); - - open( FILE, "<$filename" ) - || die ("Cannot open file $filename for read.\n"); - while ( my $line = <FILE> ) { - chop $line; - push @lines, $line; - } - close(FILE); - - return (@lines); -} - -# }}} - -# {{{ sub format_lists - -sub format_lists { - my @items = (@_); - - my $files = ""; - map { - $_->{'files'} && ( $files .= ' ' . join ( ' ', @{ $_->{'files'} } ) ); - } @items; - - my @lines = wrap( "\t", "\t\t", $files ); - return (@lines); - -} - -# }}} - -# {{{ sub format_diffs - -sub format_diffs { - my @items = (@_); - - my @lines; - foreach my $item (@items) { - next unless ( $item->{'files'} ); - push ( @lines, - "cvs diff -r" - . $item->{'old'} . " -r" - . $item->{'new'} . " " - . join ( " ", @{ $item->{'files'} } ) . "\n" ); - - } - - @lines = fill( "\t", "\t\t", @lines ); - - return (@lines); -} - -# }}} - -# {{{ sub order_and_summarize_diffs { - -# takes an array of file items -# returns a sorted array of fileset items, which are like file items, except they can have an array of files, rather than -# a singleton file. - -sub order_and_summarize_diffs { - - my @files = (@_); - - # Sort by tag, dir, file. - @files = sort { - $a->{'tag'} cmp $b->{'tag'} - || $a->{'dir'} cmp $b->{'dir'} - || $a->{'file'} cmp $b->{'file'}; - } @files; - - # Combine adjacent rows that are the same modulo the file name. - - my @items = (undef); - - foreach my $file (@files) { - if ( $#items == -1 #if it's empty - || ( !defined $items[-1]->{'old'} - || $items[-1]->{'old'} ne $file->{'old'} ) - || ( !defined $items[-1]->{'new'} - || $items[-1]->{'new'} ne $file->{'new'} ) - || ( !defined $items[-1]->{'tag'} - || $items[-1]->{'tag'} ne $file->{'tag'} ) ) - { - - push ( @items, $file ); - } - push ( @{ $items[-1]->{'files'} }, - $file->{'dir'} . "/" . $file->{'file'} ); - } - - return (@items); -} - -# }}} - -# {{{ build_header - -sub build_header { - my $now = gmtime; - my $header = - sprintf( "Module Name:\t%s\nCommitted By:\t%s\nDate:\t\t%s %s %s", - $MODULE_NAME, $LOGIN, substr( $now, 0, 19 ), "UTC", - substr( $now, 20, 4 ) ); - return ($header); -} - -# }}} - -# {{{ mail_notification -sub mail_notification { - my $id = shift; - my (@text) = @_; - write_file( "$MAIL_FILE.$id", "From: " . $LOGIN, - "Subject: CVS commit: " . $MODULE_NAME, "To: " . $MAILTO, - "Reply-To: " . $REPLYTO, "", "", @text ); - - my $entity = MIME::Entity->build( - From => $LOGIN, - To => $MAILTO, - Subject => "CVS commit: " . $MODULE_NAME, - 'Reply-To' => $REPLYTO, - Data => join ( "\n", @text ) - ); - if ( $RT::MailCommand eq 'sendmailpipe' ) { - open( MAIL, "|$RT::SendmailPath $RT::SendmailArguments" ) - || die "Couldn't send mail: " . $@ . "\n"; - print MAIL $entity->as_string; - close(MAIL); - } - else { - $entity->send( $RT::MailCommand, $RT::MailParams ); - } - -} - -# }}} - -# {{{ sub record_last_dir - -sub record_last_dir { - my $id = shift; - my $dir = shift; - - # make a note of this directory. later, we'll use this to - # figure out if we've gone through the whole commit, - # for something that is a bad mockery of attomic commits. - - warn "about to write $dir to $LASTDIR_FILE.$id" if ($DEBUG); - - write_file( "$LASTDIR_FILE.$id", $dir ); -} - -# }}} - -# {{{ Get the RT stuff set up - -# {{{ sub rt_handler - -sub rt_handler { - my (@LogMessage) = (@_); - - #Connect to the database and get RT::SystemUser and RT::Nobody loaded - RT::Init; - - require RT::Ticket; - - #Get the current user all loaded - my $CurrentUser = GetCurrentUser(); - - if ( !$CurrentUser->Id ) { - print -loc("No valid RT user found. RT cvs handler disengaged. Please consult your RT administrator.\n"); - return; - } - - my (@commands) = find_commands( \@LogMessage ); - - my ( @tickets, @errors ); - - # Get the list of tickets we're working with out of commands - grep { $_ =~ /^RT-Ticket:\s*(.*?)$/i && push ( @tickets, $1 ) } @commands; - - my $message = new MIME::Entity; - $message->build( - From => $CurrentUser->EmailAddress, - Subject => 'CVS Commit', - Data => \@LogMessage - ); - - # {{{ comment or correspond, as needed - - foreach my $ticket (@tickets) { - my $TicketObj = RT::Ticket->new($CurrentUser); - $TicketObj->Load($ticket); - my ( $id, $msg ); - unless ( $TicketObj->Id ) { - push ( @errors, -"Couldn't load ticket #$ticket. Not adding commit log to ticket history.\n" - ); - } - - if ( $LogMessage[0] =~ /^(comment|private)$/ ) { - ( $id, $msg ) = $TicketObj->Comment( MIMEObj => $message ); - - } - else { - ( $id, $msg ) = $TicketObj->Correspond( MIMEObj => $message ); - } - - push ( @errors, ">> Log message", - "Ticket #" . $TicketObj->Id . ": " . $msg ); - - } - - # }}} - - my ($reply) = ActOnPseudoHeaders( $CurrentUser, @commands ); - print "$reply\n" if ($reply); - print join ( "\n", @errors ); - print "\n"; - -} - -# }}} - -# {{{ sub find_commands - -sub find_commands { - my $lines = shift; - my (@pseudoheaders); - - while ( my $line = shift @{$lines} ) { - next if $line =~ /^\s*?$/; - if ( $line =~ /^RT-/i ) { - - push ( @pseudoheaders, $line ); - } - - #If we find a line that's not a command, get out. - else { - unshift ( @{$lines}, $line ); - last; - } - } - - return (@pseudoheaders); - -} - -# }}} - -# {{{ sub ActOnPseudoHeaders - -=item ActOnPseudoHeaders $PseudoHeaders - -Takes a string of pseudo-headers, iterates through them and does what they tell it to. - -=cut - -sub ActOnPseudoHeaders { - my $CurrentUser = shift; - my (@actions) = (@_); - - my $ResultsMessage = ''; - my $Ticket = RT::Ticket->new($CurrentUser); - - foreach my $action (@actions) { - my ($val); - my $msg = ''; - - $ResultsMessage .= ">>> $action\n"; - - if ( $action =~ /^RT-(.*?):\s*(.*)$/i ) { - my $command = $1; - my $args = $2; - - if ( $command =~ /^ticket$/i ) { - - $val = $Ticket->Load($args); - unless ($val) { - $ResultsMessage .= - loc("ERROR: Couldn't load ticket '[_1]': [_2].\n", $1, $msg); - . loc("Aborting to avoid unintended ticket modifications.\n") - . loc("The following commands were not proccessed:\n\n") - . join ( "\n", @actions ); - return ($ResultsMessage); - } - $ResultsMessage .= loc("Ticket [_1] loaded\n", $Ticket->Id); - } - else { - unless ( $Ticket->Id ) { - $ResultsMessage .= loc("No Ticket specified. Aborting ticket ") - . loc("modifications\n\n") - . loc("The following commands were not proccessed:\n\n") - . join ( "\n", @actions ); - return ($ResultsMessage); - } - - # Deal with the basics - if ( $command =~ /^(Subject|Owner|Status|Queue)$/i ) { - my $method = 'Set' . ucfirst( lc($1) ); - ( $val, $msg ) = $Ticket->$method($args); - } - - # Deal with the dates - elsif ( $command =~ /^(due|starts|started|resolved)$/i ) { - my $method = 'Set' . ucfirst( lc($1) ); - my $date = new RT::Date($CurrentUser); - $date->Set( Format => 'unknown', Value => $args ); - ( $val, $msg ) = $Ticket->$method( $date->ISO ); - } - - # Deal with the watchers - elsif ( $command =~ /^(requestor|requestors|cc|admincc)$/i ) { - my $operator = "+"; - my ($type); - if ( $args =~ /^(\+|\-)(.*)$/ ) { - $operator = $1; - $args = $2; - } - $type = 'Requestor' if ( $command =~ /^requestor/i ); - $type = 'Cc' if ( $command =~ /^cc/i ); - $type = 'AdminCc' if ( $command =~ /^admincc/i ); - - my $user = RT::User->new($CurrentUser); - $user->Load($args); - - if ($operator eq '+') { - ($val, $msg) = $Ticket->AddWatcher( Type => $type, - PrincipalId => $user->PrincipalId); - } elsif ($operator eq '-') { - ($val, $msg) = $Ticket->DeleteWatcher( Type => $type, - PrincipalId => $user->PrincipalId); - } - - } - $ResultsMessage .= $msg . "\n"; - } - - } - return ($ResultsMessage); - -} - -# }}} - -# {{{ sub untaint -sub untaint { - my $val = shift; - - if ( $val =~ /^([-\#\/\w.]+)$/ ) { - $val = $1; # $data now untainted - } - else { - die loc("Bad data in [_1]", $val); # log this somewhere - } - return ($val); -} - -# }}} - -=head1 AUTHOR - - - - rt-commit-handler is a rewritten version of the NetBSD commit handler, - which was placed in the public domain by Charles Hannum. It bore the following - authors statement: - - Contributed by David Hampton <hampton@cisco.com> - Hacked greatly by Greg A. Woods <woods@planix.com> - Rewritten by Charles M. Hannum <mycroft@netbsd.org> - -=cut - diff --git a/rt/bin/rt-mailgate b/rt/bin/rt-mailgate index 8af800227..b30443638 100755 --- a/rt/bin/rt-mailgate +++ b/rt/bin/rt-mailgate @@ -1,26 +1,26 @@ #!/usr/bin/perl -w # BEGIN LICENSE BLOCK -# +# # Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -# +# # (Except where explictly superceded by other copyright notices) -# +# # 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. -# +# # Unless otherwise specified, all modifications, corrections or # extensions to this work which alter its source code become the # property of Best Practical Solutions, LLC when submitted for # inclusion in the work. -# -# +# +# # END LICENSE BLOCK =head1 NAME @@ -31,25 +31,10 @@ rt-mailgate - Mail interface to RT3. use RT::I18N; -# Make sure that when we call the mailgate wrong, it tempfails - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://bad.address"), "Opened the mailgate - The error below is expected - $@"); -print MAIL <<EOF; -From: root\@localhost -To: rt\@example.com -Subject: This is a test of new ticket creation - -Foob! -EOF -close (MAIL); - -# Check the return value -is ( $? >> 8, 75, "The error message above is expected The mail gateway exited with a failure. yay"); - # {{{ Test new ticket creation by root who is privileged and superuser -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); print MAIL <<EOF; From: root\@localhost To: rt\@example.com @@ -60,9 +45,6 @@ Foob! EOF close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - use RT::Tickets; my $tickets = RT::Tickets->new($RT::SystemUser); $tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); @@ -77,7 +59,7 @@ ok ($tick->Subject eq 'This is a test of new ticket creation', "Created the tick # {{{This is a test of new ticket creation as an unknown user -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); print MAIL <<EOF; From: doesnotexist\@example.com To: rt\@example.com @@ -87,8 +69,6 @@ Blah! Foob! EOF close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); $tickets = RT::Tickets->new($RT::SystemUser); $tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); @@ -114,7 +94,7 @@ ok ($val, "Granted everybody the right to create tickets - $msg"); sleep(60); # gotta sleep so the remote process' ACL cache times out -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); print MAIL <<EOF; From: doesnotexist\@example.com To: rt\@example.com @@ -124,8 +104,6 @@ Blah! Foob! EOF close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); $tickets = RT::Tickets->new($RT::SystemUser); @@ -148,7 +126,7 @@ ok( $u->Id != 0, " user does not exist and was created by ticket submission"); #ok ($val, "Granted everybody the right to create tickets - $msg"); #sleep(60); # gotta sleep so the remote process' ACL cache times out -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); print MAIL <<EOF; From: doesnotexist-2\@example.com To: rt\@example.com @@ -158,8 +136,6 @@ Blah! Foob! EOF close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); $u = RT::User->new($RT::SystemUser); $u->Load('doesnotexist-2@example.com'); @@ -172,7 +148,7 @@ ok( $u->Id == 0, " user does not exist and was not created by ticket corresponde ok ($val, "Granted everybody the right to reply to tickets - $msg"); sleep(60); # gotta sleep so the remote process' ACL cache times out -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); print MAIL <<EOF; From: doesnotexist-2\@example.com To: rt\@example.com @@ -182,8 +158,6 @@ Blah! Foob! EOF close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); $u = RT::User->new($RT::SystemUser); @@ -199,7 +173,7 @@ ok( $u->Id != 0, " user exists and was created by ticket correspondence submissi #ok ($val, "Granted everybody the right to create tickets - $msg"); #sleep(60); # gotta sleep so the remote process' ACL cache times out -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action comment"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action comment"), "Opened the mailgate - $@"); print MAIL <<EOF; From: doesnotexist-3\@example.com To: rt\@example.com @@ -210,9 +184,6 @@ Foob! EOF close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - $u = RT::User->new($RT::SystemUser); $u->Load('doesnotexist-3@example.com'); ok( $u->Id == 0, " user does not exist and was not created by ticket comment submission"); @@ -225,7 +196,7 @@ ok( $u->Id == 0, " user does not exist and was not created by ticket comment sub ok ($val, "Granted everybody the right to reply to tickets - $msg"); sleep(60); # gotta sleep so the remote process' ACL cache times out -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action comment"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action comment"), "Opened the mailgate - $@"); print MAIL <<EOF; From: doesnotexist-3\@example.com To: rt\@example.com @@ -236,8 +207,6 @@ Foob! EOF close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); $u = RT::User->new($RT::SystemUser); $u->Load('doesnotexist-3@example.com'); @@ -258,20 +227,17 @@ my $entity = MIME::Entity->build( From => 'root@localhost', Data => ['This is a test of a binary attachment']); # currently in lib/t/autogen -$entity->attach(Path => '/opt/rt3/share/html/NoAuth/images/spacer.gif', +$entity->attach(Path => '../../../html/NoAuth/images/spacer.gif', Type => 'image/gif', Encoding => 'base64'); # Create a ticket with a binary attachment -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); $entity->print(\*MAIL); close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - my $tickets = RT::Tickets->new($RT::SystemUser); $tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); $tickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); @@ -307,7 +273,7 @@ use LWP::UserAgent; # Grab the binary attachment via the web ui my $ua = LWP::UserAgent->new(); -my $full_url = "http://localhost".$RT::WebPath."/Ticket/Attachment/".$attachment->TransactionId."/".$attachment->id."/spacer.gif?&user=root&pass=password"; +my $full_url = "http://localhost/Ticket/Attachment/".$attachment->TransactionId."/".$attachment->id."/spacer.gif?&user=root&pass=password"; my $r = $ua->get( $full_url); @@ -320,7 +286,7 @@ is($file, $r->content, 'The attachment isn\'t screwed up in download'); # {{{ Simple I18N testing -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); print MAIL <<EOF; From: root\@localhost @@ -335,9 +301,6 @@ bye EOF close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - my $unitickets = RT::Tickets->new($RT::SystemUser); $unitickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); $unitickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); @@ -354,7 +317,7 @@ is ($unitick->Transactions->First->Content, $unitick->Transactions->First->Attac ok($unitick->Transactions->First->Attachments->First->Content =~ /$unistring/i, $unitick->Id." appears to be unicode ". $unitick->Transactions->First->Attachments->First->Id); # supposedly I18N fails on the second message sent in. -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost".$RT::WebPath."/ --queue general --action correspond"), "Opened the mailgate - $@"); +ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); print MAIL <<EOF; From: root\@localhost @@ -369,9 +332,6 @@ bye EOF close (MAIL); -#Check the return value -is ($? >> 8, 0, "The mail gateway exited normally. yay"); - my $tickets2 = RT::Tickets->new($RT::SystemUser); $tickets2->OrderBy(FIELD => 'id', ORDER => 'DESC'); $tickets2->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); @@ -407,7 +367,7 @@ use LWP::UserAgent; use constant EX_TEMPFAIL => 75; my %opts; -GetOptions( \%opts, "queue=s", "action=s", "url=s", "jar=s", "help", "debug", "extension=s", "timeout=i" ); +GetOptions( \%opts, "queue=s", "action=s", "url=s", "jar=s", "help", "debug", "extension=s" ); if ( $opts{help} ) { require Pod::Usage; @@ -421,18 +381,17 @@ for (qw(url)) { } undef $/; +my $message = <>; my $ua = LWP::UserAgent->new(); $ua->cookie_jar( { file => $opts{jar} } ); my %args = ( queue => $opts{queue}, action => $opts{action}, + message => $message, SessionType => 'REST', # Surpress login box ); -# Read the message in from STDIN -$args{'message'} = <>; - if ($opts{'extension'}) { $args{$opts{'extension'}} = $ENV{'EXTENSION'}; @@ -445,7 +404,6 @@ warn "Connecting to $full_url" if $opts{'debug'}; -$ua->timeout(exists($opts{'timeout'}) ? $opts{'timeout'} : 180); my $r = $ua->post( $full_url, {%args} ); check_failure($r); @@ -456,7 +414,7 @@ if ( $content !~ /^(ok|not ok)/ ) { # It's not the server's fault if the mail is bogus. We just want to know that # *something* came out of the server. - warn <<EOF; + die <<EOF RT server error. The RT server which handled your email did not behave as expected. It @@ -465,13 +423,8 @@ said: $content EOF -exit EX_TEMPFAIL; - } -exit; - - sub check_failure { my $r = shift; return if $r->is_success(); @@ -502,11 +455,7 @@ Usual invocation (from MTA): rt-mailgate --action (correspond|comment) --queue queuename --url http://your.rt.server/ - [ --debug ] - [ --extension (queue|action|ticket) ] - [ --timeout seconds ] - - + [ --extension (queue|action|ticket) See C<man rt-mailgate> for more. @@ -537,16 +486,6 @@ submitted to will be set to the value of $EXTENSION. By specifying is related to. "action" will allow the user to specify either "comment" or "correspond" in the address extension. -=item C<--debug> OPTIONAL - -Print debugging output to standard error - - -=item C<--timeout> OPTIONAL - -Configure the timeout for posting the message to the web server. The -default timeout is 3 minutes (180 seconds). - =head1 DESCRIPTION diff --git a/rt/bin/webmux.pl b/rt/bin/webmux.pl index 96e7ebf8d..21cb83f5e 100755 --- a/rt/bin/webmux.pl +++ b/rt/bin/webmux.pl @@ -31,7 +31,6 @@ BEGIN { $ENV{'SHELL'} = '/bin/sh' if defined $ENV{'SHELL'}; $ENV{'ENV'} = '' if defined $ENV{'ENV'}; $ENV{'IFS'} = '' if defined $ENV{'IFS'}; - } use lib ("/opt/rt3/local/lib", "/opt/rt3/lib"); @@ -43,17 +42,6 @@ use CGI qw(-private_tempfiles); #bring this in before mason, to make sure we #set private_tempfiles BEGIN { - if ($mod_perl::VERSION >= 1.9908) { - require Apache::RequestUtil; - no warnings 'redefine'; - my $sub = *Apache::request{CODE}; - *Apache::request = sub { - my $r; - eval { $r = $sub->('Apache'); }; - # warn $@ if $@; - return $r; - }; - } if ($CGI::MOD_PERL) { require HTML::Mason::ApacheHandler; } @@ -116,32 +104,21 @@ if ( $CGI::MOD_PERL) { unless ( ( -d _ ) and ( -r _ ) and ( -w _ ) ); } -my $ah = &RT::Interface::Web::NewApacheHandler(@RT::MasonParameters) if $CGI::MOD_PERL; +my $ah = &RT::Interface::Web::NewApacheHandler() if $CGI::MOD_PERL; sub handler { ($r) = @_; - local $SIG{__WARN__}; - local $SIG{__DIE__}; - RT::Init(); # We don't need to handle non-text items return -1 if defined( $r->content_type ) && $r->content_type !~ m|^text/|io; my %session; - my $status; - eval { $status = $ah->handle_request($r) }; - if ($@) { - $RT::Logger->crit($@); - } - + my $status = $ah->handle_request($r); undef (%session); - if ($RT::Handle->TransactionDepth) { - $RT::Handle->ForceRollback; - $RT::Logger->crit("Transaction not committed. Usually indicates a software fault. Data loss may have occurred") ; - } + $RT::Logger->crit("Transaction not committed. Usually indicates a software fault. Data loss may have occurred") if $RT::Handle->TransactionDepth; return $status; } diff --git a/rt/config b/rt/config deleted file mode 100644 index b9418a66d..000000000 --- a/rt/config +++ /dev/null @@ -1,256 +0,0 @@ -/* - * This is the project ``config'' file. It controls many aspects of - * how Aegis interacts with your project. - * - * There are several sections of this file, each dealing with a different - * aspect of the interaction between Aegis and the tools used to manage - * yout project. - */ - -/* - * ------------------------------------------------------------------------- - * - * The build tool is delegated. - */ - -/* - * The build_command field of the config file is used to invoke the relevant - * build command. The following command tells cook where to find the recipes. - * The ${s Howto.cook} expands to a path into the baseline during development - * if the file is not in the change. Look in aesub(5) for more information - * about command substitutions. - */ -build_command = - ""; - -/* cook -book ${s Howto.cook} search_path=$search_path \ -project=$p change=$c version=$v -star -no-log -action -notouch"; - -/* - * The recipes in the User Guide will all remove their targets before - * constructing them, which qualifies them to use the following entry in the - * config file. The targets MUST be removed first if this field is true, - * otherwise the baseline would cease to be self-consistent. - * - * Fortunately, Cook has a nifty ``set unlink;'' statement which is - * placed at the top of the cookbook. - */ -link_integration_directory = true; - - -/* - * ------------------------------------------------------------------------- - * - * The history tool is delegated. - * - * The fhist program was written by David I. Bell and is admirably - * suited to providing a history mechanism with out the "cruft" that - * SCCS and RCS impose. The fhist program also comes with two other - * utilities, fcomp and fmerge, which use the same minimal difference - * algorithm. - * - * Please note that the [# edit #] feature needs to be avoided, or the - * -Fored_Update (-fu) flag needs to be used in addition to the - * -Conditional_Update (-cu) flag, otherwise updates will complain that - * ``Input file "XXX" contains edit A instead of B for module "YYY"'' - * - * The history_create_command and the history_put_command are - * intentionally identical. This minimizes problems when using - * branches. - * - * The ${quote ...} construct is used to quote filesnames whicg contain - * shell special characters. A minimum of quoting is performed, so if - * the filenames do not contail shell special characters, no quotes will - * be used. - */ - -/* - * This command is used to create a new project history. The command is - * always executed as the project owner. Note he the source is left in - * the baseline. The following substitutions are available: - * - * ${Input} - * absolute path of the source file - * ${History} - * absolute path of the history file - * - * The history_create_command and the history_put_command are - * intentionally identical. This minimizes problems when using - * branches. - */ -history_create_command = - "fhist ${quote ${basename $input}} -cr -cu -i ${quote $input} \ --p ${quote ${dirname $history}} -r"; - -/* - * This command is used to get a specific edit back from history. The - * command may be executed by developers. The following substitutions - * are available: - * - * ${History} - * absolute path of the history file - * ${Edit} - * edit number, as given by history_query_command - * ${Output} - * absolute path of the destination file - * - * Note that the destination filename will never look anything like the - * history source filename, so the -p is essential. - */ -history_get_command = - "fhist ${quote ${basename $history}} -e ${quote $e} \ --o ${quote $output} -p ${quote ${dirname $history}}"; - -/* - * This command is used to add a new "top-most" entry to the history - * file. This command is always executed as the project owner. Note - * that the source file is left in the baseline. The following - * substitutions are available: - * - * ${Input} - * absolute path of source file - * ${History} - * absolute path of history file - * - * The history_create_command and the history_put_command are - * intentionally identical. This minimizes problems when using - * branches. - */ -history_put_command = - "fhist ${quote ${basename $input}} -cr -cu -i ${quote $input} \ --p ${quote ${dirname $history}} -r"; - -/* - * This command is used to query what the history mechanism calls the - * "top-most" edit of a history file. The result may be any arbitrary - * string, it need not be anything like a number, just so long as it - * uniquely identifies the edit for use by the history_get_command at a - * later date. The edit number is to be printed on the standard output. - * This command may be executed by developers. The following - * substitutions are available: - * - * ${History} - * absolute path of the history file - */ -history_query_command = - "fhist ${quote ${basename $history}} -l 0 \ --p ${quote ${dirname $history}} -q"; - -/* - * ------------------------------------------------------------------------- - * - * The difference and merge tools are delegated. - */ - -/* - * Compare two files using fcomp. The -w option produces an output of - * the entire file, with insertions an deletions marked by "change bars" - * in the left margin. This is superior to context difference, as it - * shows the entire file as context. The -s option could be added to - * compare runs of white space as equal. - * - * This command is used by aed(1) to produce a difference listing when - * file in the development directory was originally copied from the - * current version in the baseline. - * - * All of the command substitutions described in aesub(5) are available. - * In addition, the following substitutions are also available: - * - * ${ORiginal} - * The absolute path name of a file containing the version - * originally copied. Usually in the baseline. - * ${Input} - * The absolute path name of the edited version of the file. - * Usually in the development directory. - * ${Output} - * The absolute path name of the file in which to write the - * difference listing. Usually in the development directory. - * - * An exit status of 0 means successful, even of the files differ (and - * they usually do). An exit status which is non-zero means something - * is wrong. - * - * The non-zero exit status may be used to overload this command with - * extra tests, such as line length limits. The difference files must - * be produced in addition to these extra tests. - */ -diff_command = - "fcomp -w ${quote $original} ${quote $input} -o ${quote $output}"; - -/* - * Compare three files using fmerge. Conflicts are marked in the - * output. - * - * This command is used by aed(1) to produce a difference listing when a - * file in the development directory is out of date compared to the - * current version in the baseline. - * - * All of the command substitutions described in aesub(5) are available. - * In addition, the following substitutions are also available: - * - * ${ORiginal} - * The absolute path name of a file containing the common ancestor - * version of ${MostRecent} and {$Input}. Usually the version - * originally copied into the change. Usually in a temporary file. - * ${Most_Recent} - * The absolute path name of a file containing the most recent - * version. Usually in the baseline. - * ${Input} - * The absolute path name of the edited version of the file. - * Usually in the development directory. - * ${Output} - * The absolute path name of the file in which to write the - * difference listing. Usually in the development directory. - * - * An exit status of 0 means successful, even of the files differ (and - * they usually do). An exit status which is non-zero means something - * is wrong. - */ -merge_command = - "fmerge ${quote $original} ${quote $MostRecent} ${quote $input} \ --o ${quote $output} -c /dev/null"; - -/* - * ------------------------------------------------------------------------- - * - * The new file templates are very handy. They allow all sorts of things - * to be se automatically. You need to edit them to add your own name, - * and copyright conditions. - */ - -file_template = -[ - { - pattern = [ "*" ]; - body = "${read_file ${source etc/template/generic abs}}"; - - } -]; - -/* ------------------------------------------------------------------------- - * - * The integrate_begin_exceptions are files which are not hard linked - * from the baseline to the integration directory. In this case, this - * is done to ensure the version stmp is updated appropriately. - */ - -integrate_begin_exceptions = [ ]; - - - - -/* ------------------------------------------------------------------------- - * - * The trojan_horse_suspect field is a list of filename patterns which - * indicate files which *could* host a Trojan horse attack. It makes - * aedist --receive more cautions. It is NOT a silver bullet: just - * about ANY file can host a Trojan, one way or the other. - */ - -trojan_horse_suspect = [ ]; - -build_covers_all_architectures = true; - -test_command = "make test"; - -build_time_adjust=dont_adjust; diff --git a/rt/config.layout b/rt/config.layout.in index 5b86eb99e..a08f48948 100644 --- a/rt/config.layout +++ b/rt/config.layout.in @@ -59,31 +59,6 @@ customlibdir: ${customdir}/lib </Layout> -<Layout FHS> - prefix: /usr/local - exec_prefix: ${prefix} - bindir: ${prefix}/bin - sbindir: ${prefix}/sbin - sysconfdir: /etc+ - datadir: ${prefix}/share -# FIXME: missing support for lib64 - libdir: ${prefix}/lib - mandir: ${datadir}/man -# FIXME: no such directory in FHS; shouldn't go to somewhere in "${datadir}/rt/"? - htmldir: ${datadir}/html - manualdir: ${datadir}/doc - localstatedir: /var - logfiledir: ${localstatedir}/log -# XXX: "/var/cache/mason/*"? - masonstatedir: ${localstatedir}/cache/mason_data - sessionstatedir: ${localstatedir}/cache/session_data - customdir: ${prefix}/local - custometcdir: ${customdir}/etc - customhtmldir: ${customdir}/html - customlexdir: ${customdir}/po - customlibdir: ${customdir}/lib -</Layout> - <Layout FreeBSD> prefix: /usr/local exec_prefix: ${prefix} @@ -127,3 +102,26 @@ customlexdir: ${customdir}/po customlibdir: ${customdir}/lib </Layout> + +<Layout Freeside> + prefix: /opt/rt3 + exec_prefix: ${prefix} + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/sbin + sysconfdir: ${prefix}/etc + mandir: ${prefix}/man + libdir: ${prefix}/lib + datadir: ${prefix}/share + htmldir: %%%FREESIDE_DOCUMENT_ROOT%%%/rt + manualdir: ${datadir}/doc + localstatedir: ${prefix}/var + logfiledir: ${localstatedir}/log + masonstatedir: %%%MASONDATA%%% + sessionstatedir: ${localstatedir}/session_data + customdir: ${prefix}/local + custometcdir: ${customdir}/etc + customhtmldir: ${customdir}/html + customlexdir: ${customdir}/po + customlibdir: ${customdir}/lib +</Layout> + diff --git a/rt/config.pld b/rt/config.pld deleted file mode 100644 index c71c7bbdd..000000000 --- a/rt/config.pld +++ /dev/null @@ -1,19 +0,0 @@ -(test "x$prefix" = "xNONE" || test "x$prefix" = "x") && prefix=/opt/rt3 -(test "x$exec_prefix" = "xNONE" || test "x$exec_prefix" = "x") && exec_prefix=${prefix} -bindir=${exec_prefix}/bin -sbindir=${exec_prefix}/sbin -sysconfdir=${prefix}/etc -mandir=${prefix}/man -libdir=${prefix}/lib -datadir=${prefix}/share -(test "x$htmldir" = "xNONE" || test "x$htmldir" = "x") && htmldir=${datadir}/html -(test "x$manualdir" = "xNONE" || test "x$manualdir" = "x") && manualdir=${datadir}/doc -localstatedir=${prefix}/var -(test "x$logfiledir" = "xNONE" || test "x$logfiledir" = "x") && logfiledir=${localstatedir}/log -(test "x$masonstatedir" = "xNONE" || test "x$masonstatedir" = "x") && masonstatedir=${localstatedir}/mason_data -(test "x$sessionstatedir" = "xNONE" || test "x$sessionstatedir" = "x") && sessionstatedir=${localstatedir}/session_data -(test "x$customdir" = "xNONE" || test "x$customdir" = "x") && customdir=${prefix}/local -(test "x$custometcdir" = "xNONE" || test "x$custometcdir" = "x") && custometcdir=${customdir}/etc -(test "x$customhtmldir" = "xNONE" || test "x$customhtmldir" = "x") && customhtmldir=${customdir}/html -(test "x$customlexdir" = "xNONE" || test "x$customlexdir" = "x") && customlexdir=${customdir}/po -(test "x$customlibdir" = "xNONE" || test "x$customlibdir" = "x") && customlibdir=${customdir}/lib diff --git a/rt/etc/RT_SiteConfig.pm b/rt/etc/RT_SiteConfig.pm index 39c99161f..affd36bb3 100644 --- a/rt/etc/RT_SiteConfig.pm +++ b/rt/etc/RT_SiteConfig.pm @@ -14,6 +14,27 @@ # # perl -c /path/to/your/etc/RT_SiteConfig.pm -Set( $rtname, 'example.com'); +#Set( $rtname, 'example.com'); + +$RT::rtname = '%%%RT_DOMAIN%%%'; +$RT::Organization = '%%%RT_DOMAIN%%%'; + +$RT::Timezone = '%%%RT_TIMEZONE%%%'; + +$RT::WebBaseURL = ''; +$RT::WebPath = '/freeside/rt'; + +$RT::WebExternalAuth = 1; +$RT::WebFallbackToInternal = 1; #no +$RT::WebExternalAuto = 1; + +$RT::URI::freeside::IntegrationType = 'Internal'; +$RT::URI::freeside::URL = '%%%FREESIDE_URL%%%'; + +Set($DatabaseHost , ''); + +#perl 5.8.0 - 5.8.2 experiment +#@EmailInputEncodings = qw(iso-8859-1 us-ascii utf-8); # unless (@EmailInputEncodings); +#Set($EmailOutputEncoding , 'iso-8859-1'); 1; diff --git a/rt/etc/acl.Oracle b/rt/etc/acl.Oracle index ac29215c2..c8667c031 100644 --- a/rt/etc/acl.Oracle +++ b/rt/etc/acl.Oracle @@ -1,10 +1,10 @@ sub acl { return ( -"CREATE USER ${RT::DatabaseUser} identified by ${RT::DatabasePassword} ". -"default tablespace USERS " . -"temporary tablespace TEMP " . -"quota unlimited on USERS" , -"grant connect, resource to ${RT::DatabaseUser}" -); +"CREATE USER ${RT::DatabaseUser} identified by ${RT::DatabasePassword}". +"temporary tablespace TEMP" . +"default tablespace USERS" . +"quota unlimited on USERS;" , +"grant connect, resource to ${RT::DatabaseUser};", +"exit;"); } 1; diff --git a/rt/etc/acl.Pg b/rt/etc/acl.Pg index fb625592d..16ea71b2d 100755 --- a/rt/etc/acl.Pg +++ b/rt/etc/acl.Pg @@ -7,42 +7,38 @@ sub acl { attachments_id_seq Attachments - Attributes - attributes_id_seq queues_id_seq - Queues + Queues links_id_seq - Links + Links principals_id_seq - Principals + Principals groups_id_seq - Groups + Groups scripconditions_id_seq - ScripConditions + ScripConditions transactions_id_seq - Transactions + Transactions scrips_id_seq - Scrips + Scrips acl_id_seq - ACL + ACL groupmembers_id_seq - GroupMembers + GroupMembers cachedgroupmembers_id_seq - CachedGroupMembers + CachedGroupMembers users_id_seq - Users + Users tickets_id_seq - Tickets + Tickets scripactions_id_seq - ScripActions + ScripActions templates_id_seq - Templates - objectcustomfieldvalues_id_s - ObjectCustomFieldValues + Templates + ticketcustomfieldvalues_id_s + TicketCustomFieldValues customfields_id_seq - CustomFields - objectcustomfields_id_s - ObjectCustomFields + CustomFields customfieldvalues_id_seq CustomFieldValues sessions diff --git a/rt/etc/acl.mysql b/rt/etc/acl.mysql index 621ef121c..0ecaa3b15 100755 --- a/rt/etc/acl.mysql +++ b/rt/etc/acl.mysql @@ -1,9 +1,8 @@ sub acl { -return () if !$RT::DatabaseUser or $RT::DatabaseUser eq 'root'; return ( "USE mysql;", "DELETE FROM user WHERE user = '${RT::DatabaseUser}';", "DELETE FROM db where db = '${RT::DatabaseName}';", -"GRANT SELECT,INSERT,CREATE,INDEX,UPDATE,DELETE ON ${RT::DatabaseName}.* TO ${RT::DatabaseUser}\@'${RT::DatabaseRTHost}' IDENTIFIED BY '${RT::DatabasePassword}';"); +"GRANT SELECT,INSERT,CREATE,INDEX,UPDATE,DELETE ON ${RT::DatabaseName}.* TO ${RT::DatabaseUser}\@${RT::DatabaseRTHost} IDENTIFIED BY '${RT::DatabasePassword}';"); } 1; diff --git a/rt/etc/schema.Oracle b/rt/etc/schema.Oracle deleted file mode 100644 index 40238b526..000000000 --- a/rt/etc/schema.Oracle +++ /dev/null @@ -1,400 +0,0 @@ - -CREATE SEQUENCE ATTACHMENTS_seq; -CREATE TABLE Attachments ( - id NUMBER(11,0) - CONSTRAINT Attachments_Key PRIMARY KEY, - TransactionId NUMBER(11,0) NOT NULL, - Parent NUMBER(11,0) DEFAULT 0 NOT NULL, - MessageId VARCHAR2(160), - Subject VARCHAR2(255), - Filename VARCHAR2(255), - ContentType VARCHAR2(80), - ContentEncoding VARCHAR2(80), - Content CLOB, - Headers CLOB, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE -); -CREATE INDEX Attachments2 ON Attachments (TransactionId); -CREATE INDEX Attachments3 ON Attachments (Parent, TransactionId); - - -CREATE SEQUENCE QUEUES_seq; -CREATE TABLE Queues ( - id NUMBER(11,0) - CONSTRAINT Queues_Key PRIMARY KEY, - Name VARCHAR2(200) CONSTRAINT Queues_Name_Unique UNIQUE NOT NULL, - Description VARCHAR2(255), - CorrespondAddress VARCHAR2(120), - CommentAddress VARCHAR2(120), - InitialPriority NUMBER(11,0) DEFAULT 0 NOT NULL, - FinalPriority NUMBER(11,0) DEFAULT 0 NOT NULL, - DefaultDueIn NUMBER(11,0) DEFAULT 0 NOT NULL, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE, - Disabled NUMBER(11,0) DEFAULT 0 NOT NULL -); - CREATE INDEX Queues1 ON Queues (lower(Name)); -CREATE INDEX Queues2 ON Queues (Disabled); - - -CREATE SEQUENCE LINKS_seq; -CREATE TABLE Links ( - id NUMBER(11,0) - CONSTRAINT Links_Key PRIMARY KEY, - Base VARCHAR2(240), - Target VARCHAR2(240), - Type VARCHAR2(20) NOT NULL, - LocalTarget NUMBER(11,0) DEFAULT 0 NOT NULL, - LocalBase NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE -); -CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type); -CREATE INDEX Links2 ON Links (Base, Type); -CREATE INDEX Links3 ON Links (Target, Type); -CREATE INDEX Links4 ON Links(Type,LocalBase); - - -CREATE SEQUENCE PRINCIPALS_seq; -CREATE TABLE Principals ( - id NUMBER(11,0) - CONSTRAINT Principals_Key PRIMARY KEY, - PrincipalType VARCHAR2(16), - ObjectId NUMBER(11,0), - Disabled NUMBER(11,0) DEFAULT 0 NOT NULL -); -CREATE UNIQUE INDEX Principals2 ON Principals (ObjectId); - - -CREATE SEQUENCE GROUPS_seq; -CREATE TABLE Groups ( - id NUMBER(11,0) - CONSTRAINT Groups_Key PRIMARY KEY, - Name VARCHAR2(200), - Description VARCHAR2(255), - Domain VARCHAR2(64), - Type VARCHAR2(64), - Instance NUMBER(11,0) DEFAULT 0 -- NOT NULL --- Instance VARCHAR2(64) -); -CREATE INDEX Groups1 ON Groups (lower( Domain), Instance, lower(Type), id); -CREATE INDEX Groups2 ON Groups (lower(Type), Instance, lower(Domain)); - - -CREATE SEQUENCE SCRIPCONDITIONS_seq; -CREATE TABLE ScripConditions ( - id NUMBER(11, 0) - CONSTRAINT ScripConditions_Key PRIMARY KEY, - Name VARCHAR2(200), - Description VARCHAR2(255), - ExecModule VARCHAR2(60), - Argument VARCHAR2(255), - ApplicableTransTypes VARCHAR2(60), - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE -); - - -CREATE SEQUENCE TRANSACTIONS_seq; -CREATE TABLE Transactions ( - id NUMBER(11,0) - CONSTRAINT Transactions_Key PRIMARY KEY, - ObjectType VARCHAR2(255), - ObjectId NUMBER(11,0) DEFAULT 0 NOT NULL, - TimeTaken NUMBER(11,0) DEFAULT 0 NOT NULL, - Type VARCHAR2(20), - Field VARCHAR2(40), - OldValue VARCHAR2(255), - NewValue VARCHAR2(255), - ReferenceType VARCHAR2(255), - OldReference NUMBER(11,0), - NewReference NUMBER(11,0), - Data VARCHAR2(255), - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE -); -CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); - - -CREATE SEQUENCE SCRIPS_seq; -CREATE TABLE Scrips ( - id NUMBER(11,0) - CONSTRAINT Scrips_Key PRIMARY KEY, - Description VARCHAR2(255), - ScripCondition NUMBER(11,0) DEFAULT 0 NOT NULL, - ScripAction NUMBER(11,0) DEFAULT 0 NOT NULL, - ConditionRules CLOB, - ActionRules CLOB, - CustomIsApplicableCode CLOB, - CustomPrepareCode CLOB, - CustomCommitCode CLOB, - Stage VARCHAR2(32), - Queue NUMBER(11,0) DEFAULT 0 NOT NULL, - Template NUMBER(11,0) DEFAULT 0 NOT NULL, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE -); - - -CREATE SEQUENCE ACL_seq; -CREATE TABLE ACL ( - id NUMBER(11,0) - CONSTRAINT ACL_Key PRIMARY KEY, - PrincipalType VARCHAR2(25) NOT NULL, - PrincipalId NUMBER(11,0) NOT NULL, - RightName VARCHAR2(25) NOT NULL, - ObjectType VARCHAR2(25) NOT NULL, - ObjectId NUMBER(11,0) DEFAULT 0 NOT NULL, - DelegatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - DelegatedFrom NUMBER(11,0) DEFAULT 0 NOT NULL -); -CREATE INDEX ACL1 ON ACL(RightName, ObjectType, ObjectId, PrincipalType, PrincipalId); - - -CREATE SEQUENCE GROUPMEMBERS_seq; -CREATE TABLE GroupMembers ( - id NUMBER(11,0) - CONSTRAINT GroupMembers_Key PRIMARY KEY, - GroupId NUMBER(11,0) DEFAULT 0 NOT NULL, - MemberId NUMBER(11,0) DEFAULT 0 NOT NULL -); -CREATE UNIQUE INDEX GroupMembers1 ON GroupMembers (GroupId, MemberId); - - -CREATE SEQUENCE CachedGroupMembers_seq; -CREATE TABLE CachedGroupMembers ( - id NUMBER(11,0) - CONSTRAINT CachedGroupMembers_Key PRIMARY KEY, - GroupId NUMBER(11,0), - MemberId NUMBER(11,0), - Via NUMBER(11,0), - ImmediateParentId NUMBER(11,0), - Disabled NUMBER(11,0) DEFAULT 0 NOT NULL -); -CREATE INDEX DisGrouMem ON CachedGroupMembers (GroupId, MemberId, Disabled); -CREATE INDEX GrouMem ON CachedGroupMembers (GroupId, MemberId); - - -CREATE SEQUENCE USERS_seq; -CREATE TABLE Users ( - id NUMBER(11,0) - CONSTRAINT Users_Key PRIMARY KEY, - Name VARCHAR2(200) CONSTRAINT Users_Name_Unique - unique NOT NULL, - Password VARCHAR2(40), - Comments CLOB, - Signature CLOB, - EmailAddress VARCHAR2(120), - FreeFormContactInfo CLOB, - Organization VARCHAR2(200), - RealName VARCHAR2(120), - NickName VARCHAR2(16), - Lang VARCHAR2(16), - EmailEncoding VARCHAR2(16), - WebEncoding VARCHAR2(16), - ExternalContactInfoId VARCHAR2(100), - ContactInfoSystem VARCHAR2(30), - ExternalAuthId VARCHAR2(100), - AuthSystem VARCHAR2(30), - Gecos VARCHAR2(16), - HomePhone VARCHAR2(30), - WorkPhone VARCHAR2(30), - MobilePhone VARCHAR2(30), - PagerPhone VARCHAR2(30), - Address1 VARCHAR2(200), - Address2 VARCHAR2(200), - City VARCHAR2(100), - State VARCHAR2(100), - Zip VARCHAR2(16), - Country VARCHAR2(50), - Timezone VARCHAR2(50), - PGPKey CLOB, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE -); --- CREATE UNIQUE INDEX Users1 ON Users (Name); - -CREATE INDEX Users2 ON Users( LOWER(name)); -CREATE INDEX Users4 ON Users (lower(EmailAddress)); - - -CREATE SEQUENCE TICKETS_seq; -CREATE TABLE Tickets ( - id NUMBER(11, 0) - CONSTRAINT Tickets_Key PRIMARY KEY, - EffectiveId NUMBER(11,0) DEFAULT 0 NOT NULL, - Queue NUMBER(11,0) DEFAULT 0 NOT NULL, - Type VARCHAR2(16), - IssueStatement NUMBER(11,0) DEFAULT 0 NOT NULL, - Resolution NUMBER(11,0) DEFAULT 0 NOT NULL, - Owner NUMBER(11,0) DEFAULT 0 NOT NULL, - Subject VARCHAR2(200) DEFAULT '[no subject]', - InitialPriority NUMBER(11,0) DEFAULT 0 NOT NULL, - FinalPriority NUMBER(11,0) DEFAULT 0 NOT NULL, - Priority NUMBER(11,0) DEFAULT 0 NOT NULL, - TimeEstimated NUMBER(11,0) DEFAULT 0 NOT NULL, - TimeWorked NUMBER(11,0) DEFAULT 0 NOT NULL, - Status VARCHAR2(10), - TimeLeft NUMBER(11,0) DEFAULT 0 NOT NULL, - Told DATE, - Starts DATE, - Started DATE, - Due DATE, - Resolved DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - Disabled NUMBER(11,0) DEFAULT 0 NOT NULL -); -CREATE INDEX Tickets1 ON Tickets (Queue, Status); -CREATE INDEX Tickets2 ON Tickets (Owner); -CREATE INDEX Tickets4 ON Tickets (id, Status); -CREATE INDEX Tickets5 ON Tickets (id, EffectiveId); -CREATE INDEX Tickets6 ON Tickets (EffectiveId, Type); - - -CREATE SEQUENCE SCRIPACTIONS_seq; -CREATE TABLE ScripActions ( - id NUMBER(11,0) - CONSTRAINT ScripActions_Key PRIMARY KEY, - Name VARCHAR2(200), - Description VARCHAR2(255), - ExecModule VARCHAR2(60), - Argument VARCHAR2(255), - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE -); - - -CREATE SEQUENCE TEMPLATES_seq; -CREATE TABLE Templates ( - id NUMBER(11,0) - CONSTRAINT Templates_Key PRIMARY KEY, - Queue NUMBER(11,0) DEFAULT 0 NOT NULL, - Name VARCHAR2(200) NOT NULL, - Description VARCHAR2(255), - Type VARCHAR2(16), - Language VARCHAR2(16), - TranslationOf NUMBER(11,0) DEFAULT 0 NOT NULL, - Content CLOB, - LastUpdated DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE -); - - -CREATE SEQUENCE OBJECTCUSTOMFIELDS_seq; -CREATE TABLE ObjectCustomFields ( - id NUMBER(11,0) - CONSTRAINT ObjectCustomFields_Key PRIMARY KEY, - CustomField NUMBER(11,0) NOT NULL, - ObjectId NUMBER(11,0) NOT NULL, - SortOrder NUMBER(11,0) DEFAULT 0 NOT NULL, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE -); - - -CREATE SEQUENCE OBJECTCUSTOMFIELDVALUES_seq; -CREATE TABLE ObjectCustomFieldValues ( - id NUMBER(11,0) - CONSTRAINT ObjectCustomFieldValues_Key PRIMARY KEY, - CustomField NUMBER(11,0) NOT NULL, - ObjectType VARCHAR2(25) NOT NULL, - ObjectId NUMBER(11,0) DEFAULT 0 NOT NULL, - SortOrder NUMBER(11,0) DEFAULT 0 NOT NULL, - - Content VARCHAR2(255), - LargeContent CLOB, - ContentType VARCHAR2(80), - ContentEncoding VARCHAR2(80), - - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE, - Disabled NUMBER(11,0) DEFAULT 0 NOT NULL -); - -CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (Content); -CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId); - -CREATE SEQUENCE CUSTOMFIELDS_seq; -CREATE TABLE CustomFields ( - id NUMBER(11,0) - CONSTRAINT CustomFields_Key PRIMARY KEY, - Name VARCHAR2(200), - Type VARCHAR2(200), - MaxValues NUMBER(11,0) DEFAULT 0 NOT NULL, - Pattern VARCHAR2(255), - Repeated NUMBER(11,0) DEFAULT 0 NOT NULL, - Description VARCHAR2(255), - SortOrder NUMBER(11,0) DEFAULT 0 NOT NULL, - LookupType VARCHAR2(255), - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE, - Disabled NUMBER(11,0) DEFAULT 0 NOT NULL -); - - -CREATE SEQUENCE CUSTOMFIELDVALUES_seq; -CREATE TABLE CustomFieldValues ( - id NUMBER(11,0) - CONSTRAINT CustomFieldValues_Key PRIMARY KEY, - CustomField NUMBER(11,0), - Name VARCHAR2(200), - Description VARCHAR2(255), - SortOrder NUMBER(11,0) DEFAULT 0 NOT NULL, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE -); - -CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField); - -CREATE SEQUENCE ATTRIBUTES_seq; -CREATE TABLE Attributes ( - id NUMBER(11,0) PRIMARY KEY, - Name VARCHAR2(255) NOT NULL, - Description VARCHAR2(255), - Content CLOB, - ContentType VARCHAR(16), - ObjectType VARCHAR2(25) NOT NULL, - ObjectId NUMBER(11,0) DEFAULT 0 NOT NULL, - Creator NUMBER(11,0) DEFAULT 0 NOT NULL, - Created DATE, - LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, - LastUpdated DATE -); - -CREATE INDEX Attributes1 on Attributes(Name); -CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); - - -CREATE TABLE sessions ( - id VARCHAR2(32) - CONSTRAINT Sessions_Key PRIMARY KEY, - a_session CLOB, - LastUpdated DATE -); - diff --git a/rt/etc/schema.Pg b/rt/etc/schema.Pg index 2d45a946a..ba0d6fc6c 100755 --- a/rt/etc/schema.Pg +++ b/rt/etc/schema.Pg @@ -3,6 +3,9 @@ -- ------------------------------------------------------------------ +BEGIN; + + -- @@ -57,7 +60,7 @@ CREATE TABLE Queues ( Created TIMESTAMP NULL , LastUpdatedBy integer NOT NULL DEFAULT 0 , LastUpdated TIMESTAMP NULL , - Disabled integer NOT NULL DEFAULT 0 , + Disabled int2 NOT NULL DEFAULT 0 , PRIMARY KEY (id) ); @@ -90,7 +93,6 @@ CREATE TABLE Links ( ); CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type) ; -CREATE INDEX Links4 ON Links(Type,LocalBase); -- }}} @@ -108,7 +110,7 @@ CREATE TABLE Principals ( id INTEGER DEFAULT nextval('principals_id_seq') not null, PrincipalType VARCHAR(16) not null, ObjectId integer, - Disabled integer NOT NULL DEFAULT 0 , + Disabled int2 NOT NULL DEFAULT 0 , PRIMARY KEY (id) ); @@ -134,7 +136,7 @@ CREATE TABLE Groups ( Description varchar(255) NULL , Domain varchar(64), Type varchar(64), - Instance integer, + Instance varchar(64), PRIMARY KEY (id) ); @@ -183,24 +185,22 @@ CREATE SEQUENCE transactions_id_seq; CREATE TABLE Transactions ( id INTEGER DEFAULT nextval('transactions_id_seq'), - ObjectType varchar(255) NOT NULL , - ObjectId integer NOT NULL DEFAULT 0 , + EffectiveTicket integer NOT NULL DEFAULT 0 , + Ticket integer NOT NULL DEFAULT 0 , TimeTaken integer NOT NULL DEFAULT 0 , Type varchar(20) NULL , Field varchar(40) NULL , OldValue varchar(255) NULL , NewValue varchar(255) NULL , - ReferenceType varchar(255) NULL, - OldReference integer NULL , - NewReference integer NULL , - Data varchar(255) NULL , + Data varchar(100) NULL , Creator integer NOT NULL DEFAULT 0 , Created TIMESTAMP NULL , PRIMARY KEY (id) ); -CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); +CREATE INDEX Transactions1 ON Transactions (Ticket); +CREATE INDEX Transactions2 ON Transactions (EffectiveTicket); -- }}} @@ -301,7 +301,7 @@ CREATE TABLE CachedGroupMembers ( MemberId int, Via int, ImmediateParentId int, - Disabled integer NOT NULL DEFAULT 0 , + Disabled int2 NOT NULL DEFAULT 0 , PRIMARY KEY (id) ); @@ -408,7 +408,7 @@ CREATE TABLE Tickets ( LastUpdated TIMESTAMP NULL , Creator integer NOT NULL DEFAULT 0 , Created TIMESTAMP NULL , - Disabled integer NOT NULL DEFAULT 0 , + Disabled int2 NOT NULL DEFAULT 0 , PRIMARY KEY (id) ); @@ -476,7 +476,7 @@ CREATE TABLE Templates ( -- }}} --- {{{ ObjectCustomFieldValues +-- {{{ TicketCustomFieldValues @@ -484,32 +484,22 @@ CREATE TABLE Templates ( -- Sequences for table TICKETCUSTOMFIELDVALUES -- -CREATE SEQUENCE objectcustomfieldvalues_id_s; +CREATE SEQUENCE ticketcustomfieldvalues_id_s; -CREATE TABLE ObjectCustomFieldValues ( - id INTEGER DEFAULT nextval('objectcustomfieldvalues_id_s'), +CREATE TABLE TicketCustomFieldValues ( + id INTEGER DEFAULT nextval('ticketcustomfieldvalues_id_s'), + Ticket int NOT NULL , CustomField int NOT NULL , - ObjectType varchar(255) NULL , - ObjectId int NOT NULL , - SortOrder integer NOT NULL DEFAULT 0 , - Content varchar(255) NULL , - LargeContent text NULL, - ContentType varchar(80) NULL, - ContentEncoding varchar(80) NULL , Creator integer NOT NULL DEFAULT 0 , Created TIMESTAMP NULL , LastUpdatedBy integer NOT NULL DEFAULT 0 , LastUpdated TIMESTAMP NULL , - Disabled integer NOT NULL DEFAULT 0 , PRIMARY KEY (id) ); -CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId,Content); -CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId); - -- }}} -- {{{ CustomFields @@ -526,10 +516,7 @@ CREATE TABLE CustomFields ( id INTEGER DEFAULT nextval('customfields_id_seq'), Name varchar(200) NULL , Type varchar(200) NULL , - MaxValues integer NOT NULL DEFAULT 0 , - Repeated integer NOT NULL DEFAULT 0 , - Pattern varchar(255) NULL , - LookupType varchar(255) NOT NULL , + Queue integer NOT NULL DEFAULT 0 , Description varchar(255) NULL , SortOrder integer NOT NULL DEFAULT 0 , @@ -537,27 +524,7 @@ CREATE TABLE CustomFields ( Created TIMESTAMP NULL , LastUpdatedBy integer NOT NULL DEFAULT 0 , LastUpdated TIMESTAMP NULL , - Disabled integer NOT NULL DEFAULT 0 , - PRIMARY KEY (id) - -); - --- }}} - --- {{{ ObjectCustomFields - -CREATE SEQUENCE objectcustomfields_id_s; - -CREATE TABLE ObjectCustomFields ( - id INTEGER DEFAULT nextval('objectcustomfields_id_s'), - CustomField integer NOT NULL, - ObjectId integer NOT NULL, - SortOrder integer NOT NULL DEFAULT 0 , - - Creator integer NOT NULL DEFAULT 0 , - Created TIMESTAMP NULL , - LastUpdatedBy integer NOT NULL DEFAULT 0 , - LastUpdated TIMESTAMP NULL , + Disabled int2 NOT NULL DEFAULT 0 , PRIMARY KEY (id) ); @@ -589,34 +556,6 @@ CREATE TABLE CustomFieldValues ( ); -CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField); - --- }}} - - --- {{{ Attributes - -CREATE SEQUENCE attributes_id_seq; - -CREATE TABLE Attributes ( - id INTEGER DEFAULT nextval('attributes_id_seq'), - Name varchar(255) NOT NULL , - Description varchar(255) NULL , - Content text, - ContentType varchar(16), - ObjectType varchar(64), - ObjectId integer, - Creator integer NOT NULL DEFAULT 0 , - Created TIMESTAMP NULL , - LastUpdatedBy integer NOT NULL DEFAULT 0 , - LastUpdated TIMESTAMP NULL , - PRIMARY KEY (id) - -); - -CREATE INDEX Attributes1 on Attributes(Name); -CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); - -- }}} -- {{{ Sessions @@ -634,3 +573,6 @@ CREATE TABLE sessions ( -- }}} + + +COMMIT; diff --git a/rt/etc/schema.mysql b/rt/etc/schema.mysql index 60f1abae2..46f8ec562 100755 --- a/rt/etc/schema.mysql +++ b/rt/etc/schema.mysql @@ -16,6 +16,7 @@ CREATE TABLE Attachments ( PRIMARY KEY (id) ) TYPE=InnoDB; +CREATE INDEX Attachments1 ON Attachments (Parent) ; CREATE INDEX Attachments2 ON Attachments (TransactionId) ; CREATE INDEX Attachments3 ON Attachments (Parent, TransactionId) ; # }}} @@ -61,7 +62,6 @@ CREATE TABLE Links ( CREATE UNIQUE INDEX Links1 ON Links (Base, Target, Type) ; CREATE INDEX Links2 ON Links (Base, Type) ; CREATE INDEX Links3 ON Links (Target, Type) ; -CREATE INDEX Links4 ON Links (Type,LocalBase); # }}} @@ -87,12 +87,12 @@ CREATE TABLE Groups ( Description varchar(255) NULL , Domain varchar(64), Type varchar(64), - Instance integer, + Instance varchar(64), PRIMARY KEY (id) ) TYPE=InnoDB; CREATE INDEX Groups1 ON Groups (Domain,Instance,Type,id); -CREATE INDEX Groups2 On Groups (Type, Instance); +CREATE INDEX Groups2 On Groups (Type, Instance, Domain); # }}} @@ -118,23 +118,21 @@ CREATE TABLE ScripConditions ( # {{{ Transactions CREATE TABLE Transactions ( id INTEGER NOT NULL AUTO_INCREMENT, - ObjectType varchar(64) NOT NULL, - ObjectId integer NOT NULL DEFAULT 0 , + EffectiveTicket integer NOT NULL DEFAULT 0 , + Ticket integer NOT NULL DEFAULT 0 , TimeTaken integer NOT NULL DEFAULT 0 , Type varchar(20) NULL , Field varchar(40) NULL , OldValue varchar(255) NULL , NewValue varchar(255) NULL , - ReferenceType varchar(255) NULL, - OldReference integer NULL , - NewReference integer NULL , - Data varchar(255) NULL , + Data varchar(100) NULL , Creator integer NOT NULL DEFAULT 0 , Created DATETIME NULL , PRIMARY KEY (id) ) TYPE=InnoDB; -CREATE INDEX Transactions1 ON Transactions (ObjectType, ObjectId); +CREATE INDEX Transactions1 ON Transactions (Ticket); +CREATE INDEX Transactions2 ON Transactions (EffectiveTicket); # }}} @@ -212,6 +210,7 @@ create table CachedGroupMembers ( ) TYPE=InnoDB; CREATE INDEX DisGrouMem on CachedGroupMembers (GroupId,MemberId,Disabled); +CREATE INDEX GrouMem on CachedGroupMembers (GroupId,MemberId); # }}} @@ -258,6 +257,8 @@ CREATE TABLE Users ( CREATE UNIQUE INDEX Users1 ON Users (Name) ; +CREATE INDEX Users2 ON Users (Name); +CREATE INDEX Users3 ON Users (id, EmailAddress); CREATE INDEX Users4 ON Users (EmailAddress); @@ -298,6 +299,9 @@ CREATE TABLE Tickets ( CREATE INDEX Tickets1 ON Tickets (Queue, Status) ; CREATE INDEX Tickets2 ON Tickets (Owner) ; +CREATE INDEX Tickets3 ON Tickets (EffectiveId) ; +CREATE INDEX Tickets4 ON Tickets (id, Status) ; +CREATE INDEX Tickets5 ON Tickets (id, EffectiveId) ; CREATE INDEX Tickets6 ON Tickets (EffectiveId, Type) ; # }}} @@ -339,31 +343,21 @@ CREATE TABLE Templates ( # }}} -# {{{ ObjectCustomFieldValues +# {{{ TicketCustomFieldValues -CREATE TABLE ObjectCustomFieldValues ( +CREATE TABLE TicketCustomFieldValues ( id INTEGER NOT NULL AUTO_INCREMENT, + Ticket int NOT NULL , CustomField int NOT NULL , - ObjectType varchar(255) NOT NULL, # Final target of the Object - ObjectId int NOT NULL , # New -- Replaces Ticket - SortOrder integer NOT NULL DEFAULT 0 , # New -- ordering for multiple values - Content varchar(255) NULL , - LargeContent LONGTEXT NULL, # New -- to hold 255+ strings - ContentType varchar(80) NULL, # New -- only text/* gets searched - ContentEncoding varchar(80) NULL , # New -- for binary Content Creator integer NOT NULL DEFAULT 0 , Created DATETIME NULL , LastUpdatedBy integer NOT NULL DEFAULT 0 , LastUpdated DATETIME NULL , - Disabled int2 NOT NULL DEFAULT 0 , # New -- whether the value was current PRIMARY KEY (id) ) TYPE=InnoDB; -CREATE INDEX ObjectCustomFieldValues1 ON ObjectCustomFieldValues (Content); -CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,ObjectType,ObjectId); - # }}} # {{{ CustomFields @@ -371,13 +365,10 @@ CREATE INDEX ObjectCustomFieldValues2 ON ObjectCustomFieldValues (CustomField,Ob CREATE TABLE CustomFields ( id INTEGER NOT NULL AUTO_INCREMENT, Name varchar(200) NULL , - Type varchar(200) NULL , # Changed -- 'Single' and 'Multiple' is moved out - MaxValues integer, # New -- was 'Single'(1) and 'Multiple'(0) - Pattern varchar(255) NULL , # New -- Must validate against this - Repeated int2 NOT NULL DEFAULT 0 , # New -- repeated table entry + Type varchar(200) NULL , + Queue integer NOT NULL DEFAULT 0 , Description varchar(255) NULL , SortOrder integer NOT NULL DEFAULT 0 , - LookupType varchar(255) NOT NULL, Creator integer NOT NULL DEFAULT 0 , Created DATETIME NULL , @@ -387,22 +378,8 @@ CREATE TABLE CustomFields ( PRIMARY KEY (id) ) TYPE=InnoDB; -# }}} - -# {{{ ObjectCustomFields +CREATE INDEX CustomFields1 on CustomFields (Disabled, Queue); -CREATE TABLE ObjectCustomFields ( - id INTEGER NOT NULL AUTO_INCREMENT, - CustomField int NOT NULL , - ObjectId integer NOT NULL, - SortOrder integer NOT NULL DEFAULT 0 , - - Creator integer NOT NULL DEFAULT 0 , - Created DATETIME NULL , - LastUpdatedBy integer NOT NULL DEFAULT 0 , - LastUpdated DATETIME NULL , - PRIMARY KEY (id) -) TYPE=InnoDB; # }}} @@ -422,31 +399,6 @@ CREATE TABLE CustomFieldValues ( PRIMARY KEY (id) ) TYPE=InnoDB; -CREATE INDEX CustomFieldValues1 ON CustomFieldValues (CustomField); - -# }}} - - -# {{{ Attributes - -CREATE TABLE Attributes ( - id INTEGER NOT NULL AUTO_INCREMENT, - Name varchar(255) NULL , - Description varchar(255) NULL , - Content text, - ContentType varchar(16), - ObjectType varchar(64), - ObjectId integer, # foreign key to anything - Creator integer NOT NULL DEFAULT 0 , - Created DATETIME NULL , - LastUpdatedBy integer NOT NULL DEFAULT 0 , - LastUpdated DATETIME NULL , - PRIMARY KEY (id) -) TYPE=InnoDB; - -CREATE INDEX Attributes1 on Attributes(Name); -CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); - # }}} # {{{ Sessions diff --git a/rt/etc/upgrade/2.1.71 b/rt/etc/upgrade/2.1.71 deleted file mode 100644 index cb89a3ac3..000000000 --- a/rt/etc/upgrade/2.1.71 +++ /dev/null @@ -1,211 +0,0 @@ -@Queues = ( { - Name => '___Approvals', - Description => 'A system-internal queue for the approvals system', - Disabled => 2, - } -); - - - - - -# {{{ Templates -@Templates = ( - { - Queue => '___Approvals', - Name => "New Pending Approval", # loc - Description => "Notify Owners and AdminCcs of new items pending their approval", # loc - Content => 'Subject: New Pending Approval: {$Ticket->Subject} - -Greetings, - -There is a new item pending your approval: "{$Ticket->Subject()}", -a summary of which appears below. - -Please visit {$RT::WebURL}Approvals/Display.html?id={$Ticket->id} -to approve or reject this ticket, or {$RT::WebURL}Approvals/ to -batch-process all your pending approvals. - -------------------------------------------------------------------------- -{$Transaction->Content()} -' - }, -); - -# }}} - -1; - -@ScripActions = ( - { Name => 'Open Tickets', - Description => 'Open tickets on correspondence', - ExecModule => 'AutoOpen' }, - -); - - @Scrips = ( - { ScripCondition => 'On Correspond', - ScripAction => 'Open Tickets', - Template => 'Blank', - Queue => '0' - }, - { ScripCondition => 'On Create', - ScripAction => 'AutoReply To Requestors', - Template => 'AutoReply' }, - { ScripCondition => 'On Create', - ScripAction => 'Notify AdminCcs', - Template => 'Transaction' }, - { ScripCondition => 'On Correspond', - ScripAction => 'Notify AdminCcs', - Template => 'Admin Correspondence' }, - { ScripCondition => 'On Correspond', - ScripAction => 'Notify Requestors And Ccs', - Template => 'Correspondence' }, - { ScripCondition => 'On Correspond', - ScripAction => 'Notify Other Recipients', - Template => 'Correspondence' }, - { ScripCondition => 'On Comment', - ScripAction => 'Notify AdminCcs As Comment', - Template => 'Admin Comment' }, - { ScripCondition => 'On Comment', - ScripAction => 'Notify Other Recipients As Comment', - Template => 'Correspondence' }, - { ScripCondition => 'On Resolve', - ScripAction => 'Notify Requestors', - Template => 'Resolved' }, - - - { - Description => "When an approval ticket is created, notify the Owner and AdminCc of the item awaiting their approval", # loc - Queue => '___Approvals', - ScripCondition => 'On Create', - ScripAction => 'Notify AdminCcs', - Template => 'New Pending Approval' - }, - { - Description => "If an approval is rejected, reject the original and delete pending approvals", # loc - Queue => '___Approvals', - ScripCondition => 'On Status Change', - ScripAction => 'User Defined', - CustomCommitCode => q[ -# ------------------------------------------------------------------- # -return(1) unless ( lc($self->TransactionObj->NewValue) eq "rejected" or - lc($self->TransactionObj->NewValue) eq "deleted" ); - -my $links = $self->TicketObj->DependedOnBy; -foreach my $link (@{ $links->ItemsArrayRef }) { - my $obj = $link->BaseObj; - if ($obj->QueueObj->IsActiveStatus($obj->Status)) { - if ($obj->Type eq 'ticket') { - $obj->Correspond( - Content => $self->loc("Your request was rejected."), - ); - $obj->SetStatus( - Status => 'rejected', - Force => 1, - ); - } - else { - $obj->SetStatus( - Status => 'deleted', - Force => 1, - ); - } - } -} - -$links = $self->TicketObj->DependsOn; -foreach my $link (@{ $links->ItemsArrayRef }) { - my $obj = $link->TargetObj; - if ($obj->QueueObj->IsActiveStatus($obj->Status)) { - $obj->SetStatus( - Status => 'deleted', - Force => 1, - ); - } -} - -return 1; -# ------------------------------------------------------------------- # - ], - CustomPrepareCode => '1', - Template => 'Admin Comment', - }, - { - Description => "When a ticket has been approved by any approver, add correspondence to the original ticket", # loc - Queue => '___Approvals', - ScripCondition => 'On Resolve', - ScripAction => 'User Defined', - CustomPrepareCode => 'return(1);', - CustomCommitCode => q[ -# ------------------------------------------------------------------- # -return(1) unless ($self->TicketObj->Type eq 'approval'); - -foreach my $obj ($self->TicketObj->AllDependedOnBy( Type => 'ticket' )) { - $obj->Correspond( - Content => $self->loc( "Your request has been approved by [_1]. Other approvals may still be pending.", # loc - $self->TransactionObj->CreatorObj->Name, - ) . "\n" . $self->loc( "Approver's notes: [_1]", # loc - $self->TicketObj->Transactions->Last->Content, - ), - _reopen => 0, - ); -} - -return 1; -# ------------------------------------------------------------------- # - ], - Template => 'Admin Comment' - }, - { - Description => "When a ticket has been approved by all approvers, add correspondence to the original ticket", # loc - Queue => '___Approvals', - ScripCondition => 'On Resolve', - ScripAction => 'User Defined', - CustomPrepareCode => 'return(1);', - CustomCommitCode => q[ -# ------------------------------------------------------------------- # -# Find all the tickets that depend on this (that this is approving) - -my $Ticket = $self->TicketObj; -my @TOP = $Ticket->AllDependedOnBy( Type => 'ticket' ); -my $links = $Ticket->DependedOnBy; - -while (my $link = $links->Next) { - my $obj = $link->BaseObj; - next if ($obj->HasUnresolvedDependencies( Type => 'approval' )); - - if ($obj->Type eq 'ticket') { - $obj->Correspond( - Content => $self->loc("Your request has been approved."), - _reopen => 0, - ); - } - elsif ($obj->Type eq 'code') { - my $code = $obj->Transactions->First->Content; - my $rv; - - foreach my $TOP (@TOP) { - local $@; - $rv++ if eval $code; - $RT::Logger->error("Cannot eval code: $@") if $@; - } - - if ($rv or !@TOP) { - $obj->SetStatus( Status => 'resolved', Force => 1,); - } - else { - $obj->SetStatus( Status => 'rejected', Force => 1,); - } - } -} - -return 1; -# ------------------------------------------------------------------- # - ], - Template => 'Admin Comment', - }, -); - -# }}} - diff --git a/rt/html/Admin/Elements/ModifyQueue b/rt/html/Admin/Elements/ModifyQueue deleted file mode 100644 index 36f9ce17f..000000000 --- a/rt/html/Admin/Elements/ModifyQueue +++ /dev/null @@ -1,78 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<& /Elements/TitleBoxStart, title => loc('Editing Configuration for queue [_1]', $QueueObj->Id) &> - -<FORM ACTION="<%$RT::WebPath%>/Admin/Queues/Modify.html" METHOD=POST> -<INPUT TYPE=HIDDEN NAME=id VALUE="<%$QueueObj->Id%>"> -<TABLE> -<TR><TD ALIGN=RIGHT> -<&|/l&>Queue Name</&>: -</TD> -<TD><INPUT name="Name" value="<%$QueueObj->Name%>"></TD> -</TR><TR> -<TD ALIGN=RIGHT> -<&|/l&>Description</&>:</TD><TD COLSPAN=3><INPUT name="Description" value="<%$QueueObj->Description%>" size=60></TD></TR> -<TR> -<TD ALIGN=RIGHT> -<&|/l&>Correspondence Address</&>: -</TD><TD> -<INPUT name="CorrespondAddress" value="<%$QueueObj->CorrespondAddress%>"> -</TD> -<TD ALIGN=RIGHT> - -<&|/l&>Comment Address</&>: </TD><TD> -<INPUT NAME="CommentAddress" value="<%$QueueObj->CommentAddress%>"> -</TD> -</TR><TR> - -<TD ALIGN=RIGHT> -<&|/l&>Priority starts at</&>: -</TD><TD><INPUT NAME="InitialPriority" value="<%$QueueObj->InitialPriority %>"> -</TD> -<TD ALIGN=RIGHT> -<&|/l&>Over time, priority moves toward</&>: -</TD><TD><INPUT NAME="FinalPriority" value="<%$QueueObj->FinalPriority %>"> -</TD> -</TR> -<TR> -<TD ALIGN=RIGHT> -<&|/l&>Requests should be due in</&>: -</TD><TD> -<INPUT NAME="DefaultDueIn" VALUE="<%$QueueObj->DefaultDueIn%>"> <&|/l&>days</&>. -</TD> -</TR> -</TABLE> -<& /Elements/Submit, Label => loc('Save Changes') &> -</form> -<& /Elements/TitleBoxEnd &> - -<%INIT> - -</%INIT> - -<%ARGS> - - -$QueueObj => undef -</%ARGS> diff --git a/rt/html/Admin/Elements/ModifyUser b/rt/html/Admin/Elements/ModifyUser deleted file mode 100644 index 2faefefaa..000000000 --- a/rt/html/Admin/Elements/ModifyUser +++ /dev/null @@ -1,99 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<& /Elements/TitleBoxStart, title => loc('Editing Configuration for user [_1]', $UserObj->Name) &> - -<FORM ACTION="<%$RT::WebPath%>/Admin/Users/Modify.html" METHOD=POST> -<INPUT TYPE=HIDDEN NAME=id VALUE="<%$UserObj->Id%>"> - -<&|/l&>Name</&>: <input name="Name" value="<%$UserObj->Name%>"> -<BR> -<&|/l&>New Password</&>: <input type=password name="Pass1"><BR> -<&|/l&>Retype Password</&>: <input type=password name="Pass2"><BR> - -<&|/l&>Comments</&>: <TEXTAREA name="Comments" COLS=80 ROWS=5 WRAP=VIRTUAL> -<%$UserObj->Comments%></TEXTAREA> - -<BR> -<&|/l&>Signature</&>: <TEXTAREA COLS=80 ROWS=5 name="Signature" WRAP=HARD> -<%$UserObj->Signature%></TEXTAREA> -<BR> -<&|/l&>EmailAddress</&>: <input name="EmailAddress" value="<%$UserObj->EmailAddress%>"> -<BR> -<&|/l&>FreeformContactInfo</&>: <input name="FreeformContactInfo" value="<%$UserObj->FreeformContactInfo%>"> -<BR> -<&|/l&>Organization</&>: <input name="Organization" value="<%$UserObj->Organization%>"> -<BR> -<&|/l&>RealName</&>: <input name="RealName" value="<%$UserObj->RealName%>"> -<BR> -<&|/l&>NickName</&>: <input name="NickName" value="<%$UserObj->NickName%>"> -<BR> -<&|/l&>Lang</&>: <input name="Lang" value="<%$UserObj->Lang%>"> -<BR> -<&|/l&>EmailEncoding</&>: <input name="EmailEncoding" value="<%$UserObj->EmailEncoding%>"> -<BR> -<&|/l&>WebEncoding</&>: <input name="WebEncoding" value="<%$UserObj->WebEncoding%>"> -<BR> -<&|/l&>ExternalContactInfoId</&>: <input name="ExternalContactInfoId" value="<%$UserObj->ExternalContactInfoId%>"> -<BR> -<&|/l&>ContactInfoSystem</&>: <input name="ContactInfoSystem" value="<%$UserObj->ContactInfoSystem%>"> -<BR> -<&|/l&>UnixUsername</&>: <input name="Gecos" value="<%$UserObj->Gecos%>"> -<BR> -<&|/l&>ExternalAuthId</&>: <input name="ExternalAuthId" value="<%$UserObj->ExternalAuthId%>"> -<BR> -<&|/l&>AuthSystem</&>: <input name="AuthSystem" value="<%$UserObj->AuthSystem%>"> -<BR> -<&|/l&>HomePhone</&>: <input name="HomePhone" value="<%$UserObj->HomePhone%>"> -<BR> -<&|/l&>WorkPhone</&>: <input name="WorkPhone" value="<%$UserObj->WorkPhone%>"> -<BR> -<&|/l&>MobilePhone</&>: <input name="MobilePhone" value="<%$UserObj->MobilePhone%>"> -<BR> -<&|/l&>PagerPhone</&>: <input name="PagerPhone" value="<%$UserObj->PagerPhone%>"> -<BR> -<&|/l&>Address1</&>: <input name="Address1" value="<%$UserObj->Address1%>"> -<BR> -<&|/l&>Address2</&>: <input name="Address2" value="<%$UserObj->Address2%>"> -<BR> -<&|/l&>City</&>: <input name="City" value="<%$UserObj->City%>"> -<BR> -<&|/l&>State</&>: <input name="State" value="<%$UserObj->State%>"> -<BR> -<&|/l&>Zip</&>: <input name="Zip" value="<%$UserObj->Zip%>"> -<BR> -<&|/l&>Country</&>: <input name="Country" value="<%$UserObj->Country%>"> -<BR> -<& /Elements/Submit, Label => loc('Save Changes') &> -</form> -<& /Elements/TitleBoxEnd &> - -<%INIT> - -</%INIT> - -<%ARGS> - - -$UserObj => undef -</%ARGS> diff --git a/rt/html/Admin/Global/CustomField.html b/rt/html/Admin/Global/CustomField.html deleted file mode 100644 index 3871d8998..000000000 --- a/rt/html/Admin/Global/CustomField.html +++ /dev/null @@ -1,86 +0,0 @@ -%# {{{ BEGIN BPS TAGGED BLOCK -%# -%# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC -%# <jesse@bestpractical.com> -%# -%# (Except where explicitly superseded by other copyright notices) -%# -%# -%# LICENSE: -%# -%# This work is made available to you under the terms of Version 2 of -%# the GNU General Public License. A copy of that license should have -%# been provided with this software, but in any event can be snarfed -%# from www.gnu.org. -%# -%# This work is distributed in the hope that it will be useful, but -%# WITHOUT ANY WARRANTY; without even the implied warranty of -%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%# General Public License for more details. -%# -%# You should have received a copy of the GNU General Public License -%# along with this program; if not, write to the Free Software -%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -%# -%# -%# 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 -<& /Admin/Elements/Header, Title => $title &> -<& /Admin/Elements/SystemTabs, - current_tab => 'Admin/Global/CustomFields.html', - current_subtab => $current_subtab, - subtabs => $subtabs, - Title => $title &> - -<& /Admin/Elements/EditCustomField, title => $title, %ARGS &> - -<%INIT> -my ($title, $current_subtab); - -my $subtabs = { - A => { title => loc('Select custom field'), - path => "Admin/Global/CustomFields.html" - }, - B => { title => loc('New custom field'), - path => "Admin/Global/CustomField.html?create=1&Queue=0", - separator => 1, - } - }; -if ( $ARGS{'create'} ) { - $current_subtab = "Admin/Global/CustomField.html?create=1&Queue=0"; - $title = loc('Create a CustomField which applies to all queues'); -} -else { - $current_subtab = - "Admin/Global/CustomField.html?CustomField=" . $CustomField . "&Queue=0"; - $title = loc('Modify a CustomField which applies to all queues'); - $subtabs->{"C"} = { - title => loc( 'Custom Field #[_1]', $CustomField ), - path => "Admin/Global/CustomField.html?CustomField=" . $CustomField . "&Queue=0" - }; -} -</%INIT> -<%ARGS> -$CustomField => undef -</%ARGS> -<%ATTR> -AutoFlush => 0 -</%ATTR> diff --git a/rt/html/Admin/Global/CustomFields.html b/rt/html/Admin/Global/CustomFields.html deleted file mode 100644 index 593040218..000000000 --- a/rt/html/Admin/Global/CustomFields.html +++ /dev/null @@ -1,69 +0,0 @@ -%# {{{ BEGIN BPS TAGGED BLOCK -%# -%# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC -%# <jesse@bestpractical.com> -%# -%# (Except where explicitly superseded by other copyright notices) -%# -%# -%# LICENSE: -%# -%# This work is made available to you under the terms of Version 2 of -%# the GNU General Public License. A copy of that license should have -%# been provided with this software, but in any event can be snarfed -%# from www.gnu.org. -%# -%# This work is distributed in the hope that it will be useful, but -%# WITHOUT ANY WARRANTY; without even the implied warranty of -%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%# General Public License for more details. -%# -%# You should have received a copy of the GNU General Public License -%# along with this program; if not, write to the Free Software -%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -%# -%# -%# 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 -<& /Admin/Elements/Header, Title => $title &> -<& /Admin/Elements/SystemTabs, - current_tab => 'Admin/Global/CustomFields.html', - current_subtab => 'Admin/Global/CustomFields.html', - subtabs => $subtabs, - Title => $title &> - -<& /Admin/Elements/EditCustomFields, title => $title, %ARGS &> - -<%INIT> -my $subtabs = { - A => { title => loc('Select custom field'), - path => "Admin/Global/CustomFields.html" - }, - B => { title => loc('New custom field'), - path => "Admin/Global/CustomField.html?create=1&Queue=0", - separator => 1, - } - }; -my $title = loc("Modify Custom Fields which apply to all queues"); -</%INIT> -<%ARGS> -$id => undef -</%ARGS> diff --git a/rt/html/Admin/Users/Prefs.html b/rt/html/Admin/Users/Prefs.html deleted file mode 100644 index 0bba9fadd..000000000 --- a/rt/html/Admin/Users/Prefs.html +++ /dev/null @@ -1,122 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<& /Elements/Header, Title => loc("User view") &> - -<& /Elements/ViewUser, User=>$u &> - -<h2 class="title"><%loc("User view")%></h2> - -%if ($session{CurrentUser} && ($session{CurrentUser}->Id == $id)) { - <& /Elements/TitleBoxStart, title => loc('Signature') &> -<form method=post> -<input type="hidden" name="id" value=<%$id%>> -<TEXTAREA COLS=72 ROWS=4 WRAP=HARD NAME="Signature"><% $u->Signature %></TEXTAREA><br><br> -<input type="submit" value="<&|/l&>Update signature</&>"> -</form> - <& /Elements/TitleBoxEnd &> - <form method=post> - <&|/l&>Open tickets (from listing) in another window</&>: <input type="checkbox" name="NewWindowOption" <%exists $session{NewWindowOption} && "CHECKED"%>><br> - <&|/l&>Open tickets (from listing) in a new window</&>: <input type="checkbox" name="AlwaysNewWindowOption" <%exists $session{AlwaysNewWindowOption} && "CHECKED"%>><br> - <input type="submit" name="NewWindowSetting" value="<&|/l&>New window setting</&>"> - </form> -%} - - <& /Elements/TitleBoxStart, title => loc('Email') &> -<form method=post> -<input type="hidden" name="id" value="<%$id%>"> -<input name="Email" value="<% $u->EmailAddress %>"><input type="submit" value="<&|/l&>Update email</&>"> -</form> - <& /Elements/TitleBoxEnd &> - <& /Elements/TitleBoxStart, title => loc('Real Name') &> -<form method=post> -<input type="hidden" name="id" value="<%$id%>"> -<input name="RealName" value="<% $u->RealName %>"><input type="submit" value="<&|/l&>Update name</&>"> -</form> - <& /Elements/TitleBoxEnd &> - - <& /Elements/TitleBoxStart, title => loc('User ID') &> -<form method=post> -<input type="hidden" name="id" value="<%$id%>"> -<input name="Name" value="<% $u->Name %>"><input type="submit" value="<&|/l&>Update ID</&>"> -</form> - <& /Elements/TitleBoxEnd &> - -%# TODO: alternative email addresses + merging users - -<%ARGS> -$id => $session{CurrentUser} ? $session{CurrentUser}->Id : 0 -$Signature => undef -$Email => undef -$RealName => undef -$Name => undef -</%ARGS> - -<%INIT> -require RT::User; -my $u=RT::User->new($session{CurrentUser}); -$u->Load($id) || die loc("Couldn't load that user ([_1])", $id); -if ($Signature) { -my ($val, $msg)=$u->SetSignature($Signature); -$RT::Logger->log(level=>($val ? 'info' : 'error'), message=>$msg); -} - -if ($Email) { -my ($val, $msg)=$u->SetEmailAddress($Email); -$RT::Logger->log(level=>($val ? 'info' : 'error'), message=>$msg); -} - -if ($RealName) { -my ($val, $msg)=$u->SetRealName($RealName); -$RT::Logger->log(level=>($val ? 'info' : 'error'), message=>$msg); -} - -if ($Name) { -my ($val, $msg)=$u->SetName($Name); -$RT::Logger->log(level=>($val ? 'info' : 'error'), message=>$msg); -} - -if ($ARGS{NewWindowSetting}) { -if ($ARGS{NewWindowOption}) { -$session{NewWindowOption}=1; -} else { -delete $session{NewWindowOption}; -} -if ($ARGS{AlwaysNewWindowOption}) { -$session{NewWindowOption}=1; -$session{AlwaysNewWindowOption}=1; -} else { -delete $session{AlwaysNewWindowOption}; -} -} - -</%INIT> - - - - - - - - - diff --git a/rt/html/Elements/CollectionAsTable/Row b/rt/html/Elements/CollectionAsTable/Row index 0de362ea8..3316bc027 100644 --- a/rt/html/Elements/CollectionAsTable/Row +++ b/rt/html/Elements/CollectionAsTable/Row @@ -71,7 +71,6 @@ foreach my $column (@Format) { $item++; $m->out('<td class="collection-as-table" '); $m->out( 'align="' . $column->{align} . '"' ) if ( $column->{align} ); - $m->out( 'style="' . $column->{style} . '"' ) if ( $column->{style} ); $m->out('>'); foreach my $subcol ( @{ $column->{output} } ) { if ( $subcol =~ /^__(.*?)__$/o ) { diff --git a/rt/html/Elements/Footer b/rt/html/Elements/Footer index 4c90acfa3..78a116f38 100644 --- a/rt/html/Elements/Footer +++ b/rt/html/Elements/Footer @@ -50,6 +50,7 @@ <td> % } <& /Elements/Callback, %ARGS &> +<!-- <div class="bpscredits"> <&|/l, '»|«', $RT::VERSION, '2005', '<a href="http://www.bestpractical.com?rt='.$RT::VERSION.'">Best Practical Solutions, LLC</a>', &>[_1] RT [_2] Copyright 1996-[_3] [_4].</&><br> % if (!$Menu) { @@ -57,6 +58,7 @@ <&|/l, '<a href="mailto:sales@bestpractical.com">sales@bestpractical.com</a>' &>To inquire about support, training, custom development or licensing, please contact [_1].</&><br> % } </div> +--> % if ($Debug >= 2 ) { % require Data::Dumper; % my $d = Data::Dumper->new([\%ARGS], [qw(%ARGS)]); diff --git a/rt/html/Elements/FreesideInvoiceSearch b/rt/html/Elements/FreesideInvoiceSearch new file mode 100644 index 000000000..3842b2ff9 --- /dev/null +++ b/rt/html/Elements/FreesideInvoiceSearch @@ -0,0 +1,20 @@ +% if ( $FS::CurrentUser::CurrentUser->access_right('View invoices') ) { + + <form action="<% $RT::URI::freeside::URL %>/search/cust_bill.html" STYLE="margin:0"> + <SCRIPT TYPE="text/javascript"> + function clearhint_search_invoice (what) { + if ( what.value == '(inv #)' ) + what.value = ''; + } + </SCRIPT> + <input name="invnum" accesskey="0" VALUE="(inv #)" SIZE="4" onFocus="clearhint_search_invoice(this);" onClick="clearhint_search_invoice(this);" STYLE="text-align:right; margin-bottom:1px; font-family: Arial, Verdana, Helvetica, sans-serif;"> + +% if ( $FS::CurrentUser::CurrentUser->access_right('List invoices') ) { + <A HREF="<% $RT::URI::freeside::URL %>search/report_cust_bill.html" STYLE="color: #ffffff; font-size: 70%; font-weight:normal">Advanced</A> +% } + <BR> + + <input type="submit" value="<&|/l&>Search invoices</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%"> + </form> + +% } diff --git a/rt/html/Elements/FreesideNewCust b/rt/html/Elements/FreesideNewCust new file mode 100644 index 000000000..c752437da --- /dev/null +++ b/rt/html/Elements/FreesideNewCust @@ -0,0 +1,3 @@ +<form action="<% $RT::URI::freeside::URL %>/edit/cust_main.cgi" STYLE="margin:0"> +<INPUT TYPE="submit" VALUE="<&|/l&>New customer</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;"> +</FORM> diff --git a/rt/html/Elements/FreesideSearch b/rt/html/Elements/FreesideSearch new file mode 100644 index 000000000..99b8da072 --- /dev/null +++ b/rt/html/Elements/FreesideSearch @@ -0,0 +1,11 @@ +<form action="<% $RT::URI::freeside::URL %>/search/cust_main.cgi" STYLE="margin:0"> + <SCRIPT TYPE="text/javascript"> + function clearhint_search_cust (what) { + if ( what.value == '(cust #, name, company or phone)' ) + what.value = ''; + } + </SCRIPT> +<input name="search_cust" accesskey="0" VALUE="(cust #, name, company or phone)" SIZE="28" onFocus="clearhint_search_cust(this);" onClick="clearhint_search_cust(this);" STYLE="text-align:right; font-family: Arial, Verdana, Helvetica, sans-serif;"><BR> +<A HREF="<% $RT::URI::freeside::URL %>/search/cust_main.html" STYLE="color: #000000; font-size: 70%; font-weight:normal">Advanced</A> +<input type="submit" value="<&|/l&>Search customers</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%"> +</form> diff --git a/rt/html/Elements/FreesideSvcSearch b/rt/html/Elements/FreesideSvcSearch new file mode 100644 index 000000000..e9ad56426 --- /dev/null +++ b/rt/html/Elements/FreesideSvcSearch @@ -0,0 +1,11 @@ +<form action="<% $RT::URI::freeside::URL %>/search/svc_Smart.html" STYLE="margin:0"> + <SCRIPT TYPE="text/javascript"> + function clearhint_search_svc (what) { + if ( what.value == '(user, user@domain or domain)' ) + what.value = ''; + } + </SCRIPT> +<input name="search_svc" accesskey="0" VALUE="(user, user@domain or domain)" SIZE="26" onFocus="clearhint_search_svc(this);" onClick="clearhint_search_svc(this);" STYLE="text-align:right; font-family: Arial, Verdana, Helvetica, sans-serif;"><BR> + <A HREF="<% $RT::URI::freeside::URL %>search/svc_Smarter.html" STYLE="color: #000000; font-size: 70%; font-weight:normal">Advanced</A> +<input type="submit" value="<&|/l&>Search services</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%"> +</form> diff --git a/rt/html/Elements/Header b/rt/html/Elements/Header index f5a616ece..c1bc92afd 100644 --- a/rt/html/Elements/Header +++ b/rt/html/Elements/Header @@ -47,14 +47,12 @@ <HTML> <HEAD> <TITLE><%$Title%></TITLE> -% if ($Refresh && $Refresh > 0) { +% if ($Refresh > 0) { <META HTTP-EQUIV="REFRESH" CONTENT="<%$Refresh%>"> % } -<link rel="shortcut icon" href="<%$RT::WebImagesURL%>/favicon.png" type="image/png" /> -<link media="all" rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/webrt.css" type="text/css" /> -<link media="print" rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/printrt.css" type="text/css" /> - +<link rel="shortcut icon" href="<%$RT::WebImagesURL%>/favicon.png" type="image/png"> +<link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/webrt.css" type="text/css"> <script> function hideshow(num) { idstring = "element-" + num; @@ -69,7 +67,7 @@ function hideshow(num) { </script> <& /Elements/Callback, _CallbackName => 'Head', %ARGS &> </HEAD> -<BODY BGCOLOR="<%$BgColor%>" +<BODY BACKGROUND="<% $RT::URI::freeside::URL %>/images/background-cheat.png" STYLE="margin-top:0; margin-bottom:0; margin-left:0; margin-right:0" % if ($Focus) { ONLOAD=" var tmp = (document.getElementsByName('<% $Focus %>')); @@ -77,14 +75,15 @@ ONLOAD=" " % } > -<table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#FFFFFF"> +<table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#FFFFFF" STYLE="padding-left:0; padding-right:4"> <tr> - <td colspan=2><a href="http://bestpractical.com"><img src="<%$RT::WebImagesURL%>/bplogo.gif" alt="<%loc("Best Practical Solutions, LLC corporate logo")%>" width="230" height="50"></a></td> - <td> </td> - <td> </td> - <td width="50%" align="right"> + <td colspan=2 rowspan=2><img border=0 alt="freeside" src="<%$RT::WebImagesURL%>/small-logo.png" width="92" height="62"></td> + <td align="left" rowspan=2><font size=6><% &RT::URI::freeside::FreesideGetConfig('company_name') || 'ExampleCo' %></font></td> + <td align="right" valign="top"> % if ($session{'CurrentUser'} && $session{'CurrentUser'}->Id && $LoggedIn) { <SPAN STYLE="display: none"><A HREF="#skipnav"><&|/l&>Skip Menu</&></A> |</SPAN> +<&|/l, "<b>".$session{'CurrentUser'}->Name."</b>" &>Logged in as [_1]</&> +<BR> %if ($session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System )) { <A HREF="<%$RT::WebPath%><% $Prefs %>" ><&|/l&>Preferences</&></A> % } @@ -92,18 +91,42 @@ ONLOAD=" % unless ($RT::WebExternalAuth and !$RT::WebFallbackToInternalAuth) { | <A HREF="<%$RT::WebPath%>/NoAuth/Logout.html<%$URL ? "?URL=".$URL : ''%>"><&|/l&>Logout</&></a> % } -<BR> -<&|/l, "<b>".$session{'CurrentUser'}->Name."</b>" &>Logged in as [_1]</&> % } else { <&|/l&>Not logged in.</&> % } </td> + + </tr> + <tr> + + <td align=right valign=bottom> + <table> + <tr> + <td align=right> + <FONT SIZE="-3"> + <A HREF="http://www.sisd.com/freeside">Freeside</A> v<% &RT::URI::freeside::FreesideVersion() %><BR> + <A HREF="../docs/">Documentation</A><BR> + </FONT> + </td> + <td bgcolor=#000000></td> + <td align=left> + <FONT SIZE="-3"> + <A HREF="http://www.bestpractical.com/rt">RT</A> v<% $RT::VERSION %><BR> + <A HREF="http://wiki.bestpractical.com/">Documentation</A><BR> + </FONT> + </td> + + </tr> + </table> + </td> + </tr> </table> <%INIT> $r->headers_out->{'Pragma'} = 'no-cache'; $r->headers_out->{'Cache-control'} = 'no-cache'; +require RT::URI::freeside; </%INIT> <%ARGS> diff --git a/rt/html/Elements/PageLayout b/rt/html/Elements/PageLayout index 3d7241dad..f13ee0dda 100644 --- a/rt/html/Elements/PageLayout +++ b/rt/html/Elements/PageLayout @@ -43,32 +43,43 @@ %# those contributions and any derivatives thereof. %# %# END BPS TAGGED BLOCK }}} -<table class="darkblue" border=0 cellspacing=0 cellpadding=0 width="100%"> - <th class="titlebox" align="left"><span class="rtname"><%$AppName%></span> - </th> +<table class="black" border=0 cellspacing=0 cellpadding=0 width="100%"> +<tr> + <TD colspan=5 WIDTH="100%" STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gradient.png" HEIGHT="13" WIDTH="100%"></TD> +</tr> +<tr> +%# <th class="black" align="left" width=15%><span class="rtname"><%$AppName%></span> +%# </th> <span class="topactions"> -% foreach my $action (sort keys %{$topactions}) { - <td class="darkblueright"> +% my $notfirst = 0; foreach my $action (sort keys %{$topactions}) { + <td class="blackright" ALIGN="right" VALIGN="center"> <%$topactions->{"$action"}->{'html'} |n %> </td> % } </span> +</tr> </table> <table border=0 cellspacing=0 cellpadding=0 width="100%" height="100%"> +<TR> + <TD BGCOLOR="#000000" STYLE="padding:0" WIDTH="154"></TD> + <TD STYLE="padding:0" WIDTH="13"><IMG BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gray-corner.png"></TD> + <TD STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gray-top.png" HEIGHT="13" WIDTH="100%"></TD> +</TR> %# Vertical menu <TR height="100%"> -<TD valign="top" width="140" class="blue"> +<TD valign="top" width="140" class="black"> <& /Elements/Menu, toptabs => $toptabs, current_toptab => $current_toptab &> </TD> +<TD STYLE="padding:0" HEIGHT="100%" WIDTH=13 VALIGN="top"><IMG WIDTH="13" HEIGHT="100%" BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gray-side.png"></TD> <td valign="top"> <table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0"> <tr> - <td class="blue" valign="top"> + <td class="<% $actions ? 'darkmediumgray' : 'bggray' %>" valign="top"> <span class="title"><%$title%></span> </td> </tr> <tr> -<td class="blueright" valign="top"> +<td class="<% $actions ? 'darkmediumgrayright' : 'bggrayright' %>" valign="top"> <span class="nav"> % if ($actions) { % my @actions; @@ -79,7 +90,8 @@ % push @actions, qq|<a class="nav" href="|.$RT::WebPath."/".$actions->{$action}->{'path'}.qq|">|.$actions->{$action}->{'title'}."</a>"; % } % } -<% join(" | ", @actions) | n %> +%#<% join(" | ", @actions) | n %> +<% '['. join("] [", @actions). '] ' | n %> % if ($subactions) { % my @actions; % foreach my $action (sort keys %{$subactions}) { @@ -118,5 +130,5 @@ $tabs => undef $actions => undef $subactions => undef $title => $m->callers(-1)->path -$AppName => undef +$AppName => '' </%ARGS> diff --git a/rt/html/Elements/ShadedBox b/rt/html/Elements/ShadedBox deleted file mode 100644 index 36b9cae7c..000000000 --- a/rt/html/Elements/ShadedBox +++ /dev/null @@ -1,33 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<table> - <tr> - <td class="label"><%$title |n %>:</td> - <td class="value"><%$content |n %></td> - </tr> -</table> -<%ARGS> -$title => undef -$content => " " -</%ARGS> diff --git a/rt/html/Elements/ShadedInputRow b/rt/html/Elements/ShadedInputRow deleted file mode 100644 index e9fb69e5f..000000000 --- a/rt/html/Elements/ShadedInputRow +++ /dev/null @@ -1,35 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<tr> - <td class="label"><%$title |n %>:</td> - <td class="value"> - <input name=<%$name%> value="<%$content|h%>" SIZE=<%$size%>> - </td> -</tr> -<%ARGS> -$title => undef -$content => " " -$name => undef -$size => undef -</%ARGS> diff --git a/rt/html/Elements/ShadedRow b/rt/html/Elements/ShadedRow deleted file mode 100644 index 8947fcd82..000000000 --- a/rt/html/Elements/ShadedRow +++ /dev/null @@ -1,31 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<tr> - <td class="label"><%$title |n %>:</td> - <td class="value"><%$content |n %></td> -</tr> -<%ARGS> -$title => undef -$content => " " -</%ARGS> diff --git a/rt/html/Elements/SimpleSearch b/rt/html/Elements/SimpleSearch index 2b34d3a24..e9fc5c6ed 100644 --- a/rt/html/Elements/SimpleSearch +++ b/rt/html/Elements/SimpleSearch @@ -43,7 +43,14 @@ %# those contributions and any derivatives thereof. %# %# END BPS TAGGED BLOCK }}} -<form action="<% $RT::WebPath %>/index.html"> -<input size="12" name="q" autocomplete="off" accesskey="0"> -<input type="submit" value="<&|/l&>Search</&>"> +<form action="<% $RT::WebPath %>/index.html" STYLE="margin:0"> +<SCRIPT TYPE="text/javascript"> + function clearhint_search_ticket (what) { + if ( what.value == '(ticket # or subject string)' ) + what.value = ''; + } +</SCRIPT> +<input name="q" accesskey="0" VALUE="(ticket # or subject string)" onFocus="clearhint_search_ticket(this);" onClick="clearhint_search_ticket(this);" STYLE="text-align:right; font-family: Arial, Verdana, Helvetica, sans-serif;"><BR> +<A HREF="<% $RT::WebPath %>/Search/Build.html" STYLE="color: #ffffff; font-size: 70%; font-weight:normal">Advanced</A> +<input type="submit" value="<&|/l&>Search tickets</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%;padding-left:2px;padding-right:2px"> </form> diff --git a/rt/html/Elements/Tabs b/rt/html/Elements/Tabs index b2081edca..721f920d5 100644 --- a/rt/html/Elements/Tabs +++ b/rt/html/Elements/Tabs @@ -57,12 +57,25 @@ <%INIT> my $action; my $basetopactions = { - A => { html => $m->scomp('/Elements/CreateTicket') +# A => { html => $m->scomp('/Elements/CreateTicket') +# }, + A => { html => $m->scomp('/Elements/FreesideNewCust') }, - B => { html => $m->scomp('/Elements/SimpleSearch') + B => { html => $m->scomp('/Elements/FreesideSearch') + }, + C => { html => $m->scomp('/Elements/FreesideInvoiceSearch') + }, + D => { html => $m->scomp('/Elements/FreesideSvcSearch') + }, + E => { html => $m->scomp('/Elements/SimpleSearch') } }; -my $basetabs = { A => { title => loc('Homepage'), +my $basetabs = { + ' A'=> { title => 'Billing Main', + path => &RT::URI::freeside::FreesideURL(), + }, + A => { #title => loc('Homepage'), + title => 'Ticketing Main', path => '', }, B => { title => loc('Tickets'), @@ -96,6 +109,8 @@ if (!defined $toptabs) { if (!defined $topactions) { $topactions = $basetopactions; } + + require RT::URI::freeside; # Now let callbacks add their extra tabs $m->comp('/Elements/Callback', diff --git a/rt/html/Elements/TitleBoxStart b/rt/html/Elements/TitleBoxStart index 804e5cfaa..d98fe2744 100644 --- a/rt/html/Elements/TitleBoxStart +++ b/rt/html/Elements/TitleBoxStart @@ -78,7 +78,7 @@ $title_class => '' $titleright_href => undef $titleright => undef -$contentbg => "#dddddd" +$contentbg => "#d4d4d4" $color => "#336699" </%ARGS> <%init> diff --git a/rt/html/Elements/ViewUser b/rt/html/Elements/ViewUser deleted file mode 100644 index 657272496..000000000 --- a/rt/html/Elements/ViewUser +++ /dev/null @@ -1,51 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<& /Elements/TitleBoxStart, - title => "<a class='inverse' href=\"$RT::WebPath/Search/Listing.html?LimitRequestorById=1&IdOfRequestor=".$User->id."\">".loc("Tickets from [_1]", $name)."</a>", - titleright=> "<a class='inverse' href=\"$RT::WebPath/EditUserComments.html?id=".$User->id."\">".loc("Comments about [_1]", $name)."</a>" &> -<TABLE WIDTH="100%"> -<tr> -<td halign=left valign=top> -%while (my $w=$tickets->Next) { -<%$w->Id%>: <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$w->id%>"><%$w->Subject%></a> (<%$w->Status%>)<BR> -%} -</td> -<td align=right valign=top> - <% ($User->Comments || loc("No comment entered about this user")) %> -</tr> -</table> -<& /Elements/TitleBoxEnd &> - -<%ARGS> -$User=>undef -</%ARGS> - -<%INIT> -my $name=$User->RealName || $User->EmailAddress; - -my $tickets = new RT::Tickets($session{'CurrentUser'}); -$tickets->LimitWatcher(TYPE => 'Requestor', VALUE => $User->EmailAddress); - - -</%INIT> diff --git a/rt/html/NoAuth/images/back_home.gif b/rt/html/NoAuth/images/back_home.gif Binary files differdeleted file mode 100644 index 40b19c153..000000000 --- a/rt/html/NoAuth/images/back_home.gif +++ /dev/null diff --git a/rt/html/NoAuth/images/head_requestracker.gif b/rt/html/NoAuth/images/head_requestracker.gif Binary files differdeleted file mode 100644 index 73315e918..000000000 --- a/rt/html/NoAuth/images/head_requestracker.gif +++ /dev/null diff --git a/rt/html/NoAuth/images/rt.jpg b/rt/html/NoAuth/images/rt.jpg Binary files differdeleted file mode 100644 index a137a932b..000000000 --- a/rt/html/NoAuth/images/rt.jpg +++ /dev/null diff --git a/rt/html/NoAuth/images/small-logo.png b/rt/html/NoAuth/images/small-logo.png Binary files differnew file mode 100644 index 000000000..1e415e6d8 --- /dev/null +++ b/rt/html/NoAuth/images/small-logo.png diff --git a/rt/html/NoAuth/images/spacer.gif b/rt/html/NoAuth/images/spacer.gif Binary files differdeleted file mode 100644 index 5bfd67a2d..000000000 --- a/rt/html/NoAuth/images/spacer.gif +++ /dev/null diff --git a/rt/html/NoAuth/images/squares_blue.gif b/rt/html/NoAuth/images/squares_blue.gif Binary files differdeleted file mode 100644 index a28da5ce1..000000000 --- a/rt/html/NoAuth/images/squares_blue.gif +++ /dev/null diff --git a/rt/html/NoAuth/webrt.css b/rt/html/NoAuth/webrt.css index 7fa2f83f8..5c241f93f 100644 --- a/rt/html/NoAuth/webrt.css +++ b/rt/html/NoAuth/webrt.css @@ -1,3 +1,4 @@ +/* %# BEGIN BPS TAGGED BLOCK {{{ %# %# COPYRIGHT: @@ -43,180 +44,191 @@ %# those contributions and any derivatives thereof. %# %# END BPS TAGGED BLOCK }}} -SPAN.nav { font-family: Verdana, Arial, Helvetica, sans-serif; +*/ + +/* * { + font-family: Arial, Verdana, Helvetica, sans-serif; + font-size: 1.2em; +} */ + +SPAN.nav { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 12px; color: #FFFFFF; text-decoration: none; white-space: nowrap} .nav2 { font-size: 10px; white-space: nowrap} -.nav { font-family: Verdana, Arial, Helvetica, sans-serif; +.nav { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 13px; - font-weight: normal; + font-weight: bold; color: #FFFFFF; text-decoration: none; white-space: nowrap} -.currentnav { font-family: Verdana, Arial, Helvetica, sans-serif; +.currentnav { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 13px; font-weight: bold; color: #FFFF66; text-decoration: none; white-space: nowrap} -.topnav { font-family: Verdana, Arial, Helvetica, sans-serif; +.topnav { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 16px; font-weight: normal; color: #FFFFFF; text-decoration: none; white-space: nowrap} +/* %# .topnav is the original RT class for the sidebar navigation tabs. %# Font-sizing by level depth was originally hard-coded into Elements/Menu. %# This modification sets a different class name for each level, allowing %# style sheet control over the formats. +*/ -a.topnav-0 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.topnav-0 { font-family: Verdana, sans-serif; font-size: 16px; font-weight: normal; color: #FFFFFF; text-decoration: none; white-space: nowrap} -a.topnav-1 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.topnav-1 { font-family: Verdana, sans-serif; font-size: 14px; font-weight: normal; color: #FFFFFF; text-decoration: none; white-space: nowrap} -a.topnav-2 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.topnav-2 { font-family: Verdana, sans-serif; font-size: 12px; font-weight: normal; color: #FFFFFF; text-decoration: none; white-space: nowrap} -a.topnav-3 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.topnav-3 { font-family: Verdana, sans-serif; font-size: 11px; font-weight: normal; color: #FFFFFF; text-decoration: none; white-space: nowrap} -a.topnav-4 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.topnav-4 { font-family: Verdana, sans-serif; font-size: 11px; font-weight: normal; color: #FFFFFF; text-decoration: none; white-space: nowrap} -a.topnav-5 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.topnav-5 { font-family: Verdana, sans-serif; font-size: 11px; font-weight: normal; color: #FFFFFF; text-decoration: none; white-space: nowrap} li.topnav-0-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.topnav-1-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.topnav-2-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.topnav-3-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.topnav-4-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.topnav-5-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.topnav-0-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.topnav-1-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.topnav-2-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.topnav-3-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.topnav-4-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.topnav-5-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } -.currenttopnav { font-family: Verdana, Arial, Helvetica, sans-serif; +.currenttopnav { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 16px; font-weight: bold; - color: #FFFF66; + color: #ffffff; background-color: #7e0079; text-decoration: none; white-space: nowrap} +/* %# .currenttopnav is the original RT class for the sidebar navigation tabs. %# Font-sizing by level depth was originally hard-coded into Elements/Menu. %# This modification sets a different class name for each level, allowing %# style sheet control over the formats +*/ -a.currenttopnav-0 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.currenttopnav-0 { font-family: Verdana, sans-serif; font-size: 16px; font-weight: bold; - color: #FFFF66; + color: #ffffff; background-color: #7e0079; text-decoration: none; white-space: nowrap} -a.currenttopnav-1 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.currenttopnav-1 { font-family: Verdana, sans-serif; font-size: 14px; font-weight: bold; - color: #FFFF66; + color: #ffffff; background-color: #7e0079; text-decoration: none; white-space: nowrap} -a.currenttopnav-2 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.currenttopnav-2 { font-family: Verdana, sans-serif; font-size: 12px; font-weight: normal; - color: #FFFF66; + color: #ffffff; background-color: #7e0079; text-decoration: none; white-space: nowrap} -a.currenttopnav-3 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.currenttopnav-3 { font-family: Verdana, sans-serif; font-size: 11px; font-weight: normal; - color: #FFFF66; + color: #ffffff; background-color: #7e0079; text-decoration: none; white-space: nowrap} -a.currenttopnav-4 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.currenttopnav-4 { font-family: Verdana, sans-serif; font-size: 11px; font-weight: normal; - color: #FFFF66; + color: #ffffff; background-color: #7e0079; text-decoration: none; white-space: nowrap} -a.currenttopnav-5 { font-family: Verdana, Arial, Helvetica, sans-serif; +a.currenttopnav-5 { font-family: Verdana, sans-serif; font-size: 11px; font-weight: normal; - color: #FFFF66; + color: #ffffff; background-color: #7e0079; text-decoration: none; white-space: nowrap} li.currenttopnav-0-minor { @@ -225,73 +237,73 @@ li.currenttopnav-0-minor { margin-top: .5em; } li.currenttopnav-1-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.currenttopnav-2-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.currenttopnav-3-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.currenttopnav-4-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.currenttopnav-5-minor { - border-top: solid #999999 1px; + border-top: solid #777777 1px; padding-top: .1em; margin-top: .5em; } li.currenttopnav-0-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.currenttopnav-1-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.currenttopnav-2-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.currenttopnav-3-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.currenttopnav-4-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } li.currenttopnav-5-major { - border-bottom: solid white 1px; + border-bottom: solid black 1px; padding-top: .25em; padding-bottom: .5em; } -.topactions { font-family: Verdana, Arial, Helvetica, sans-serif; +.topactions { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 10px; color: #FFFFFF; text-decoration: none; white-space: nowrap} -.subnav { font-family: Verdana, Arial, Helvetica, sans-serif; +.subnav { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 11px; font-weight: normal; color: #FFFFFF; text-decoration: none; white-space: nowrap} -.currentsubnav { font-family: Verdana, Arial, Helvetica, sans-serif; +.currentsubnav { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 11px; font-weight: bold; color: #FFFF66; @@ -307,12 +319,14 @@ li.currenttopnav-5-major { vertical-align: top; text-align: left; } -.blue { background-color: #4682B4; +.blue { + background-color: #4682B4; +/* %# background-color: #eeeeee; */ background-position: left top; vertical-align: top; text-align: left; } -%# Actually the "topactions" section +/* %# Actually the "topactions" section */ .blueright { background-color: #4682B4; background-position: left top; vertical-align: top; @@ -324,12 +338,123 @@ li.currenttopnav-5-major { vertical-align: top; text-align: left; } -.darkblue { background-color: #000080; +.darkblue { + background-color: #000080; + background-position: left top; + vertical-align: top; + text-align: left; + } +.darkblueright { + background-color: #000080; + background-position: left top; + vertical-align: top; + text-align: right; + } +.lightgray { + background-color: #eeeeee; + background-position: left top; + vertical-align: top; + text-align: left; + } +.lightgrayright { + background-color: #eeeeee; + background-position: left top; + vertical-align: top; + text-align: right; + } +.black { + background-color: #000000; + color: #ffffff; + background-position: left top; + vertical-align: top; + text-align: left; + } +.blackright { + background-color: #000000; + color: #ffffff; + background-position: left top; + vertical-align: center; + text-align: right; + font-size:16px; + padding-right:4px + } + +input.fsblackbutton { + background-color:#333333; + color: #ffffff; + border:1px solid; + border-top-color:#cccccc; + border-left-color:#cccccc; + border-right-color:#aaaaaa; + border-bottom-color:#aaaaaa; + font-family: Arial, Verdana, Helvetica, sans-serif; + font-weight:bold; + padding-left:12px; + padding-right:12px; + overflow:visible; + filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff333333',EndColorStr='#ff666666') +} + +input.fsblackbuttonselected { + background-color:#7e0079; + color: #ffffff; + border:1px solid; + border-top-color:#cccccc; + border-left-color:#cccccc; + border-right-color:#aaaaaa; + border-bottom-color:#aaaaaa; + font-family: Arial, Verdana, Helvetica, sans-serif; + font-weight:bold; + padding-left:12px; + padding-right:12px; + overflow:visible; + filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff330033',EndColorStr='#ff7e0079') +} + +.mediumgray { + background-color: #cccccc; background-position: left top; vertical-align: top; text-align: left; } -.darkblueright { background-color: #000080; +.mediumgrayright { + background-color: #cccccc; + background-position: left top; + vertical-align: top; + text-align: right; + } +.darkmediumgray { + background-color: #aaaaaa; + background-position: left top; + vertical-align: top; + text-align: left; + } +.darkmediumgrayright { + background-color: #aaaaaa; + background-position: left top; + vertical-align: top; + text-align: right; + } +.bggray { + background-color: #e8e8e8; + background-position: left top; + vertical-align: top; + text-align: left; + } +.bggrayright { + background-color: #e8e8e8; + background-position: left top; + vertical-align: top; + text-align: right; + } +.white { + background-color: #ffffff; + background-position: left top; + vertical-align: top; + text-align: left; + } +.whiteright { + background-color: #ffffff; background-position: left top; vertical-align: top; text-align: right; @@ -351,26 +476,26 @@ div.downloadattachment { } -td { font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; +td { font-family: Arial, Verdana, Helvetica, sans-serif; + font-size: 12px; background-position: left top; } .black { background-color: #000000; background-position: left top; } -span.rtname { font-family: Verdana, Arial, Helvetica, sans-serif; +span.rtname { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 18px; font-weight: normal; color: #ffffff} -span.title { font-family: Verdana, Arial, Helvetica, sans-serif; +span.title { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 20px; font-weight: bold; color: #ffffff} -.header { font-family: Verdana, Arial, Helvetica, sans-serif; +.header { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #0066CC} -.subheader { font-family: Verdana, Arial, Helvetica, sans-serif; +.subheader { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 11px; font-weight: bold; color: #0066CC } @@ -381,9 +506,9 @@ span.title { font-family: Verdana, Arial, Helvetica, sans-serif; .labeltop { font-weight: normal; text-align: right; vertical-align: top } -.productnav { font-family: Verdana, Arial, Helvetica, sans-serif; +.productnav { font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 11px; - color: #000000; + color: #FFFFFF; text-align: center; vertical-align: middle; text-decoration: none} @@ -405,6 +530,7 @@ TD.mainbody { padding-right: 1em; margin-left: 1em; margin-right: 1em; + background-color: #e8e8e8; } td.boxcontainer + td.boxcontainer { @@ -447,14 +573,14 @@ TD.titlebox { SPAN.message { font-size: 100%; - font-family: Verdana, Arial, Helvetica, sans-serif; + font-family: Arial, Verdana, Helvetica, sans-serif; } BODY { color: #000; background: #FFFFFF; - font-family: Verdana, Arial, Helvetica, sans-serif; + font-family: "Helvetica", sans-serif; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; @@ -477,7 +603,7 @@ TR.evenline { H1, H2, H3 { margin-top: 0.2em; color: #336699; - font-family: Verdana, Arial, Helvetica, sans-serif; + font-family: "Helvetica", sans-serif; clear: both; } @@ -490,7 +616,7 @@ DIV.endmatter { margin-left: -7% } } -A { font-weight: bold; color: #000000; +A { font-weight: bold; color: #000000 } .currenttab { color: #ffffff;} @@ -504,8 +630,9 @@ A:link IMG, A:visited IMG { border-style: none } a:focus {text-decoration: underline } A IMG { color: white } /* The only way to hide the border in NS 4.x */ -a:link { text-decoration: none} -a:visited { text-decoration: none} +/* a:link { text-decoration: none} */ +/* a:visited { text-decoration: none} */ + a:hover { text-decoration: underline} /* a:focus { background-color: #ccccee } */ @@ -518,7 +645,9 @@ SPAN.date { font-size: 0.8em } span.title { font-size: 1.6em; vertical-align: middle; - color: #ffffff;} +/* %# color: #ffffff; */ + color: #000000; + } span.productname { font-size: 2em; color: #0066cc;} SPAN.titleboxtitle, SPAN.titleboxclose { @@ -615,6 +744,7 @@ textarea.messagebox { width: 100%; } +/* %# Provide a callback for adding/modifying the style sheet. %# http://www.w3.org/TR/REC-CSS1 - section 3.2, says: %# "latter specified rule wins" @@ -626,3 +756,4 @@ inherit => undef $r->content_type('text/css'); #$r->headers_out->{'Expires'} = '+30m'; </%init> +*/ diff --git a/rt/html/Search/Bulk.html b/rt/html/Search/Bulk.html index f9eef26b6..b7c64e3f8 100644 --- a/rt/html/Search/Bulk.html +++ b/rt/html/Search/Bulk.html @@ -68,7 +68,7 @@ $Tickets->RedoSearch(); while (my $Ticket = $Tickets->Next) { $i++; if ($i % 2) { - $bgcolor = "#dddddd"; + $bgcolor = "#d4d4d4"; } else { $bgcolor = "#ffffff"; diff --git a/rt/html/Search/Elements/PickRestriction b/rt/html/Search/Elements/PickRestriction deleted file mode 100644 index ff9b86ba5..000000000 --- a/rt/html/Search/Elements/PickRestriction +++ /dev/null @@ -1,142 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<FORM ACTION="<%$RT::WebPath%>/Search/Listing.html" METHOD="GET"> -<INPUT TYPE=HIDDEN NAME="Bookmark" VALUE="<% $session{'tickets'}->FreezeLimits()%>"> -<& /Elements/TitleBoxStart, title => loc('Refine search')&> -<INPUT TYPE=HIDDEN NAME="CompileRestriction" VALUE=1> - -<ul> -<li><&|/l&>Owner is</&> <& /Elements/SelectBoolean, Name => "OwnerOp", - TrueVal=> '=', - FalseVal => '!=' -&> -<& /Elements/SelectOwner, Name => "ValueOfOwner" &> - -<li> -<& /Elements/SelectWatcherType, Name => "WatcherRole", AllowNull => 0 &> -<&|/l&>email address</&> -<& /Elements/SelectMatch, Name => "WatcherRoleOp" &> -<INPUT Name="ValueOfWatcherRole" SIZE=20> - -<li> -<&|/l&>Subject</&> <& /Elements/SelectMatch, Name => "SubjectOp" &> -<INPUT Name="ValueOfSubject" SIZE=20> - -<li><&|/l&>Queue</&> <& /Elements/SelectBoolean, Name => "QueueOp" , - True => loc("is"), - False => loc("isn't"), - TrueVal=> '=', - FalseVal => '!=' &> -<& /Elements/SelectQueue, Name => "ValueOfQueue" &> - - -<li><&|/l&>Priority</&> <& /Elements/SelectEqualityOperator, Name => "PriorityOp" &> - -<INPUT Name="ValueOfPriority" SIZE=5> - -<li> -<& /Elements/SelectDateType, Name => 'DateType' &> -<& /Elements/SelectDateRelation, Name=>"DateOp" &> -<& /Elements/SelectDate, Name => "ValueOfDate", ShowTime => 0, Default => '' &> - -<li><&|/l&>Ticket attachment</&> - -<& /Elements/SelectAttachmentField, Name => 'AttachmentField' &> -<& /Elements/SelectBoolean, Name => "AttachmentFieldOp", - True => loc("matches"), - False => loc("does not match"), - TrueVal => 'LIKE', - FalseVal => 'NOT LIKE' -&> -<Input Name="ValueOfAttachmentField" Size=20> - -<li><&|/l&>Status</&> -<& /Elements/SelectBoolean, Name => "StatusOp", - True => loc("is"), - False => loc("isn't"), - TrueVal=> '=', - FalseVal => '!=' -&> -<& /Elements/SelectStatus, Name => "ValueOfStatus", SkipDeleted => 1 &> - - -% while ( my $CustomField = $CustomFields->Next ) { - -<li><% $CustomField->Name %> - <& /Elements/SelectCustomFieldOperator, Name => "CustomFieldOp". $CustomField->id, - True => loc("is"), - False => loc("isn't"), - TrueVal=> '=', FalseVal => '!=' &> - -<& /Elements/SelectCustomFieldValue, Name => "CustomField".$CustomField->id, - CustomField => $CustomField, - &> -% } - -</UL> - -<& /Elements/TitleBoxEnd &> - -<& /Elements/TitleBoxStart, title => loc('Ordering and sorting')&> - -<UL> - -<li><&|/l&>Results per page</&> <& /Elements/SelectResultsPerPage, Name => "RowsPerPage", - Default => $session{'tickets_rows_per_page'} || '50' -&> - -<li><&|/l&>Sort results by</&> <& /Elements/SelectTicketSortBy, Name => "TicketsSortBy", - Default => $session{'tickets_sort_by'} -&> -<& /Elements/SelectSortOrder, Name => 'TicketsSortOrder', Default => $session{'tickets_sort_order'} &> - -<li><input type="checkbox" name="HideResults" <%$ARGS{'HideResults'} && 'CHECKED'%>> <&|/l&>Don't show search results</&> -<li><& /Elements/Refresh, Name => 'RefreshSearchInterval' , Default => $session{'tickets_refresh_interval'} &> - -</UL> - - -</DIV> - - - -<& /Elements/TitleBoxEnd &> - -<& /Elements/Submit, Label => loc('Search'), Name => 'Action'&> - -</FORM> - - - <%INIT> -my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'}); - foreach ( $session{'tickets'}->RestrictionValues('Queue') ) { - # Gotta load up the $queue object, since queues get stored by name now. - my $queue = RT::Queue->new($session{'CurrentUser'}); - $queue->Load($_); - $CustomFields->LimitToQueue($queue->Id); - } - - $CustomFields->LimitToGlobal(); - -</%INIT> diff --git a/rt/html/Search/Elements/TicketHeader b/rt/html/Search/Elements/TicketHeader deleted file mode 100644 index ed2f60e4e..000000000 --- a/rt/html/Search/Elements/TicketHeader +++ /dev/null @@ -1,40 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<TR> -<& TicketHeaderCell , Attribute => 'id', Header => '#'&> -<& TicketHeaderCell , Attribute => 'Subject'&> -<& TicketHeaderCell , Attribute => 'Status'&> -<& TicketHeaderCell , Attribute => 'Queue'&> -<& TicketHeaderCell , Attribute => 'Owner'&> -<& TicketHeaderCell , Attribute => 'Priority'&> -</TR> -<TR> -<TH class="ticketheader"> </TH> -<& TicketHeaderCell , Attribute => 'Requestor(s)'&> -<& TicketHeaderCell , Attribute => 'Created'&> -<& TicketHeaderCell , Attribute => 'Told', Header => 'Last Contact'&> -<& TicketHeaderCell , Attribute => 'LastUpdated', Header => 'Last Updated'&> -<& TicketHeaderCell , Attribute => 'TimeLeft', Header => 'Left'&> -</TR> -%# loc('Last Notified'); diff --git a/rt/html/Search/Elements/TicketHeaderCell b/rt/html/Search/Elements/TicketHeaderCell deleted file mode 100644 index 5def9ea37..000000000 --- a/rt/html/Search/Elements/TicketHeaderCell +++ /dev/null @@ -1,55 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<%INIT> -my ($order,$curorder); - $Attribute =~ s/Obj->(Name|AsString|AgeAsString)//g; - if ($session{'tickets_sort_order'} =~ /^asc$/i) { - $order = 'DESC'; - $curorder = 'ASC'; - } else { - $order = 'ASC'; - $curorder = 'DESC'; - } -$Header = $Attribute unless ($Header); - -</%INIT> -<th class="ticketheader"> -% if (grep (/^$Attribute$/i, $session{'tickets'}->SortFields)) { -<A -% if ($Attribute eq $session{'tickets_sort_by'}) { -class="currenttab" -HREF="<% $RT::WebPath%>/Search/Listing.html?Bookmark=<%$session{'tickets'}->FreezeLimits()|u%>&TicketsSortBy=<%$Attribute%>&TicketsSortOrder=<%$order%>&RowsPerPage=<%$session{'tickets_rows_per_page'}%>"> -% } else { -HREF="<% $RT::WebPath%>/Search/Listing.html?Bookmark=<%$session{'tickets'}->FreezeLimits()|u%>&TicketsSortBy=<%$Attribute%>&TicketsSortOrder=<%$curorder%>&RowsPerPage=<%$session{'tickets_rows_per_page'}%>"> -% } -<% loc($Header) %> -</A> -% } else { -<% loc($Header) %> -% } -</th> -<%ARGS> -$Header => undef -$Attribute => undef -</%ARGS> diff --git a/rt/html/Search/Elements/TicketRow b/rt/html/Search/Elements/TicketRow deleted file mode 100644 index 5d1ad209a..000000000 --- a/rt/html/Search/Elements/TicketRow +++ /dev/null @@ -1,55 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<SPAN class="search"> -<TR -% if ($i%2) { -CLASS="oddline" -% } else { -CLASS="evenline" -% } -> -<TD ROWSPAN="2"><B><A HREF="<%$RT::WebPath%>/Ticket/Display.html?id=<%$Ticket->Id%>"><%$Ticket->id%></a></B></TD> -<TD><B><A HREF="<%$RT::WebPath%>/Ticket/Display.html?id=<%$Ticket->Id%>"><%$Ticket->Subject%></a></B></TD> -<TD><%loc($Ticket->Status)%></TD> -<TD><%$Ticket->QueueObj->Name%></TD> -<TD><%$Ticket->Owner == $RT::Nobody->Id ? loc('Nobody') : $Ticket->OwnerObj->Name%></TD> -<TD><%$Ticket->Priority%></TD> -</TR> -<TR -% if ($i%2) { -CLASS="oddline" -% } else { -CLASS="evenline" -% } -><TD><small><%$Ticket->Requestors->MemberEmailAddressesAsString%></small></TD> -<TD><SMALL><%$Ticket->CreatedObj->AgeAsString || '-'%></SMALL></TD> -<TD><SMALL><%$Ticket->ToldObj->AgeAsString || '-'%></SMALL></TD> -<TD><SMALL><%$Ticket->LastUpdatedObj->AgeAsString || '-'%></SMALL></TD> -<TD><SMALL><%$Ticket->TimeLeft%></SMALL></TD> -</TR> -</SPAN> -<%ARGS> -$Ticket => undef -$i => undef -</%ARGS> diff --git a/rt/html/Search/Listing.html b/rt/html/Search/Listing.html deleted file mode 100644 index 68b1fd75c..000000000 --- a/rt/html/Search/Listing.html +++ /dev/null @@ -1,113 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<& /Elements/Header, Title => $title, Refresh => $session{'tickets_refresh_interval'} &> -<& /Ticket/Elements/Tabs, - current_tab => 'Search/Listing.html', - Title => $title &> - -%if ($ticketcount && ! $ARGS{'HideResults'}) { -<TABLE WIDTH=100% border=0 cellpadding=2 CELLSPACING=0> -<& Elements/TicketHeader, %ARGS &> -% my $i; -%while (my $Ticket = $session{'tickets'}->Next) { -% $i++; -<& Elements/TicketRow, Ticket => $Ticket, i=> $i, %ARGS &> -%} -</TABLE> -<div align=center> -<font size=2> -<a href="<%$RT::WebPath%>/Search/Listing.html?GotoPage=1"><&|/l&>First page</&></a> - -% if ( $session{'tickets'}->FirstRow >= $session{'tickets_rows_per_page'}-1 ) { -<a href="<%$RT::WebPath%>/Search/Listing.html?GotoPage=Prev"><<&|/l&>Previous page</&></a> - -% } -% if ( $session{'tickets'}->FirstRow + $session{'tickets_rows_per_page'} < $ticketcount ) { -<a href="<%$RT::WebPath%>/Search/Listing.html?GotoPage=Next"><&|/l&>Next page</&>></a> -% } -%# <form method=get action="<%$RT::WebPath%>/Search/Listing.html"><&|/l&>Goto page</&> <input name=GotoPage size=2></form> -</font> -</div> -<!--<div align=right>--> -<table width="100%" border=0 cellpadding=3 CELLSPACING=1> -<tr> -<td align=left> -(<&|/l, ($session{'tickets'}->FirstRow+1), ($session{'tickets'}->FirstRow() + $session{'tickets'}->RowsPerPage() ) &>[_1] - [_2] shown</&>) -</td> -<td align=right> - -<a href="<%$RT::WebPath%>/Search/Bulk.html"><&|/l&>Update all these tickets at once</&></a> -<!--</div>--> -</td> -</tr> -</table> - -% } -<TABLE WIDTH="100%"> -<TR> -<TD VALIGN="TOP"> -<& /Elements/TitleBoxStart, title => loc('Current search criteria')&> - -%my %restrictions=$session{'tickets'}->DescribeRestrictions(); -%foreach my $row (keys %restrictions){ -<%$restrictions{"$row"}%> <A HREF="<% $RT::WebPath %>/Search/Listing.html?DeleteRestriction=<%$row%>">[<&|/l&>delete</&>]</a><br> -%} -<BR> -<BR> -<A HREF="<% $RT::WebPath%>/Search/Listing.html?Bookmark=<%$session{'tickets'}->FreezeLimits()|nu%>&TicketsSortBy=<%$session{'tickets_sort_by'}%>&TicketsSortOrder=<%$session{'tickets_sort_order'}%>&RowsPerPage=<%$session{'tickets_rows_per_page'}%>"><&|/l&>Bookmarkable URL for this search</&></a> -<& /Elements/TitleBoxEnd&> -</TD> -<TD> - -<& Elements/PickRestriction, %ARGS &> - -</TD> -</TR> -</TABLE> - -<%INIT> - -my ($title, $ticketcount); -$session{'i'}++; -if ($session{'tickets'}) { - if ($ARGS{'DeleteRestriction'}) { - $session{'tickets'}->DeleteRestriction($ARGS{'DeleteRestriction'}); - } - if ( ($ARGS{'ClearRestrictions'}) || ($ARGS{'NewSearch'}) ) { - $session{'tickets'}->ClearRestrictions; - $session{'tickets'}->CleanSlate; - } -} - ProcessSearchQuery(ARGS=>\%ARGS); - $session{'tickets'}->RedoSearch(); - if ( $session{'tickets'}->DescribeRestrictions()) { - $ticketcount = $session{tickets}->CountAll(); - $title = loc('Found [quant,_1,ticket]', $ticketcount); - } else { - $title = loc("Find tickets"); - } -</%INIT> -<%CLEANUP> -$session{'tickets'}->PrepForSerialization(); -</%CLEANUP> diff --git a/rt/html/Ticket/Elements/AddCustomers b/rt/html/Ticket/Elements/AddCustomers new file mode 100644 index 000000000..01c7367c4 --- /dev/null +++ b/rt/html/Ticket/Elements/AddCustomers @@ -0,0 +1,50 @@ +%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am> +%# +%# 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. +<BR> +<%$msg%><br> + +% if (@Customers) { + +<br><i>(Check box to link)<i> +<table> +% foreach my $customer (@Customers) { +<tr> + <td> + <input type="checkbox" name="Ticket-AddCustomer-<% $customer->{'custnum'} %>" VALUE="1" <% scalar(@Customers) == 1 ? 'CHECKED' : '' %>> + <A HREF="<%$freeside_url%>/view/cust_main.cgi?<% $customer->{'custnum'} %>"><% &RT::URI::freeside::small_custview($customer->{'custnum'}, &RT::URI::freeside::FreesideGetConfig('countrydefault'), 1) |n %> + </td> +</tr> +% } + +% } + +<%INIT> +my ($msg); + +my $freeside_url = &RT::URI::freeside::FreesideURL(); + +my @Customers = (); +if ( $CustomerString ) { + @Customers = &RT::URI::freeside::smart_search( 'search' => $CustomerString ); +} + +my @Services = (); +if ($ServiceString) { + @Services = (); #service_search(); +} + +</%INIT> + +<%ARGS> +$CustomerString => undef +$ServiceString => undef +</%ARGS> diff --git a/rt/html/Ticket/Elements/EditCustomers b/rt/html/Ticket/Elements/EditCustomers new file mode 100644 index 000000000..c5a6f708c --- /dev/null +++ b/rt/html/Ticket/Elements/EditCustomers @@ -0,0 +1,67 @@ +%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am> +%# +%# 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. +<TABLE width=100%> + <TR> + <TD VALIGN=TOP WIDTH=50%> + <h3><&|/l&>Current Customers</&></h3> + +<table> + <tr> + <td><i><&|/l&>(Check box to disassociate)</&></i></td> + </tr> + <tr> + <td class="value"> +% #while (my $link = $Ticket->MemberOf->Next) { +% foreach my $link ( +% grep { $_->TargetURI->Resolver->{'fstable'} eq 'cust_main' } +% grep { $_->TargetURI->Scheme eq 'freeside' } +% @{ $Ticket->_Links('Base')->ItemsArrayRef } +% ) { + + <INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>"> +%# <& ShowLink, URI => $link->TargetURI &><br> + <A HREF="<% $link->TargetURI->Resolver->HREF %>"><% $link->TargetURI->Resolver->AsStringLong |n %></A> + <BR> +% } + </td> + </tr> +</table> + +</TD> + +<TD VALIGN=TOP> +<h3><&|/l&>New Customer Links</&></h3> +<&|/l&>Find customer</&><BR> +<input name="CustomerString"> +<input type=submit name="OnlySearchForCustomers" value="<&|/l&>Go!</&>"> +<br><i>cust #, name, company or phone</i> +<BR> +%#<BR> +%#<&|/l&>Find service</&><BR> +%#<input name="ServiceString"> +%#<input type=submit name="OnlySearchForServices" value="<&|/l&>Go!</&>"> +%#<br><i>username, username@domain, domain, or IP address</i> +%#<BR> + +<& AddCustomers, Ticket => $Ticket, + CustomerString => $CustomerString, + ServiceString => $ServiceString, &> + +</TD> +</TR> +</TABLE> + +<%ARGS> +$CustomerString => undef +$ServiceString => undef +$Ticket => undef +</%ARGS> diff --git a/rt/html/Ticket/Elements/EditLinks b/rt/html/Ticket/Elements/EditLinks deleted file mode 100644 index bdb8a6b7d..000000000 --- a/rt/html/Ticket/Elements/EditLinks +++ /dev/null @@ -1,133 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<TABLE width=100%> - <TR> - <TD VALIGN=TOP WIDTH=50%> - <h3><&|/l&>Current Relationships</&></h3> - -<table> - <tr> - <td></td> - <td><i><&|/l&>(Check box to delete)</&></i></td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Depends on</&>:</td> - <td class="value"> -% while (my $link = $Ticket->DependsOn->Next) { - <INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>"> - <& ShowLink, URI => $link->TargetURI &><br> -% } - </td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Depended on by</&>:</td> - <td class="value"> -% while (my $link = $Ticket->DependedOnBy->Next) { -% my $member = $link->BaseObj; - <INPUT TYPE=CHECKBOX NAME="DeleteLink-<%$link->Base%>-<%$link->Type%>-"> - <& ShowLink, URI => $link->BaseURI &><br> -% } - </td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Parents</&>:</td> - <td class="value"> -% while (my $link = $Ticket->MemberOf->Next) { - <INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>"> - <& ShowLink, URI => $link->TargetURI &><br> -% } - </td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Children</&>:</td> - <td class="value"> -% while (my $link = $Ticket->Members->Next) { - <INPUT TYPE=CHECKBOX NAME="DeleteLink-<%$link->Base%>-<%$link->Type%>-"> - <& ShowLink, URI => $link->BaseURI &><br> -% } - </td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Refers to</&>:</td> - <td class="value"> -% while (my $link = $Ticket->RefersTo->Next) { - <INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>"> - <& ShowLink, URI => $link->TargetURI &><br> -%} - </td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Referred to by</&>:</td> - <td class="value"> -% while (my $link = $Ticket->ReferredToBy->Next) { - <INPUT TYPE=CHECKBOX NAME="DeleteLink-<%$link->Base%>-<%$link->Type%>-"> - <& ShowLink, URI => $link->BaseURI &><br> -% } - </td> - </tr> -</table> - -</TD> -<TD VALIGN=TOP> -<h3><&|/l&>New Relationships</&></h3> -<i><&|/l&>Enter tickets or URIs to link tickets to. Seperate multiple entries with spaces.</&></i><br> -<TABLE> - <TR> - <TD class="label"><&|/l&>Merge into</&>:</TD> - <TD class="entry"><input name="<%$Ticket->Id%>-MergeInto"> <i><&|/l&>(only one ticket)</&></i></TD> - </TR> - <TR> - <TD class="label"><&|/l&>Depends on</&>:</TD> - <TD class="entry"><input name="<%$Ticket->Id%>-DependsOn"></TD> - </TR> - <TR> - <TD class="label"><&|/l&>Depended on by</&>:</TD> - <TD class="entry"><input name="DependsOn-<%$Ticket->Id%>"></TD> - </TR> - <TR> - <TD class="label"><&|/l&>Parents</&>:</TD> - <TD class="entry"><input name="<%$Ticket->Id%>-MemberOf"></TD> - </TR> - <TR> - <TD class="label"><&|/l&>Children</&>:</TD> - <TD class="entry"> <input name="MemberOf-<%$Ticket->Id%>"></TD> - </TR> - <TR> - <TD class="label"><&|/l&>Refers to</&>:</TD> - <TD class="entry"><input name="<%$Ticket->Id%>-RefersTo"></TD> - </TR> - <TR> - <TD class="label"><&|/l&>Referred to by</&>:</TD> - <TD class="entry"> <input name="RefersTo-<%$Ticket->Id%>"></TD> - </TR> -</TABLE> -</TD> -</TR> -</TABLE> - - - -<%ARGS> -$Ticket => undef -</%ARGS> diff --git a/rt/html/Ticket/Elements/ShowCustomers b/rt/html/Ticket/Elements/ShowCustomers new file mode 100644 index 000000000..612727ede --- /dev/null +++ b/rt/html/Ticket/Elements/ShowCustomers @@ -0,0 +1,40 @@ +%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am> +%# +%# 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. +<table> +% my $cust = 0; +% foreach my $customerURI ( +% grep { $_->Resolver->{'fstable'} eq 'cust_main' } +% grep { $_->Scheme eq 'freeside' } +% map { $_->TargetURI } +% @{ $Ticket->_Links('Base')->ItemsArrayRef } +% ) { +% $cust++; +% my $cust_main = ''; + <tr> + <td class="value"> + <A HREF="<% $customerURI->Resolver->HREF %>"><% $customerURI->Resolver->AsStringLong |n %></A> + </td> + </tr> +% } +% unless ( $cust ) { + <tr> + <td class="labeltop"> + <i>(none)<i> + </td> + </tr> + +% } +</table> +<%ARGS> +$Ticket => undef +</%ARGS> + diff --git a/rt/html/Ticket/Elements/ShowLink b/rt/html/Ticket/Elements/ShowLink deleted file mode 100644 index 493fd95a5..000000000 --- a/rt/html/Ticket/Elements/ShowLink +++ /dev/null @@ -1,40 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<A href="<%$URI->Resolver->HREF%>"> -% if ($URI->IsLocal) { -% my $member = $URI->Object; -% if (UNIVERSAL::isa($member, "RT::Ticket")) { -<%$member->Id%>: (<%$member->OwnerObj->Name%>) <%$member->Subject%> [<% loc($member->Status) %>] -% } elsif ( UNIVERSAL::can($member, 'Name')) { -<%$URI->Resolver->AsString%>: <%$member->Name%> -% } else { -<%$URI->Resolver->AsString%> -% } -% } else { -<%$URI->Resolver->AsString%> -% } -</a> -<%ARGS> -$URI => undef -</%ARGS> diff --git a/rt/html/Ticket/Elements/ShowLinks b/rt/html/Ticket/Elements/ShowLinks deleted file mode 100644 index f88a6008d..000000000 --- a/rt/html/Ticket/Elements/ShowLinks +++ /dev/null @@ -1,87 +0,0 @@ -%# BEGIN LICENSE BLOCK -%# -%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -%# -%# (Except where explictly superceded by other copyright notices) -%# -%# 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. -%# -%# Unless otherwise specified, all modifications, corrections or -%# extensions to this work which alter its source code become the -%# property of Best Practical Solutions, LLC when submitted for -%# inclusion in the work. -%# -%# -%# END LICENSE BLOCK -<table> - <tr> - <td class="labeltop"><&|/l&>Depends on</&>:</td> - <td class="value"> -<ul> -% while (my $Link = $Ticket->DependsOn->Next) { -<li><& ShowLink, URI => $Link->TargetURI &> -% } -</ul> - </td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Depended on by</&>:</td> - <td class="value"> -<ul> -% while (my $Link = $Ticket->DependedOnBy->Next) { -<li><& ShowLink, URI => $Link->BaseURI &> -% } -</ul> - </td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Parents</&>:</td> - <td class="value"> -<ul> -% while (my $Link = $Ticket->MemberOf->Next) { -<li><& ShowLink, URI => $Link->TargetURI &> -% } -</ul> - </td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Children</&>:</td> - <td class="value"><& /Ticket/Elements/ShowMembers, Ticket => $Ticket &></td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Refers to</&>:</td> - <td class="value"> -<ul> -% while (my $Link = $Ticket->RefersTo->Next) { -<li><& ShowLink, URI => $Link->TargetURI &> -% } -</ul> - </td> - </tr> - <tr> - <td class="labeltop"><&|/l&>Referred to by</&>:</td> - <td class="value"> - <ul> -% while (my $Link = $Ticket->ReferredToBy->Next) { -<li><& ShowLink, URI => $Link->BaseURI &> -% } -</ul> - </td> - </tr> - -% # Allow people to add more rows to the table -% $m->comp('/Elements/Callback', %ARGS ); - -</table> - -<%ARGS> -$Ticket => undef -</%ARGS> diff --git a/rt/html/Ticket/Elements/ShowSummary b/rt/html/Ticket/Elements/ShowSummary index 31571400e..5a6e7e099 100644 --- a/rt/html/Ticket/Elements/ShowSummary +++ b/rt/html/Ticket/Elements/ShowSummary @@ -69,6 +69,15 @@ color => "#333399" &> <& /Ticket/Elements/ShowPeople, Ticket => $Ticket &> <& /Elements/TitleBoxEnd &> + <br> + + <& /Elements/TitleBoxStart, title => loc('Customers'), + title_href =>"$RT::WebPath/Ticket/ModifyCustomers.html?id=".$Ticket->Id, + title_class=> 'inverse', + color => "#7f007b" &> + <& /Ticket/Elements/ShowCustomers, Ticket => $Ticket &> + <& /Elements/TitleBoxEnd &> + <BR> </TD> <TD VALIGN=TOP WIDTH="50%" class="boxcontainer"> diff --git a/rt/html/Ticket/Elements/Tabs b/rt/html/Ticket/Elements/Tabs index 1a5058691..46e1d4a27 100644 --- a/rt/html/Ticket/Elements/Tabs +++ b/rt/html/Ticket/Elements/Tabs @@ -119,6 +119,8 @@ my $ticket_page_tabs = { { title => loc('People'), path => "Ticket/ModifyPeople.html?id=" . $id, }, _E => { title => loc('Links'), path => "Ticket/ModifyLinks.html?id=" . $id, }, + _Eb=> { title => loc('Customers'), + path => "Ticket/ModifyCustomers.html?id=" . $id, }, _F => { title => loc('Jumbo'), path => "Ticket/ModifyAll.html?id=" . $id, separator => 1 diff --git a/rt/html/Ticket/ModifyCustomers.html b/rt/html/Ticket/ModifyCustomers.html new file mode 100644 index 000000000..72d103b23 --- /dev/null +++ b/rt/html/Ticket/ModifyCustomers.html @@ -0,0 +1,49 @@ +%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am> +%# +%# 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. +<& /Elements/Header, Title => loc("Customers for ticket #[_1]", $Ticket->Id) &> +<& /Ticket/Elements/Tabs, + Ticket => $Ticket, + current_tab => "Ticket/ModifyCustomers.html?id=".$Ticket->Id, + Title => loc("Customers for ticket #[_1]", $Ticket->Id) &> + +<& /Elements/ListActions, actions => \@results &> + +<form action="ModifyCustomers.html" method="post"> +<input type="hidden" name="id" value="<%$Ticket->id%>"> + +<& /Elements/TitleBoxStart, title => loc('Edit Customer Links'), color => "#7f007b"&> +<& Elements/EditCustomers, Ticket => $Ticket, CustomerString => $CustomerString, ServiceString => $ServiceString &> +<& /Elements/TitleBoxEnd &> +<& /Elements/Submit, color => "#7f007b", Label => loc('Save Changes') &> +</form> + + +<%INIT> + +my @results = (); +my $Ticket = LoadTicket($id); + +# if we're trying to search for customers/services and nothing else +unless ( $OnlySearchForCustomers || $OnlySearchForServices) { + @results = ProcessTicketCustomers( TicketObj => $Ticket, ARGSRef => \%ARGS); +} + +</%INIT> + + +<%ARGS> +$OnlySearchForCustomers => undef +$OnlySearchForServices => undef +$CustomerString => undef +$ServiceString => undef +$id => undef +</%ARGS> diff --git a/rt/lib/RT.pm b/rt/lib/RT.pm index 7e941a2b2..90c332bc0 100644 --- a/rt/lib/RT.pm +++ b/rt/lib/RT.pm @@ -47,7 +47,7 @@ use vars qw($VERSION $System $SystemUser $Nobody $Handle $Logger $MasonSessionDir ); -$VERSION = '3.0.9'; +$VERSION = '3.0.4'; $CORE_CONFIG_FILE = "/opt/rt3/etc/RT_Config.pm"; $SITE_CONFIG_FILE = "/opt/rt3/etc/RT_SiteConfig.pm"; @@ -117,10 +117,13 @@ sub LoadConfig { =cut sub Init { - + require RT::Handle; #Get a database connection - ConnectToDatabase(); - + unless ($Handle && $Handle->dbh->ping) { + $Handle = RT::Handle->new(); + } + $Handle->Connect(); + #RT's system user is a genuine database user. its id lives here $SystemUser = new RT::CurrentUser(); $SystemUser->LoadByName('RT_System'); @@ -134,21 +137,6 @@ sub Init { InitLogging(); } - -=head2 ConnectToDatabase - -Get a database connection - -=cut - -sub ConnectToDatabase { - require RT::Handle; - unless ($Handle && $Handle->dbh && $Handle->dbh->ping) { - $Handle = RT::Handle->new(); - } - $Handle->Connect(); -} - =head2 InitLogging Create the RT::Logger object. @@ -294,15 +282,8 @@ sub DropSetGIDPermissions { =head1 BUGS -Please report them to rt-3.0-bugs@fsck.com, if you know what's broken and have at least some idea of what needs to be fixed. -If you're not sure what's going on, report them rt-devel@lists.fsck.com. - =head1 SEE ALSO -L<RT::StyleGuide> -L<DBIx::SearchBuilder> - - =begin testing diff --git a/rt/lib/RT/ACE.pm b/rt/lib/RT/ACE.pm index 9073b02b9..1501a125e 100755 --- a/rt/lib/RT/ACE.pm +++ b/rt/lib/RT/ACE.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -83,7 +61,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -126,7 +104,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -135,14 +113,14 @@ Returns the current value of id. =cut -=head2 PrincipalType +=item PrincipalType Returns the current value of PrincipalType. (In the database, PrincipalType is stored as varchar(25).) -=head2 SetPrincipalType VALUE +=item SetPrincipalType VALUE Set PrincipalType to VALUE. @@ -153,14 +131,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 PrincipalId +=item PrincipalId Returns the current value of PrincipalId. (In the database, PrincipalId is stored as int(11).) -=head2 SetPrincipalId VALUE +=item SetPrincipalId VALUE Set PrincipalId to VALUE. @@ -171,14 +149,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 RightName +=item RightName Returns the current value of RightName. (In the database, RightName is stored as varchar(25).) -=head2 SetRightName VALUE +=item SetRightName VALUE Set RightName to VALUE. @@ -189,14 +167,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ObjectType +=item ObjectType Returns the current value of ObjectType. (In the database, ObjectType is stored as varchar(25).) -=head2 SetObjectType VALUE +=item SetObjectType VALUE Set ObjectType to VALUE. @@ -207,14 +185,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ObjectId +=item ObjectId Returns the current value of ObjectId. (In the database, ObjectId is stored as int(11).) -=head2 SetObjectId VALUE +=item SetObjectId VALUE Set ObjectId to VALUE. @@ -225,14 +203,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 DelegatedBy +=item DelegatedBy Returns the current value of DelegatedBy. (In the database, DelegatedBy is stored as int(11).) -=head2 SetDelegatedBy VALUE +=item SetDelegatedBy VALUE Set DelegatedBy to VALUE. @@ -243,14 +221,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 DelegatedFrom +=item DelegatedFrom Returns the current value of DelegatedFrom. (In the database, DelegatedFrom is stored as int(11).) -=head2 SetDelegatedFrom VALUE +=item SetDelegatedFrom VALUE Set DelegatedFrom to VALUE. @@ -262,25 +240,25 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, PrincipalType => - {read => 1, write => 1, sql_type => 12, length => 25, is_blob => 0, is_numeric => 0, type => 'varchar(25)', default => ''}, + {read => 1, write => 1, type => 'varchar(25)', default => ''}, PrincipalId => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, RightName => - {read => 1, write => 1, sql_type => 12, length => 25, is_blob => 0, is_numeric => 0, type => 'varchar(25)', default => ''}, + {read => 1, write => 1, type => 'varchar(25)', default => ''}, ObjectType => - {read => 1, write => 1, sql_type => 12, length => 25, is_blob => 0, is_numeric => 0, type => 'varchar(25)', default => ''}, + {read => 1, write => 1, type => 'varchar(25)', default => ''}, ObjectId => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, DelegatedBy => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, DelegatedFrom => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, } }; @@ -312,7 +290,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/ACL.pm b/rt/lib/RT/ACL.pm index aafc1d22c..81f59c6d0 100755 --- a/rt/lib/RT/ACL.pm +++ b/rt/lib/RT/ACL.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::ACE item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Action/Autoreply.pm b/rt/lib/RT/Action/Autoreply.pm index c1ac5f897..81f7bddfa 100755 --- a/rt/lib/RT/Action/Autoreply.pm +++ b/rt/lib/RT/Action/Autoreply.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK package RT::Action::Autoreply; require RT::Action::SendEmail; @@ -50,18 +28,6 @@ use strict; use vars qw/@ISA/; @ISA = qw(RT::Action::SendEmail); -=head2 Prepare - -Set up the relevant recipients, then call our parent. - -=cut - - -sub Prepare { - my $self = shift; - $self->SetRecipients(); - $self->SUPER::Prepare(); -} # {{{ sub SetRecipients @@ -108,18 +74,10 @@ sub SetReturnAddress { } unless ($self->TemplateObj->MIMEObj->head->get('From')) { - if ($RT::UseFriendlyFromLine) { - my $friendly_name = $self->TicketObj->QueueObj->Description || - $self->TicketObj->QueueObj->Name; - $friendly_name =~ s/"/\\"/g; - $self->SetHeader( 'From', - sprintf($RT::FriendlyFromLineFormat, - $self->MIMEEncodeString( $friendly_name, $RT::EmailOutputEncoding ), $replyto), - ); - } - else { - $self->SetHeader( 'From', $replyto ); - } + my $friendly_name = $self->TicketObj->QueueObj->Description || + $self->TicketObj->QueueObj->Name; + $friendly_name =~ s/"/\\"/g; + $self->SetHeader('From', "\"$friendly_name\" <$replyto>"); } unless ($self->TemplateObj->MIMEObj->head->get('Reply-To')) { diff --git a/rt/lib/RT/Action/Generic.pm b/rt/lib/RT/Action/Generic.pm index cf7600a63..007d299c7 100755 --- a/rt/lib/RT/Action/Generic.pm +++ b/rt/lib/RT/Action/Generic.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,30 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# CONTRIBUTION SUBMISSION POLICY: +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# (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 }}} - +# END LICENSE BLOCK =head1 NAME RT::Action::Generic - a generic baseclass for RT Actions @@ -67,9 +44,6 @@ ok (require RT::Action::Generic); package RT::Action::Generic; use strict; -use Scalar::Util; - -use base qw/RT::Base/; # {{{ sub new sub new { @@ -82,35 +56,31 @@ sub new { } # }}} +# {{{ sub new +sub loc { + my $self = shift; + return $self->{'ScripObj'}->loc(@_); +} +# }}} + # {{{ sub _Init sub _Init { my $self = shift; - my %args = ( Argument => undef, - CurrentUser => undef, - ScripActionObj => undef, - ScripObj => undef, - TemplateObj => undef, - TicketObj => undef, - TransactionObj => undef, - Type => undef, - - @_ ); - + my %args = ( TransactionObj => undef, + TicketObj => undef, + ScripObj => undef, + TemplateObj => undef, + Argument => undef, + Type => undef, + @_ ); + + $self->{'Argument'} = $args{'Argument'}; - $self->CurrentUser( $args{'CurrentUser'}); - $self->{'ScripActionObj'} = $args{'ScripActionObj'}; $self->{'ScripObj'} = $args{'ScripObj'}; - $self->{'TemplateObj'} = $args{'TemplateObj'}; $self->{'TicketObj'} = $args{'TicketObj'}; $self->{'TransactionObj'} = $args{'TransactionObj'}; + $self->{'TemplateObj'} = $args{'TemplateObj'}; $self->{'Type'} = $args{'Type'}; - - Scalar::Util::weaken($self->{'ScripActionObj'}); - Scalar::Util::weaken($self->{'ScripObj'}); - Scalar::Util::weaken($self->{'TemplateObj'}); - Scalar::Util::weaken($self->{'TicketObj'}); - Scalar::Util::weaken($self->{'TransactionObj'}); - } # }}} @@ -151,13 +121,6 @@ sub ScripObj { } # }}} -# {{{ sub ScripActionObj -sub ScripActionObj { - my $self = shift; - return($self->{'ScripActionObj'}); -} -# }}} - # {{{ sub Type sub Type { my $self = shift; @@ -213,11 +176,13 @@ sub DESTROY { # We need to clean up all the references that might maybe get # oddly circular - $self->{'ScripActionObj'} = undef; - $self->{'ScripObj'} = undef; $self->{'TemplateObj'} =undef $self->{'TicketObj'} = undef; $self->{'TransactionObj'} = undef; + $self->{'ScripObj'} = undef; + + + } # }}} diff --git a/rt/lib/RT/Action/Notify.pm b/rt/lib/RT/Action/Notify.pm index 0daaa5586..1e4e4c073 100755 --- a/rt/lib/RT/Action/Notify.pm +++ b/rt/lib/RT/Action/Notify.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,51 +14,20 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} -# +# END LICENSE BLOCK package RT::Action::Notify; require RT::Action::SendEmail; -use Mail::Address; + use strict; use vars qw/@ISA/; @ISA = qw(RT::Action::SendEmail); - -=head2 Prepare - -Set up the relevant recipients, then call our parent. - -=cut - - -sub Prepare { - my $self = shift; - $self->SetRecipients(); - $self->SUPER::Prepare(); -} - # {{{ sub SetRecipients =head2 SetRecipients @@ -84,18 +47,10 @@ sub SetRecipients { my ( @To, @PseudoTo, @Cc, @Bcc ); - if ( $arg =~ /\bOtherRecipients\b/ ) { - if ( $self->TransactionObj->Attachments->First ) { - my @cc_addresses = Mail::Address->parse($self->TransactionObj->Attachments->First->GetHeader('RT-Send-Cc')); - foreach my $addr (@cc_addresses) { - push @Cc, $addr->address; - } - my @bcc_addresses = Mail::Address->parse($self->TransactionObj->Attachments->First->GetHeader('RT-Send-Bcc')); - - foreach my $addr (@bcc_addresses) { - push @Bcc, $addr->address; - } - + if ($arg =~ /\bOtherRecipients\b/) { + if ($self->TransactionObj->Attachments->First) { + push (@Cc, $self->TransactionObj->Attachments->First->GetHeader('RT-Send-Cc')); + push (@Bcc, $self->TransactionObj->Attachments->First->GetHeader('RT-Send-Bcc')); } } @@ -158,12 +113,12 @@ sub SetRecipients { @{ $self->{'Bcc'} } = @Bcc; } else { - @{ $self->{'To'} } = grep ( lc $_ ne lc $creator, @To ); - @{ $self->{'Cc'} } = grep ( lc $_ ne lc $creator, @Cc ); - @{ $self->{'Bcc'} } = grep ( lc $_ ne lc $creator, @Bcc ); + @{ $self->{'To'} } = grep ( !/^$creator$/, @To ); + @{ $self->{'Cc'} } = grep ( !/^$creator$/, @Cc ); + @{ $self->{'Bcc'} } = grep ( !/^$creator$/, @Bcc ); } @{ $self->{'PseudoTo'} } = @PseudoTo; - + return (1); } diff --git a/rt/lib/RT/Action/NotifyAsComment.pm b/rt/lib/RT/Action/NotifyAsComment.pm index f7cc87543..210e4ab15 100755 --- a/rt/lib/RT/Action/NotifyAsComment.pm +++ b/rt/lib/RT/Action/NotifyAsComment.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK package RT::Action::NotifyAsComment; require RT::Action::Notify; diff --git a/rt/lib/RT/Action/ResolveMembers.pm b/rt/lib/RT/Action/ResolveMembers.pm index 00813181c..02ff3a58c 100644 --- a/rt/lib/RT/Action/ResolveMembers.pm +++ b/rt/lib/RT/Action/ResolveMembers.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # This Action will resolve all members of a resolved group ticket package RT::Action::ResolveMembers; diff --git a/rt/lib/RT/Action/SendEmail.pm b/rt/lib/RT/Action/SendEmail.pm index 431b97c75..dac8fc8e7 100755 --- a/rt/lib/RT/Action/SendEmail.pm +++ b/rt/lib/RT/Action/SendEmail.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# CONTRIBUTION SUBMISSION POLICY: +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# (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 }}} +# END LICENSE BLOCK # Portions Copyright 2000 Tobias Brox <tobix@cpan.org> package RT::Action::SendEmail; @@ -55,7 +33,6 @@ use vars qw/@ISA/; use MIME::Words qw(encode_mimeword); use RT::EmailParser; -use Mail::Address; =head1 NAME @@ -74,6 +51,13 @@ RT::Action::AutoReply is a good example subclass. Basically, you create another module RT::Action::YourAction which ISA RT::Action::SendEmail. +If you want to set the recipients of the mail to something other than +the addresses mentioned in the To, Cc, Bcc and headers in +the template, you should subclass RT::Action::SendEmail and override +either the SetRecipients method or the SetTo, SetCc, etc methods (see +the comments for the SetRecipients sub). + + =begin testing ok (require RT::Action::SendEmail); @@ -93,207 +77,228 @@ perl(1). # {{{ Scrip methods (_Init, Commit, Prepare, IsApplicable) +# {{{ sub _Init +# We use _Init from RT::Action +# }}} # {{{ sub Commit - +#Do what we need to do and send it out. sub Commit { my $self = shift; - return($self->SendMessage($self->TemplateObj->MIMEObj)); -} + my $MIMEObj = $self->TemplateObj->MIMEObj; + my $msgid = $MIMEObj->head->get('Message-Id'); + chomp $msgid; + $RT::Logger->info($msgid." #".$self->TicketObj->id."/".$self->TransactionObj->id." - Scrip ". $self->ScripObj->id ." ".$self->ScripObj->Description); + #send the email -# }}} + # Weed out any RT addresses. We really don't want to talk to ourselves! + @{$self->{'To'}} = RT::EmailParser::CullRTAddresses("", @{$self->{'To'}}); + @{$self->{'Cc'}} = RT::EmailParser::CullRTAddresses("", @{$self->{'Cc'}}); + @{$self->{'Bcc'}} = RT::EmailParser::CullRTAddresses("", @{$self->{'Bcc'}}); + # If there are no recipients, don't try to send the message. + # If the transaction has content and has the header RT-Squelch-Replies-To -# {{{ sub Prepare + if ( defined $self->TransactionObj->Attachments->First() ) { -sub Prepare { - my $self = shift; + my $squelch = $self->TransactionObj->Attachments->First->GetHeader( 'RT-Squelch-Replies-To'); - my ( $result, $message ) = $self->TemplateObj->Parse( - Argument => $self->Argument, - TicketObj => $self->TicketObj, - TransactionObj => $self->TransactionObj - ); - if ( !$result ) { - return (undef); + if ($squelch) { + my @blacklist = split ( /,/, $squelch ); + + # Cycle through the people we're sending to and pull out anyone on the + # system blacklist + + foreach my $person_to_yank (@blacklist) { + $person_to_yank =~ s/\s//g; + @{ $self->{'To'} } = + grep ( !/^$person_to_yank$/, @{ $self->{'To'} } ); + @{ $self->{'Cc'} } = + grep ( !/^$person_to_yank$/, @{ $self->{'Cc'} } ); + @{ $self->{'Bcc'} } = + grep ( !/^$person_to_yank$/, @{ $self->{'Bcc'} } ); + } + } } - my $MIMEObj = $self->TemplateObj->MIMEObj; - - # Header - $self->SetRTSpecialHeaders(); - - $self->RemoveInappropriateRecipients(); - # Go add all the Tos, Ccs and Bccs that we need to to the message to # make it happy, but only if we actually have values in those arrays. - # TODO: We should be pulling the recipients out of the template and shove them into To, Cc and Bcc - - $self->SetHeader( 'To', join ( ', ', @{ $self->{'To'} } ) ) - if ( ! $MIMEObj->head->get('To') && $self->{'To'} && @{ $self->{'To'} } ); - $self->SetHeader( 'Cc', join ( ', ', @{ $self->{'Cc'} } ) ) - if ( !$MIMEObj->head->get('Cc') && $self->{'Cc'} && @{ $self->{'Cc'} } ); - $self->SetHeader( 'Bcc', join ( ', ', @{ $self->{'Bcc'} } ) ) - if ( !$MIMEObj->head->get('Bcc') && $self->{'Bcc'} && @{ $self->{'Bcc'} } ); + $self->SetHeader( 'To', join ( ',', @{ $self->{'To'} } ) ) + if ( $self->{'To'} && @{ $self->{'To'} } ); + $self->SetHeader( 'Cc', join ( ',', @{ $self->{'Cc'} } ) ) + if ( $self->{'Cc'} && @{ $self->{'Cc'} } ); + $self->SetHeader( 'Bcc', join ( ',', @{ $self->{'Bcc'} } ) ) + if ( $self->{'Cc'} && @{ $self->{'Bcc'} } ); - # PseudoTo (fake to headers) shouldn't get matched for message recipients. - # If we don't have any 'To' header (but do have other recipients), drop in - # the pseudo-to header. - $self->SetHeader( 'To', join ( ', ', @{ $self->{'PseudoTo'} } ) ) - if ( $self->{'PseudoTo'} && ( @{ $self->{'PseudoTo'} } ) - and ( !$MIMEObj->head->get('To') ) ) and ( $MIMEObj->head->get('Cc') or $MIMEObj->head->get('Bcc')); - # We should never have to set the MIME-Version header - $self->SetHeader( 'MIME-Version', '1.0' ); + $self->SetHeader('MIME-Version', '1.0'); # try to convert message body from utf-8 to $RT::EmailOutputEncoding $self->SetHeader( 'Content-Type', 'text/plain; charset="utf-8"' ); - # fsck.com #5959: Since RT sends 8bit mail, we should say so. - $self->SetHeader( 'Content-Transfer-Encoding','8bit'); - - - RT::I18N::SetMIMEEntityToEncoding( $MIMEObj, $RT::EmailOutputEncoding, - 'mime_words_ok' ); + RT::I18N::SetMIMEEntityToEncoding( $MIMEObj, $RT::EmailOutputEncoding, 'mime_words_ok' ); $self->SetHeader( 'Content-Type', 'text/plain; charset="' . $RT::EmailOutputEncoding . '"' ); + # Build up a MIME::Entity that looks like the original message. - $self->AddAttachments() if ( $MIMEObj->head->get('RT-Attach-Message') ); - return $result; + my $do_attach = $self->TemplateObj->MIMEObj->head->get('RT-Attach-Message'); -} + if ($do_attach) { + $self->TemplateObj->MIMEObj->head->delete('RT-Attach-Message'); -# }}} + my $attachments = RT::Attachments->new($RT::SystemUser); + $attachments->Limit( FIELD => 'TransactionId', + VALUE => $self->TransactionObj->Id ); + $attachments->OrderBy('id'); -# }}} + my $transaction_content_obj = $self->TransactionObj->ContentObj; + # attach any of this transaction's attachments + while ( my $attach = $attachments->Next ) { + # Don't attach anything blank + next unless ( $attach->ContentLength ); -=head2 To + # We want to make sure that we don't include the attachment that's being sued as the "Content" of this message" + next + if ( $transaction_content_obj + && $transaction_content_obj->Id == $attach->Id + && $transaction_content_obj->ContentType =~ qr{text/plain}i + ); + $MIMEObj->make_multipart('mixed'); + $MIMEObj->attach( Type => $attach->ContentType, + Charset => $attach->OriginalEncoding, + Data => $attach->OriginalContent, + Filename => $self->MIMEEncodeString( $attach->Filename, $RT::EmailOutputEncoding ), + Encoding => '-SUGGEST'); + } -Returns an array of Mail::Address objects containing all the To: recipients for this notification + } -=cut -sub To { - my $self = shift; - return ($self->_AddressesFromHeader('To')); -} + my $retval = $self->SendMessage($MIMEObj); -=head2 Cc -Returns an array of Mail::Address objects containing all the Cc: recipients for this notification + return ($retval); +} -=cut +# }}} + +# {{{ sub Prepare -sub Cc { +sub Prepare { my $self = shift; - return ($self->_AddressesFromHeader('Cc')); -} -=head2 Bcc + # This actually populates the MIME::Entity fields in the Template Object -Returns an array of Mail::Address objects containing all the Bcc: recipients for this notification + unless ( $self->TemplateObj ) { + $RT::Logger->warning("No template object handed to $self\n"); + } -=cut + unless ( $self->TransactionObj ) { + $RT::Logger->warning("No transaction object handed to $self\n"); + } -sub Bcc { - my $self = shift; - return ($self->_AddressesFromHeader('Bcc')); + unless ( $self->TicketObj ) { + $RT::Logger->warning("No ticket object handed to $self\n"); -} + } -sub _AddressesFromHeader { - my $self = shift; - my $field = shift; - my $header = $self->TemplateObj->MIMEObj->head->get($field); - my @addresses = Mail::Address->parse($header); + my ( $result, $message ) = $self->TemplateObj->Parse( + Argument => $self->Argument, + TicketObj => $self->TicketObj, + TransactionObj => $self->TransactionObj + ); + if ($result) { + + # Header + $self->SetSubject(); + $self->SetSubjectToken(); + $self->SetRecipients(); + $self->SetReturnAddress(); + $self->SetRTSpecialHeaders(); + if ($RT::EmailOutputEncoding) { + + # l10n related header + $self->SetHeaderAsEncoding( 'Subject', $RT::EmailOutputEncoding ); + } + } + + return $result; - return (@addresses); } +# }}} -# {{{ SendMessage +# }}} +# {{{ SendMessage =head2 SendMessage MIMEObj sends the message using RT's preferred API. -TODO: Break this out to a separate module +TODO: Break this out to a seperate module =cut sub SendMessage { - my $self = shift; + my $self = shift; my $MIMEObj = shift; - my $msgid = $MIMEObj->head->get('Message-ID'); - chomp $msgid; + my $msgid = $MIMEObj->head->get('Message-Id'); - $self->ScripActionObj->{_Message_ID}++; - - $RT::Logger->info( $msgid . " #" - . $self->TicketObj->id . "/" - . $self->TransactionObj->id - . " - Scrip " - . $self->ScripObj->id . " " - . $self->ScripObj->Description ); #If we don't have any recipients to send to, don't send a message; - unless ( $MIMEObj->head->get('To') - || $MIMEObj->head->get('Cc') - || $MIMEObj->head->get('Bcc') ) - { - $RT::Logger->info( $msgid . " No recipients found. Not sending.\n" ); + unless ( $MIMEObj->head->get('To') + || $MIMEObj->head->get('Cc') + || $MIMEObj->head->get('Bcc') ) { + $RT::Logger->info($msgid. " No recipients found. Not sending.\n"); return (1); } + # PseudoTo (fake to headers) shouldn't get matched for message recipients. + # If we don't have any 'To' header, drop in the pseudo-to header. + $self->SetHeader( 'To', join ( ',', @{ $self->{'PseudoTo'} } ) ) + if ( $self->{'PseudoTo'} && ( @{ $self->{'PseudoTo'} } ) + and ( !$MIMEObj->head->get('To') ) ); if ( $RT::MailCommand eq 'sendmailpipe' ) { eval { - open( my $mail, "|$RT::SendmailPath $RT::SendmailArguments" ) || die $!; - $MIMEObj->print($mail); - close($mail); - }; - if ($@) { - $RT::Logger->crit( $msgid . "Could not send mail. -" . $@ ); + open( MAIL, "|$RT::SendmailPath $RT::SendmailArguments" ); + print MAIL $MIMEObj->as_string; + close(MAIL); + }; + if ($@) { + $RT::Logger->crit($msgid. "Could not send mail. -".$@ ); } } else { - my @mailer_args = ($RT::MailCommand); - - local $ENV{MAILADDRESS}; + my @mailer_args = ($RT::MailCommand); + local $ENV{MAILADDRESS}; if ( $RT::MailCommand eq 'sendmail' ) { - push @mailer_args, split(/\s+/, $RT::SendmailArguments); + push @mailer_args, $RT::SendmailArguments; } elsif ( $RT::MailCommand eq 'smtp' ) { - $ENV{MAILADDRESS} = $RT::SMTPFrom || $MIMEObj->head->get('From'); - push @mailer_args, ( Server => $RT::SMTPServer ); - push @mailer_args, ( Debug => $RT::SMTPDebug ); - } - else { - push @mailer_args, $RT::MailParams; + $ENV{MAILADDRESS} = $RT::SMTPFrom || $MIMEObj->head->get('From'); + push @mailer_args, (Server => $RT::SMTPServer); + push @mailer_args, (Debug => $RT::SMTPDebug); } + else { + push @mailer_args, $RT::MailParams; + } - unless ( $MIMEObj->send(@mailer_args) ) { - $RT::Logger->crit( $msgid . "Could not send mail." ); + unless ( $MIMEObj->send( @mailer_args ) ) { + $RT::Logger->crit($msgid. "Could not send mail." ); return (0); } } - my $success = - ( $msgid - . " sent To: " - . $MIMEObj->head->get('To') . " Cc: " - . $MIMEObj->head->get('Cc') . " Bcc: " - . $MIMEObj->head->get('Bcc') ); - $success =~ s/\n//gi; - - $self->RecordOutgoingMailTransaction($MIMEObj) if ($RT::RecordOutgoingEmail); + my $success = ($msgid. " sent To: ".$MIMEObj->head->get('To') . " Cc: ".$MIMEObj->head->get('Cc') . " Bcc: ".$MIMEObj->head->get('Bcc')); + $success =~ s/\n//gi; $RT::Logger->info($success); return (1); @@ -301,121 +306,7 @@ sub SendMessage { # }}} -# {{{ AddAttachments - -=head2 AddAttachments - -Takes any attachments to this transaction and attaches them to the message -we're building. - -=cut - - -sub AddAttachments { - my $self = shift; - - my $MIMEObj = $self->TemplateObj->MIMEObj; - - $MIMEObj->head->delete('RT-Attach-Message'); - - my $attachments = RT::Attachments->new($RT::SystemUser); - $attachments->Limit( - FIELD => 'TransactionId', - VALUE => $self->TransactionObj->Id - ); - $attachments->OrderBy( FIELD => 'id'); - - my $transaction_content_obj = $self->TransactionObj->ContentObj; - - # attach any of this transaction's attachments - while ( my $attach = $attachments->Next ) { - - # Don't attach anything blank - next unless ( $attach->ContentLength ); - -# We want to make sure that we don't include the attachment that's being sued as the "Content" of this message" - next - if ( $transaction_content_obj - && $transaction_content_obj->Id == $attach->Id - && $transaction_content_obj->ContentType =~ qr{text/plain}i ); - $MIMEObj->make_multipart('mixed'); - $MIMEObj->attach( - Type => $attach->ContentType, - Charset => $attach->OriginalEncoding, - Data => $attach->OriginalContent, - Filename => $self->MIMEEncodeString( $attach->Filename, - $RT::EmailOutputEncoding ), - 'RT-Attachment:' => $self->TicketObj->Id."/".$self->TransactionObj->Id."/".$attach->id, - Encoding => '-SUGGEST' - ); - } - -} - -# }}} - -# {{{ RecordOutgoingMailTransaction - -=head2 RecordOutgoingMailTransaction MIMEObj - -Record a transaction in RT with this outgoing message for future record-keeping purposes - -=cut - - - -sub RecordOutgoingMailTransaction { - my $self = shift; - my $MIMEObj = shift; - - - my @parts = $MIMEObj->parts; - my @attachments; - my @keep; - foreach my $part (@parts) { - my $attach = $part->head->get('RT-Attachment'); - if ($attach) { - $RT::Logger->debug("We found an attachment. we want to not record it."); - push @attachments, $attach; - } else { - $RT::Logger->debug("We found a part. we want to record it."); - push @keep, $part; - } - } - $MIMEObj->parts(\@keep); - foreach my $attachment (@attachments) { - $MIMEObj->head->add('RT-Attachment', $attachment); - } - - RT::I18N::SetMIMEEntityToEncoding( $MIMEObj, 'utf-8', 'mime_words_ok' ); - - my $transaction = RT::Transaction->new($self->TransactionObj->CurrentUser); - - # XXX: TODO -> Record attachments as references to things in the attachments table, maybe. - - my $type; - if ($self->TransactionObj->Type eq 'Comment') { - $type = 'CommentEmailRecord'; - } else { - $type = 'EmailRecord'; - } - - my $msgid = $MIMEObj->head->get('Message-ID'); - chomp $msgid; - - my ( $id, $msg ) = $transaction->Create( - Ticket => $self->TicketObj->Id, - Type => $type, - Data => $msgid, - MIMEObj => $MIMEObj, - ActivateScrips => 0 - ); - - -} - -# }}} -# +# {{{ Deal with message headers (Set* subs, designed for easy overriding) # {{{ sub SetRTSpecialHeaders @@ -429,155 +320,84 @@ that don't matter much to anybody else. sub SetRTSpecialHeaders { my $self = shift; - $self->SetSubject(); - $self->SetSubjectToken(); - $self->SetHeaderAsEncoding( 'Subject', $RT::EmailOutputEncoding ) - if ($RT::EmailOutputEncoding); - $self->SetReturnAddress(); - $self->SetReferencesHeaders(); - - unless ($self->TemplateObj->MIMEObj->head->get('Message-ID')) { - # Get Message-ID for this txn - my $msgid = ""; - $msgid = $self->TransactionObj->Message->First->GetHeader("RT-Message-ID") - || $self->TransactionObj->Message->First->GetHeader("Message-ID") - if $self->TransactionObj->Message && $self->TransactionObj->Message->First; - - # If there is one, and we can parse it, then base our Message-ID on it - if ($msgid - and $msgid =~ s/<(rt-.*?-\d+-\d+)\.(\d+)-\d+-\d+\@\Q$RT::Organization\E>$/ - "<$1." . $self->TicketObj->id - . "-" . $self->ScripObj->id - . "-" . $self->ScripActionObj->{_Message_ID} - . "@" . $RT::Organization . ">"/eg - and $2 == $self->TicketObj->id) { - $self->SetHeader( "Message-ID" => $msgid ); - } else { - $self->SetHeader( 'Message-ID', - "<rt-" - . $RT::VERSION . "-" - . $$ . "-" - . CORE::time() . "-" - . int(rand(2000)) . '.' - . $self->TicketObj->id . "-" - . $self->ScripObj->id . "-" # Scrip - . $self->ScripActionObj->{_Message_ID} . "@" # Email sent - . $RT::Organization - . ">" ); - } - } + $self->SetReferences(); + + $self->SetMessageID(); - $self->SetHeader( 'Precedence', "bulk" ) - unless ( $self->TemplateObj->MIMEObj->head->get("Precedence") ); + $self->SetPrecedence(); $self->SetHeader( 'X-RT-Loop-Prevention', $RT::rtname ); $self->SetHeader( 'RT-Ticket', - $RT::rtname . " #" . $self->TicketObj->id() ); + $RT::rtname . " #" . $self->TicketObj->id() ); $self->SetHeader( 'Managed-by', - "RT $RT::VERSION (http://www.bestpractical.com/rt/)" ); + "RT $RT::VERSION (http://www.bestpractical.com/rt/)" ); $self->SetHeader( 'RT-Originator', - $self->TransactionObj->CreatorObj->EmailAddress ); + $self->TransactionObj->CreatorObj->EmailAddress ); + return (); } -# }}} - +# {{{ sub SetReferences -# }}} - -# {{{ RemoveInappropriateRecipients - -=head2 RemoveInappropriateRecipients - -Remove addresses that are RT addresses or that are on this transaction's blacklist +=head2 SetReferences + + # This routine will set the References: and In-Reply-To headers, +# autopopulating it with all the correspondence on this ticket so +# far. This should make RT responses threadable. =cut -sub RemoveInappropriateRecipients { +sub SetReferences { my $self = shift; - my @blacklist; - - my @types = qw/To Cc Bcc/; - - # Weed out any RT addresses. We really don't want to talk to ourselves! - foreach my $type (@types) { - @{ $self->{$type} } = - RT::EmailParser::CullRTAddresses( "", @{ $self->{$type} } ); - } - - # If there are no recipients, don't try to send the message. - # If the transaction has content and has the header RT-Squelch-Replies-To - - if ( $self->TransactionObj->Attachments->First() ) { - if ( - $self->TransactionObj->Attachments->First->GetHeader( - 'RT-DetectedAutoGenerated') - ) - { - - # What do we want to do with this? It's probably (?) a bounce - # caused by one of the watcher addresses being broken. - # Default ("true") is to redistribute, for historical reasons. - - if ( !$RT::RedistributeAutoGeneratedMessages ) { - - # Don't send to any watchers. - @{ $self->{'To'} } = (); - @{ $self->{'Cc'} } = (); - @{ $self->{'Bcc'} } = (); - - } - elsif ( $RT::RedistributeAutoGeneratedMessages eq 'privileged' ) { - - # Only send to "privileged" watchers. - # + # TODO: this one is broken. What is this email really a reply to? + # If it's a reply to an incoming message, we'll need to use the + # actual message-id from the appropriate Attachment object. For + # incoming mails, we would like to preserve the In-Reply-To and/or + # References. - foreach my $type (@types) { + $self->SetHeader( 'In-Reply-To', + "<rt-" . $self->TicketObj->id() . "\@" . $RT::rtname . ">" ); - foreach my $addr ( @{ $self->{$type} } ) { - my $user = RT::User->new($RT::SystemUser); - $user->LoadByEmail($addr); - @{ $self->{$type} } = - grep ( !/^\Q$addr\E$/, @{ $self->{$type} } ) - if ( !$user->Privileged ); - - } - } + # TODO We should always add References headers for all message-ids + # of previous messages related to this ticket. +} - } +# }}} - } +# {{{ sub SetMessageID - my $squelch = - $self->TransactionObj->Attachments->First->GetHeader( - 'RT-Squelch-Replies-To'); +=head2 SetMessageID - if ($squelch) { - @blacklist = split( /,/, $squelch ); - } - } +Without this one, threading won't work very nice in email agents. +Anyway, I'm not really sure it's that healthy if we need to send +several separate/different emails about the same transaction. - # Let's grab the SquelchMailTo attribue and push those entries into the @blacklist - my @non_recipients = $self->TicketObj->SquelchMailTo; - foreach my $attribute (@non_recipients) { - push @blacklist, $attribute->Content; - } +=cut - # Cycle through the people we're sending to and pull out anyone on the - # system blacklist +sub SetMessageID { + my $self = shift; - foreach my $person_to_yank (@blacklist) { - $person_to_yank =~ s/\s//g; - foreach my $type (@types) { - @{ $self->{$type} } = - grep ( !/^\Q$person_to_yank\E$/, @{ $self->{$type} } ); - } - } + # TODO this one might be sort of broken. If we have several scrips +++ + # sending several emails to several different persons, we need to + # pull out different message-ids. I'd suggest message ids like + # "rt-ticket#-transaction#-scrip#-receipient#" + + $self->SetHeader( 'Message-ID', + "<rt-" + . $RT::VERSION ."-" + . $self->TicketObj->id() . "-" + . $self->TransactionObj->id() . "." + . rand(20) . "\@" + . $RT::Organization . ">" ) + unless $self->TemplateObj->MIMEObj->head->get('Message-ID'); } # }}} + +# }}} + # {{{ sub SetReturnAddress =head2 SetReturnAddress is_comment => BOOLEAN @@ -589,10 +409,8 @@ Calculate and set From and Reply-To headers based on the is_comment flag. sub SetReturnAddress { my $self = shift; - my %args = ( - is_comment => 0, - @_ - ); + my %args = ( is_comment => 0, + @_ ); # From and Reply-To # $args{is_comment} should be set if the comment address is to be used. @@ -608,26 +426,21 @@ sub SetReturnAddress { } unless ( $self->TemplateObj->MIMEObj->head->get('From') ) { - if ($RT::UseFriendlyFromLine) { - my $friendly_name = $self->TransactionObj->CreatorObj->RealName; - if ( $friendly_name =~ /^"(.*)"$/ ) { # a quoted string - $friendly_name = $1; - } - - $friendly_name =~ s/"/\\"/g; - $self->SetHeader( - 'From', - sprintf( - $RT::FriendlyFromLineFormat, - $self->MIMEEncodeString( $friendly_name, - $RT::EmailOutputEncoding ), - $replyto - ), - ); - } - else { - $self->SetHeader( 'From', $replyto ); - } + if ($RT::UseFriendlyFromLine) { + my $friendly_name = $self->TransactionObj->CreatorObj->RealName; + if ( $friendly_name =~ /^"(.*)"$/ ) { # a quoted string + $friendly_name = $1; + } + + $friendly_name =~ s/"/\\"/g; + $self->SetHeader( 'From', + sprintf($RT::FriendlyFromLineFormat, + $self->MIMEEncodeString( $friendly_name, $RT::EmailOutputEncoding ), $replyto), + ); + } + else { + $self->SetHeader( 'From', $replyto ); + } } unless ( $self->TemplateObj->MIMEObj->head->get('Reply-To') ) { @@ -660,6 +473,82 @@ sub SetHeader { # }}} +# {{{ sub SetRecipients + +=head2 SetRecipients + +Dummy method to be overriden by subclasses which want to set the recipients. + +=cut + +sub SetRecipients { + my $self = shift; + return (); +} + +# }}} + +# {{{ sub SetTo + +=head2 SetTo + +Takes a string that is the addresses you want to send mail to + +=cut + +sub SetTo { + my $self = shift; + my $addresses = shift; + return $self->SetHeader( 'To', $addresses ); +} + +# }}} + +# {{{ sub SetCc + +=head2 SetCc + +Takes a string that is the addresses you want to Cc + +=cut + +sub SetCc { + my $self = shift; + my $addresses = shift; + + return $self->SetHeader( 'Cc', $addresses ); +} + +# }}} + +# {{{ sub SetBcc + +=head2 SetBcc + +Takes a string that is the addresses you want to Bcc + +=cut + +sub SetBcc { + my $self = shift; + my $addresses = shift; + + return $self->SetHeader( 'Bcc', $addresses ); +} + +# }}} + +# {{{ sub SetPrecedence + +sub SetPrecedence { + my $self = shift; + + unless ( $self->TemplateObj->MIMEObj->head->get("Precedence") ) { + $self->SetHeader( 'Precedence', "bulk" ); + } +} + +# }}} # {{{ sub SetSubject @@ -675,33 +564,36 @@ sub SetSubject { my $self = shift; my $subject; - my $message = $self->TransactionObj->Attachments; - if ( $self->TemplateObj->MIMEObj->head->get('Subject') ) { - return (); - } - if ( $self->{'Subject'} ) { - $subject = $self->{'Subject'}; - } - elsif ( ( $message->First() ) && ( $message->First->Headers ) ) { - my $header = $message->First->Headers(); - $header =~ s/\n\s+/ /g; - if ( $header =~ /^Subject: (.*?)$/m ) { - $subject = $1; + unless ( $self->TemplateObj->MIMEObj->head->get('Subject') ) { + my $message = $self->TransactionObj->Attachments; + my $ticket = $self->TicketObj->Id; + + if ( $self->{'Subject'} ) { + $subject = $self->{'Subject'}; + } + elsif ( ( $message->First() ) + && ( $message->First->Headers ) ) { + my $header = $message->First->Headers(); + $header =~ s/\n\s+/ /g; + if ( $header =~ /^Subject: (.*?)$/m ) { + $subject = $1; + } + else { + $subject = $self->TicketObj->Subject(); + } + } else { $subject = $self->TicketObj->Subject(); } - } - else { - $subject = $self->TicketObj->Subject(); - } - - $subject =~ s/(\r\n|\n|\s)/ /gi; + $subject =~ s/(\r\n|\n|\s)/ /gi; - chomp $subject; - $self->SetHeader( 'Subject', $subject ); + chomp $subject; + $self->SetHeader( 'Subject', $subject ); + } + return ($subject); } # }}} @@ -727,94 +619,9 @@ sub SetSubjectToken { # }}} -=head2 SetReferencesHeaders - -Set References and In-Reply-To headers for this message. - -=cut - -sub SetReferencesHeaders { - - my $self = shift; - my ( @in_reply_to, @references, @msgid ); - - my $attachments = $self->TransactionObj->Message; - - if ( my $top = $attachments->First() ) { - @in_reply_to = split(/\s+/m, $top->GetHeader('In-Reply-To') || ''); - @references = split(/\s+/m, $top->GetHeader('References') || '' ); - @msgid = split(/\s+/m, $top->GetHeader('Message-ID') || ''); - } - else { - return (undef); - } - - # There are two main cases -- this transaction was created with - # the RT Web UI, and hence we want to *not* append its Message-ID - # to the References and In-Reply-To. OR it came from an outside - # source, and we should treat it as per the RFC - if ( "@msgid" =~ /<(rt-.*?-\d+-\d+)\.(\d+-0-0)\@$RT::Organization>/) { - - # Make all references which are internal be to version which we - # have sent out - for (@references, @in_reply_to) { - s/<(rt-.*?-\d+-\d+)\.(\d+-0-0)\@$RT::Organization>$/ - "<$1." . $self->TicketObj->id . - "-" . $self->ScripObj->id . - "-" . $self->ScripActionObj->{_Message_ID} . - "@" . $RT::Organization . ">"/eg - } - - # In reply to whatever the internal message was in reply to - $self->SetHeader( 'In-Reply-To', join( " ", ( @in_reply_to ))); - - # Default the references to whatever we're in reply to - @references = @in_reply_to unless @references; - - # References are unchanged from internal - } else { - # In reply to that message - $self->SetHeader( 'In-Reply-To', join( " ", ( @msgid ))); - - # Default the references to whatever we're in reply to - @references = @in_reply_to unless @references; - - # Push that message onto the end of the references - push @references, @msgid; - } - - # Push pseudo-ref to the front - my $pseudo_ref = $self->PseudoReference; - @references = ($pseudo_ref, grep { $_ ne $pseudo_ref } @references); - - # If there are more than 10 references headers, remove all but the - # first four and the last six (Gotta keep this from growing - # forever) - splice(@references, 4, -6) if ($#references >= 10); - - # Add on the references - $self->SetHeader( 'References', join( " ", @references) ); - $self->TemplateObj->MIMEObj->head->fold_length( 'References', 80 ); - -} - # }}} -=head2 PseudoReference - -Returns a fake Message-ID: header for the ticket to allow a base level of threading - -=cut - -sub PseudoReference { - - my $self = shift; - my $pseudo_ref = '<RT-Ticket-'.$self->TicketObj->id .'@'.$RT::Organization .'>'; - return $pseudo_ref; -} - - -# {{{ SetHeadingAsEncoding +# {{{ =head2 SetHeaderAsEncoding($field_name, $charset_encoding) @@ -845,7 +652,7 @@ sub SetHeaderAsEncoding { } # }}} -# {{{ MIMEEncodeString +# {{{ MIMENcodeString =head2 MIMEEncodeString STRING ENCODING @@ -856,41 +663,15 @@ Takes a string and a possible encoding and returns the string wrapped in MIME go sub MIMEEncodeString { my $self = shift; my $value = shift; - # using RFC2047 notation, sec 2. - # encoded-word = "=?" charset "?" encoding "?" encoded-text "?=" - my $charset = shift; - my $encoding = 'B'; - # An 'encoded-word' may not be more than 75 characters long - # - # MIME encoding increases 4/3*(number of bytes), and always in multiples - # of 4. Thus we have to find the best available value of bytes available - # for each chunk. - # - # First we get the integer max which max*4/3 would fit on space. - # Then we find the greater multiple of 3 lower or equal than $max. - my $max = int(((75-length('=?'.$charset.'?'.$encoding.'?'.'?='))*3)/4); - $max = int($max/3)*3; + my $enc = shift; chomp $value; return ($value) unless $value =~ /[^\x20-\x7e]/; $value =~ s/\s*$//; Encode::_utf8_off($value); - my $res = Encode::from_to( $value, "utf-8", $charset ); - - if ($max > 0) { - # copy value and split in chuncks - my $str=$value; - my @chunks = unpack("a$max" x int(length($str)/$max - + ((length($str) % $max) ? 1:0)), $str); - # encode an join chuncks - $value = join " ", - map encode_mimeword( $_, $encoding, $charset ), @chunks ; - return($value); - } else { - # gives an error... - $RT::Logger->crit("Can't encode! Charset or encoding too big.\n"); - } + my $res = Encode::from_to( $value, "utf-8", $enc ); + $value = encode_mimeword( $value, 'B', $enc ); } # }}} diff --git a/rt/lib/RT/Attachment.pm b/rt/lib/RT/Attachment.pm index 2a09b1240..2ed520162 100755 --- a/rt/lib/RT/Attachment.pm +++ b/rt/lib/RT/Attachment.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -83,7 +61,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -132,7 +110,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -141,14 +119,14 @@ Returns the current value of id. =cut -=head2 TransactionId +=item TransactionId Returns the current value of TransactionId. (In the database, TransactionId is stored as int(11).) -=head2 SetTransactionId VALUE +=item SetTransactionId VALUE Set TransactionId to VALUE. @@ -159,14 +137,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Parent +=item Parent Returns the current value of Parent. (In the database, Parent is stored as int(11).) -=head2 SetParent VALUE +=item SetParent VALUE Set Parent to VALUE. @@ -177,14 +155,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 MessageId +=item MessageId Returns the current value of MessageId. (In the database, MessageId is stored as varchar(160).) -=head2 SetMessageId VALUE +=item SetMessageId VALUE Set MessageId to VALUE. @@ -195,14 +173,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Subject +=item Subject Returns the current value of Subject. (In the database, Subject is stored as varchar(255).) -=head2 SetSubject VALUE +=item SetSubject VALUE Set Subject to VALUE. @@ -213,14 +191,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Filename +=item Filename Returns the current value of Filename. (In the database, Filename is stored as varchar(255).) -=head2 SetFilename VALUE +=item SetFilename VALUE Set Filename to VALUE. @@ -231,14 +209,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ContentType +=item ContentType Returns the current value of ContentType. (In the database, ContentType is stored as varchar(80).) -=head2 SetContentType VALUE +=item SetContentType VALUE Set ContentType to VALUE. @@ -249,14 +227,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ContentEncoding +=item ContentEncoding Returns the current value of ContentEncoding. (In the database, ContentEncoding is stored as varchar(80).) -=head2 SetContentEncoding VALUE +=item SetContentEncoding VALUE Set ContentEncoding to VALUE. @@ -267,14 +245,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Content +=item Content Returns the current value of Content. (In the database, Content is stored as longtext.) -=head2 SetContent VALUE +=item SetContent VALUE Set Content to VALUE. @@ -285,14 +263,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Headers +=item Headers Returns the current value of Headers. (In the database, Headers is stored as longtext.) -=head2 SetHeaders VALUE +=item SetHeaders VALUE Set Headers to VALUE. @@ -303,7 +281,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -312,7 +290,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -322,33 +300,33 @@ Returns the current value of Created. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, TransactionId => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Parent => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, MessageId => - {read => 1, write => 1, sql_type => 12, length => 160, is_blob => 0, is_numeric => 0, type => 'varchar(160)', default => ''}, + {read => 1, write => 1, type => 'varchar(160)', default => ''}, Subject => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, Filename => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, ContentType => - {read => 1, write => 1, sql_type => 12, length => 80, is_blob => 0, is_numeric => 0, type => 'varchar(80)', default => ''}, + {read => 1, write => 1, type => 'varchar(80)', default => ''}, ContentEncoding => - {read => 1, write => 1, sql_type => 12, length => 80, is_blob => 0, is_numeric => 0, type => 'varchar(80)', default => ''}, + {read => 1, write => 1, type => 'varchar(80)', default => ''}, Content => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'longtext', default => ''}, + {read => 1, write => 1, type => 'longtext', default => ''}, Headers => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'longtext', default => ''}, + {read => 1, write => 1, type => 'longtext', default => ''}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, } }; @@ -380,7 +358,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Attachments.pm b/rt/lib/RT/Attachments.pm index aedd7ad2b..177cdd094 100755 --- a/rt/lib/RT/Attachments.pm +++ b/rt/lib/RT/Attachments.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::Attachment item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Condition/AnyTransaction.pm b/rt/lib/RT/Condition/AnyTransaction.pm index 6685e2779..4519fcf5a 100644 --- a/rt/lib/RT/Condition/AnyTransaction.pm +++ b/rt/lib/RT/Condition/AnyTransaction.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK package RT::Condition::AnyTransaction; diff --git a/rt/lib/RT/Condition/Generic.pm b/rt/lib/RT/Condition/Generic.pm index cdde9ee5b..bd269315e 100755 --- a/rt/lib/RT/Condition/Generic.pm +++ b/rt/lib/RT/Condition/Generic.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,30 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} - +# END LICENSE BLOCK =head1 NAME RT::Condition::Generic - ; @@ -80,8 +57,10 @@ ok (require RT::Condition::Generic); package RT::Condition::Generic; +use RT::Base; use strict; -use base qw/RT::Base/; +use vars qw/@ISA/; +@ISA = qw(RT::Base); # {{{ sub new sub new { @@ -103,7 +82,6 @@ sub _Init { TemplateObj => undef, Argument => undef, ApplicableTransTypes => undef, - CurrentUser => undef, @_ ); $self->{'Argument'} = $args{'Argument'}; @@ -111,7 +89,6 @@ sub _Init { $self->{'TicketObj'} = $args{'TicketObj'}; $self->{'TransactionObj'} = $args{'TransactionObj'}; $self->{'ApplicableTransTypes'} = $args{'ApplicableTransTypes'}; - $self->CurrentUser($args{'CurrentUser'}); } # }}} diff --git a/rt/lib/RT/Condition/StatusChange.pm b/rt/lib/RT/Condition/StatusChange.pm index 902bf2aab..8afabcda0 100644 --- a/rt/lib/RT/Condition/StatusChange.pm +++ b/rt/lib/RT/Condition/StatusChange.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK diff --git a/rt/lib/RT/CurrentUser.pm b/rt/lib/RT/CurrentUser.pm index 8e28801c1..4ca2f9891 100755 --- a/rt/lib/RT/CurrentUser.pm +++ b/rt/lib/RT/CurrentUser.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,30 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# CONTRIBUTION SUBMISSION POLICY: +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# (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 }}} - +# END LICENSE BLOCK =head1 NAME RT::CurrentUser - an RT object representing the current user @@ -74,7 +51,8 @@ use RT::Record; use RT::I18N; use strict; -use base qw/RT::Record/; +use vars qw/@ISA/; +@ISA= qw(RT::Record); # {{{ sub _Init @@ -82,30 +60,17 @@ use base qw/RT::Record/; # to be a CurrentUser object. but that's hard to do when we're trying to load # the CurrentUser object -sub _Init { - my $self = shift; - my $User = shift; - - $self->{'table'} = "Users"; - - if ( defined($User) ) { - - if ( UNIVERSAL::isa( $User, 'RT::User' ) - || UNIVERSAL::isa( $User, 'RT::CurrentUser' ) ) - { - $self->Load( $User->id ); +sub _Init { + my $self = shift; + my $Name = shift; - } - elsif ( ref($User) ) { - $RT::Logger->crit( - "RT::CurrentUser->new() called with a bogus argument: $User"); - } - else { - $self->Load($User); - } - } + $self->{'table'} = "Users"; - $self->_BuildTableAttributes(); + if (defined($Name)) { + $self->Load($Name); + } + + $self->CurrentUser($self); } # }}} @@ -139,13 +104,15 @@ sub Delete { sub UserObj { my $self = shift; + unless ($self->{'UserObj'}) { use RT::User; - my $user = RT::User->new($self); - - unless ($user->Load($self->Id)) { + $self->{'UserObj'} = RT::User->new($self); + unless ($self->{'UserObj'}->Load($self->Id)) { $RT::Logger->err($self->loc("Couldn't load [_1] from the users database.\n", $self->Id)); } - return ($user); + + } + return ($self->{'UserObj'}); } # }}} @@ -186,18 +153,18 @@ sub PrincipalId { # {{{ sub _Accessible - - - sub _CoreAccessible { - { - Name => { 'read' => 1 }, - Gecos => { 'read' => 1 }, - RealName => { 'read' => 1 }, - Lang => { 'read' => 1 }, - Password => { 'read' => 0, 'write' => 0 }, - EmailAddress => { 'read' => 1, 'write' => 0 } - }; - +sub _Accessible { + my $self = shift; + my %Cols = ( + Name => 'read', + Gecos => 'read', + RealName => 'read', + Password => 'neither', + EmailAddress => 'read', + Privileged => 'read', + IsAdministrator => 'read' + ); + return($self->SUPER::_Accessible(@_, %Cols)); } # }}} @@ -245,7 +212,6 @@ sub LoadByGecos { Loads a User into this CurrentUser object. Takes a Name. - =cut sub LoadByName { @@ -275,11 +241,6 @@ sub Load { if ($identifier !~ /\D/) { $self->SUPER::LoadById($identifier); } - - elsif (UNIVERSAL::isa($identifier,"RT::User")) { - # DWIM if they pass a user in - $self->SUPER::LoadById($identifier->Id); - } else { # This is a bit dangerous, we might get false authen if somebody # uses ambigous userids or real names: @@ -352,12 +313,12 @@ specification. but currently doesn't =begin testing ok (my $cu = RT::CurrentUser->new('root')); -ok (my $lh = $cu->LanguageHandle('en-us')); +ok (my $lh = $cu->LanguageHandle); ok ($lh != undef); ok ($lh->isa('Locale::Maketext')); -is ($cu->loc('TEST_STRING'), "Concrete Mixer", "Localized TEST_STRING into English"); +ok ($cu->loc('TEST_STRING') eq "Concrete Mixer", "Localized TEST_STRING into English"); ok ($lh = $cu->LanguageHandle('fr')); -is ($cu->loc('Before'), "Avant", "Localized TEST_STRING into Frenc"); +ok ($cu->loc('Before') eq "Avant", "Localized TEST_STRING into Frenc"); =end testing @@ -365,24 +326,16 @@ is ($cu->loc('Before'), "Avant", "Localized TEST_STRING into Frenc"); sub LanguageHandle { my $self = shift; - if ( ( !defined $self->{'LangHandle'} ) - || ( !UNIVERSAL::can( $self->{'LangHandle'}, 'maketext' ) ) - || (@_) ) { - if ( !$RT::SystemUser or ($self->id || 0) == $RT::SystemUser->id() ) { - @_ = qw(en-US); - } - - elsif ( $self->Lang ) { - push @_, $self->Lang; - } + if ((!defined $self->{'LangHandle'}) || + (!UNIVERSAL::can($self->{'LangHandle'}, 'maketext')) || + (@_)) { $self->{'LangHandle'} = RT::I18N->get_handle(@_); } - # Fall back to english. - unless ( $self->{'LangHandle'} ) { + unless ($self->{'LangHandle'}) { die "We couldn't get a dictionary. Nye mogu naidti slovar. No puedo encontrar dictionario."; } - return ( $self->{'LangHandle'} ); + return ($self->{'LangHandle'}); } sub loc { @@ -402,7 +355,7 @@ sub loc { sub loc_fuzzy { my $self = shift; - return '' if (!$_[0] || $_[0] eq ''); + return '' if $_[0] eq ''; # XXX: work around perl's deficiency when matching utf8 data return $_[0] if Encode::is_utf8($_[0]); @@ -412,62 +365,6 @@ sub loc_fuzzy { } # }}} - -=head2 CurrentUser - -Return the current currentuser object - -=cut - -sub CurrentUser { - my $self = shift; - return($self); - -} - -=head2 Authenticate - -Takes $password, $created and $nonce, and returns a boolean value -representing whether the authentication succeeded. - -If both $nonce and $created are specified, validate $password against: - - encode_base64(sha1( - $nonce . - $created . - sha1_hex( "$username:$realm:$server_pass" ) - )) - -where $server_pass is the md5_hex(password) digest stored in the -database, $created is in ISO time format, and $nonce is a random -string no longer than 32 bytes. - -=cut - -sub Authenticate { - my ($self, $password, $created, $nonce, $realm) = @_; - - require Digest::MD5; - require Digest::SHA1; - require MIME::Base64; - - my $username = $self->UserObj->Name or return; - my $server_pass = $self->UserObj->__Value('Password') or return; - my $auth_digest = MIME::Base64::encode_base64(Digest::SHA1::sha1( - $nonce . - $created . - Digest::MD5::md5_hex("$username:$realm:$server_pass") - )); - - chomp($password); - chomp($auth_digest); - - return ($password eq $auth_digest); -} - -# }}} - - eval "require RT::CurrentUser_Vendor"; die $@ if ($@ && $@ !~ qr{^Can't locate RT/CurrentUser_Vendor.pm}); eval "require RT::CurrentUser_Local"; diff --git a/rt/lib/RT/Date.pm b/rt/lib/RT/Date.pm index 620acc759..355370ada 100644 --- a/rt/lib/RT/Date.pm +++ b/rt/lib/RT/Date.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,30 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} - +# END LICENSE BLOCK =head1 NAME RT::Date - a simple Object Oriented date. @@ -353,8 +330,7 @@ sub DurationAsString { $s = int( $duration / $YEAR ); $time_unit = $self->loc("years"); } - - if ($negative) { + if (0) { # For now, never display the "AGO" # $negative) { return $self->loc( "[_1] [_2] ago", $s, $time_unit ); } else { @@ -399,7 +375,6 @@ sub AsString { # }}} # {{{ GetWeekday - =head2 GetWeekday DAY Takes an integer day of week and returns a localized string for that day of week @@ -422,7 +397,6 @@ sub GetWeekday { # }}} # {{{ GetMonth - =head2 GetMonth DAY Takes an integer month and returns a localized string for that month @@ -555,27 +529,8 @@ sub ISO { # }}} -# {{{ sub W3CDTF - -=head2 W3CDTF - -Takes nothing - -Returns the object's date in W3C DTF format - -=cut - -sub W3CDTF { - my $self = shift; - my $date = $self->ISO . 'Z'; - $date =~ s/ /T/; - return $date; -}; - -# }}} # {{{ sub LocalTimezone - =head2 LocalTimezone Returns the current timezone. For now, draws off a system timezone, RT::Timezone. Eventually, this may diff --git a/rt/lib/RT/Group.pm b/rt/lib/RT/Group.pm index 04c307652..4dcef3f07 100755 --- a/rt/lib/RT/Group.pm +++ b/rt/lib/RT/Group.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -83,7 +61,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -91,7 +69,7 @@ Create takes a hash of values and creates a row in the database: varchar(255) 'Description'. varchar(64) 'Domain'. varchar(64) 'Type'. - int(11) 'Instance'. + varchar(64) 'Instance'. =cut @@ -120,7 +98,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -129,14 +107,14 @@ Returns the current value of id. =cut -=head2 Name +=item Name Returns the current value of Name. (In the database, Name is stored as varchar(200).) -=head2 SetName VALUE +=item SetName VALUE Set Name to VALUE. @@ -147,14 +125,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Description +=item Description Returns the current value of Description. (In the database, Description is stored as varchar(255).) -=head2 SetDescription VALUE +=item SetDescription VALUE Set Description to VALUE. @@ -165,14 +143,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Domain +=item Domain Returns the current value of Domain. (In the database, Domain is stored as varchar(64).) -=head2 SetDomain VALUE +=item SetDomain VALUE Set Domain to VALUE. @@ -183,14 +161,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Type +=item Type Returns the current value of Type. (In the database, Type is stored as varchar(64).) -=head2 SetType VALUE +=item SetType VALUE Set Type to VALUE. @@ -201,40 +179,40 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Instance +=item Instance Returns the current value of Instance. -(In the database, Instance is stored as int(11).) +(In the database, Instance is stored as varchar(64).) -=head2 SetInstance VALUE +=item SetInstance VALUE Set Instance to VALUE. Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, Instance will be stored as a int(11).) +(In the database, Instance will be stored as a varchar(64).) =cut -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, Name => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, type => 'varchar(200)', default => ''}, Description => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, Domain => - {read => 1, write => 1, sql_type => 12, length => 64, is_blob => 0, is_numeric => 0, type => 'varchar(64)', default => ''}, + {read => 1, write => 1, type => 'varchar(64)', default => ''}, Type => - {read => 1, write => 1, sql_type => 12, length => 64, is_blob => 0, is_numeric => 0, type => 'varchar(64)', default => ''}, + {read => 1, write => 1, type => 'varchar(64)', default => ''}, Instance => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, write => 1, type => 'varchar(64)', default => ''}, } }; @@ -266,7 +244,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/GroupMember.pm b/rt/lib/RT/GroupMember.pm index 692303a8a..8de1a73fe 100755 --- a/rt/lib/RT/GroupMember.pm +++ b/rt/lib/RT/GroupMember.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -83,7 +61,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -111,7 +89,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -120,14 +98,14 @@ Returns the current value of id. =cut -=head2 GroupId +=item GroupId Returns the current value of GroupId. (In the database, GroupId is stored as int(11).) -=head2 SetGroupId VALUE +=item SetGroupId VALUE Set GroupId to VALUE. @@ -138,14 +116,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 MemberId +=item MemberId Returns the current value of MemberId. (In the database, MemberId is stored as int(11).) -=head2 SetMemberId VALUE +=item SetMemberId VALUE Set MemberId to VALUE. @@ -157,15 +135,15 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, GroupId => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, MemberId => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, } }; @@ -197,7 +175,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/GroupMembers.pm b/rt/lib/RT/GroupMembers.pm index 2cf2cd3f3..31cb9536f 100755 --- a/rt/lib/RT/GroupMembers.pm +++ b/rt/lib/RT/GroupMembers.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::GroupMember item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Groups.pm b/rt/lib/RT/Groups.pm index 46337f7be..29f12a5a0 100755 --- a/rt/lib/RT/Groups.pm +++ b/rt/lib/RT/Groups.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::Group item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Handle.pm b/rt/lib/RT/Handle.pm index 21ca1ace6..5cdb65e5b 100644 --- a/rt/lib/RT/Handle.pm +++ b/rt/lib/RT/Handle.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,30 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# CONTRIBUTION SUBMISSION POLICY: +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# (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 }}} - +# END LICENSE BLOCK =head1 NAME RT::Handle - RT's database handle @@ -71,13 +48,7 @@ use vars qw/@ISA/; eval "use DBIx::SearchBuilder::Handle::$RT::DatabaseType; \@ISA= qw(DBIx::SearchBuilder::Handle::$RT::DatabaseType);"; - -if ($@) { - die "Unable to load DBIx::SearchBuilder database handle for '$RT::DatabaseType'.". - "\n". - "Perhaps you've picked an invalid database type or spelled it incorrectly.". - "\n". $@; -} +#TODO check for errors here. =head2 Connect @@ -87,41 +58,29 @@ Takes nothing. Calls SUPER::Connect with the needed args =cut sub Connect { - my $self = shift; +my $self=shift; - if ($RT::DatabaseType eq 'Oracle') { - $ENV{'NLS_LANG'} = "AMERICAN_AMERICA.AL32UTF8"; - $ENV{'NLS_NCHAR'} = "AL32UTF8"; - - } +# Unless the database port is a positive integer, we really don't want to pass it. - $self->SUPER::Connect( +$self->SUPER::Connect( User => $RT::DatabaseUser, Password => $RT::DatabasePassword, ); - - $self->dbh->{LongReadLen} = $RT::MaxAttachmentSize; } -=head2 BuildDSN +=item BuildDSN Build the DSN for the RT database. doesn't take any parameters, draws all that from the config file. =cut -use File::Spec; sub BuildDSN { my $self = shift; -# Unless the database port is a positive integer, we really don't want to pass it. $RT::DatabasePort = undef unless (defined $RT::DatabasePort && $RT::DatabasePort =~ /^(\d+)$/); $RT::DatabaseHost = undef unless (defined $RT::DatabaseHost && $RT::DatabaseHost ne ''); -$RT::DatabaseName = File::Spec->catfile($RT::VarPath, $RT::DatabaseName) - if ($RT::DatabaseType eq 'SQLite') and - not File::Spec->file_name_is_absolute($RT::DatabaseName); - $self->SUPER::BuildDSN(Host => $RT::DatabaseHost, Database => $RT::DatabaseName, diff --git a/rt/lib/RT/I18N/en_malkovich.po b/rt/lib/RT/I18N/en_malkovich.po deleted file mode 100644 index 74769f1a3..000000000 --- a/rt/lib/RT/I18N/en_malkovich.po +++ /dev/null @@ -1,3973 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: html/Approvals/Elements/Approve:26 html/Approvals/Elements/ShowDependency:49 html/SelfService/Display.html:24 html/Ticket/Display.html:25 html/Ticket/Display.html:29 -#. ($TicketObj->Id, $TicketObj->Subject) -#. ($Ticket->id, $Ticket->Subject) -#. ($ticket->Id, $ticket->Subject) -#. ($link->BaseObj->Id, $link->BaseObj->Subject) -msgid "#%1: %2" -msgstr "#%1: %2" - -#: html/Search/Elements/SelectPersonType:30 lib/RT/Date.pm:337 -#. ($s, $time_unit) -#. ($option, $subtype) -msgid "%1 %2" -msgstr "%1 %2" - -#: lib/RT/Tickets_Overlay.pm:828 -#. ($args{'FIELD'}, $args{'OPERATOR'}, $args{'VALUE'}) -msgid "%1 %2 %3" -msgstr "%1 %2 %3" - -#: lib/RT/Date.pm:373 -#. ($self->GetWeekday($wday), $self->GetMonth($mon), map {sprintf "%02d", $_} ($mday, $hour, $min, $sec), ($year+1900)) -msgid "%1 %2 %3 %4:%5:%6 %7" -msgstr "%1 %2 %3 %4:%5:%6 %7" - -#: lib/RT/Ticket_Overlay.pm:3451 lib/RT/Transaction_Overlay.pm:550 lib/RT/Transaction_Overlay.pm:593 -#. ($cf->Name, $new_value->Content) -#. ($field, $self->NewValue) -#. ($self->Field, $principal->Object->Name) -msgid "%1 %2 added" -msgstr "%1 %2 Malkovich" - -#: lib/RT/Date.pm:334 -#. ($s, $time_unit) -msgid "%1 %2 ago" -msgstr "%1 %2 ago" - -#: lib/RT/Ticket_Overlay.pm:3457 lib/RT/Transaction_Overlay.pm:557 -#. ($cf->Name, $old_value, $new_value->Content) -#. ($field, $self->OldValue, $self->NewValue) -msgid "%1 %2 changed to %3" -msgstr "%1 %2 Malkovich to %3" - -#: lib/RT/Ticket_Overlay.pm:3454 lib/RT/Transaction_Overlay.pm:553 lib/RT/Transaction_Overlay.pm:599 -#. ($cf->Name, $old_value) -#. ($field, $self->OldValue) -#. ($self->Field, $principal->Object->Name) -msgid "%1 %2 deleted" -msgstr "%1 %2 Malkovich" - -#: html/Admin/Elements/EditScrips:43 html/Admin/Elements/ListGlobalScrips:27 html/Ticket/Elements/PreviewScrips:53 -#. ($scrip->ConditionObj->Name, $scrip->ActionObj->Name, $scrip->TemplateObj->Name) -#. (loc($scrip->ConditionObj->Name), loc($scrip->ActionObj->Name), loc($scrip->TemplateObj->Name)) -msgid "%1 %2 with template %3" -msgstr "%1 %2 Malkovich %3" - -#: bin/rt-crontool:165 bin/rt-crontool:172 bin/rt-crontool:178 -#. ("--search-argument", "--search") -#. ("--condition-argument", "--condition") -#. ("--action-argument", "--action") -msgid "%1 - An argument to pass to %2" -msgstr "%1 - A Malkovich to pass to %2" - -#: bin/rt-crontool:181 -#. ("--verbose") -msgid "%1 - Output status updates to STDOUT" -msgstr "%1 - Malkovich Malkovich to MALKOVICH" - -#: bin/rt-crontool:175 -#. ("--action") -msgid "%1 - Specify the action module you want to use" -msgstr "%1 - Malkovich the Malkovich Malkovich to use" - -#: bin/rt-crontool:169 -#. ("--condition") -msgid "%1 - Specify the condition module you want to use" -msgstr "%1 - Malkovich the Malkovich Malkovich to use" - -#: bin/rt-crontool:162 -#. ("--search") -msgid "%1 - Specify the search module you want to use" -msgstr "%1 - Malkovich the Malkovich Malkovich to use" - -#: lib/RT/ScripAction_Overlay.pm:114 -#. ($self->Id) -msgid "%1 ScripAction loaded" -msgstr "%1 Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:3484 -#. ($args{'Value'}, $cf->Name) -msgid "%1 added as a value for %2" -msgstr "%1 Malkovich as a Malkovich %2" - -#: lib/RT/Link_Overlay.pm:111 lib/RT/Link_Overlay.pm:118 -#. ($args{'Base'}) -#. ($args{'Target'}) -msgid "%1 appears to be a local object, but can't be found in the database" -msgstr "%1 Malkovich to be a Malkovich, but can't be Malkovich in the Malkovich" - -#: html/Ticket/Elements/ShowDates:52 lib/RT/Transaction_Overlay.pm:458 -#. ($self->BriefDescription , $self->CreatorObj->Name) -#. ($Ticket->LastUpdatedAsString, $Ticket->LastUpdatedByObj->Name) -msgid "%1 by %2" -msgstr "%1 by %2" - -#: lib/RT/Transaction_Overlay.pm:512 lib/RT/Transaction_Overlay.pm:688 lib/RT/Transaction_Overlay.pm:697 lib/RT/Transaction_Overlay.pm:700 -#. ($self->Field , ( $self->OldValue || $no_value ) , $self->NewValue) -#. ($self->Field , $q1->Name , $q2->Name) -#. ($self->Field, $t2->AsString, $t1->AsString) -#. ($self->Field, $self->OldValue, $self->NewValue) -msgid "%1 changed from %2 to %3" -msgstr "%1 Malkovich %2 to %3" - -#: lib/RT/Record.pm:739 -msgid "%1 could not be set to %2." -msgstr "%1 Malkovich be set to %2." - -#: lib/RT/Ticket_Overlay.pm:2739 -#. ($self) -msgid "%1 couldn't set status to resolved. RT's Database may be inconsistent." -msgstr "%1 couldn't Malkovich to Malkovich. RT's Malkovich be Malkovich." - -#: NOT FOUND IN SOURCE -msgid "%1 highest priority tickets I own..." -msgstr "%1 Malkovich Malkovich I Malkovich..." - -#: html/Elements/MyTickets:26 -#. ($rows) -msgid "%1 highest priority tickets I requested..." -msgstr "%1 Malkovich Malkovich I Malkovich..." - -#: bin/rt-crontool:157 -#. ($0) -msgid "%1 is a tool to act on tickets from an external scheduling tool, such as cron." -msgstr "%1 is a tool to act on Malkovich a Malkovich Malkovich, such as cron." - -#: lib/RT/Queue_Overlay.pm:784 -#. ($principal->Object->Name, $args{'Type'}) -msgid "%1 is no longer a %2 for this queue." -msgstr "%1 is no Malkovich a %2 Malkovich." - -#: lib/RT/Ticket_Overlay.pm:3540 -#. ($args{'Value'}, $cf->Name) -msgid "%1 is no longer a value for custom field %2" -msgstr "%1 is no Malkovich a Malkovich Malkovich %2" - -#: html/Ticket/Create.html:155 html/Ticket/Create.html:156 html/Ticket/Elements/ShowBasics:36 html/Ticket/Elements/ShowBasics:42 html/Ticket/Elements/ShowBasics:47 -#. ('<input size=3 name="TimeWorked" value="'.$ARGS{TimeWorked}.'">') -#. ('<input size=3 name="TimeLeft" value="'.$ARGS{TimeLeft}.'">') -#. ($Ticket->TimeEstimated) -#. ($Ticket->TimeWorked) -#. ($Ticket->TimeLeft) -msgid "%1 min" -msgstr "%1 min" - -#: html/User/Elements/DelegateRights:75 -#. (loc($ObjectType =~ /^RT::(.*)$/)) -msgid "%1 rights" -msgstr "%1 Malkovich" - -#: lib/RT/Action/ResolveMembers.pm:41 -#. (ref $self) -msgid "%1 will resolve all members of a resolved group ticket." -msgstr "%1 Malkovich Malkovich of a Malkovich Malkovich." - -#: lib/RT/Transaction_Overlay.pm:408 -#. ($self) -msgid "%1: no attachment specified" -msgstr "%1: no Malkovich Malkovich" - -#: html/Ticket/Elements/ShowTransactionAttachments:56 -#. ($size) -msgid "%1b" -msgstr "%1b" - -#: html/Ticket/Elements/ShowTransactionAttachments:53 -#. (int( $size / 102.4 ) / 10) -msgid "%1k" -msgstr "%1k" - -#: lib/RT/Ticket_Overlay.pm:1252 -#. ($args{'Status'}) -msgid "'%1' is an invalid value for status" -msgstr "'%1' is a Malkovich Malkovich" - -#: html/Admin/Elements/EditCustomFieldValues:24 html/Admin/Elements/EditQueueWatchers:28 html/Admin/Elements/EditScrips:34 html/Admin/Elements/EditTemplates:35 html/Admin/Groups/Members.html:51 html/Elements/EditLinks:32 html/Ticket/Elements/EditPeople:45 html/User/Groups/Members.html:54 -msgid "(Check box to delete)" -msgstr "(Malkovich to Malkovich)" - -#: html/Ticket/Elements/PreviewScrips:49 -msgid "(Check boxes to disable notifications to the listed recipients)" -msgstr "(Malkovich to Malkovich Malkovich to the Malkovich Malkovich)" - -#: html/Ticket/Elements/PreviewScrips:71 -msgid "(Check boxes to enable notifications to the listed recipients)" -msgstr "(Malkovich to Malkovich Malkovich to the Malkovich Malkovich)" - -#: NOT FOUND IN SOURCE -msgid "(Enter ticket ids or URLs, seperated with spaces)" -msgstr "(Malkovich Malkovich or URLs, Malkovich Malkovich)" - -#: html/Admin/Queues/Modify.html:53 html/Admin/Queues/Modify.html:59 -#. ($RT::CorrespondAddress) -#. ($RT::CommentAddress) -msgid "(If left blank, will default to %1" -msgstr "(If Malkovich, Malkovich to %1" - -#: html/Admin/Elements/EditCustomFields:32 html/Admin/Elements/ListGlobalCustomFields:31 -msgid "(No custom fields)" -msgstr "(No Malkovich)" - -#: html/Admin/Groups/Members.html:49 html/User/Groups/Members.html:52 -msgid "(No members)" -msgstr "(No Malkovich)" - -#: html/Admin/Elements/EditScrips:31 html/Admin/Elements/ListGlobalScrips:31 -msgid "(No scrips)" -msgstr "(No Malkovich)" - -#: html/Admin/Elements/EditTemplates:30 -msgid "(No templates)" -msgstr "(No Malkovich)" - -#: html/Ticket/Update.html:66 -msgid "(Sends a blind carbon-copy of this update to a comma-delimited list of email addresses. Does <b>not</b> change who will receive future updates.)" -msgstr "(Malkovich a Malkovich-copy of Malkovich to a Malkovich-Malkovich of Malkovich. Does <b>not</b> Malkovich Malkovich Malkovich Malkovich.)" - -#: html/Ticket/Create.html:78 -msgid "(Sends a carbon-copy of this update to a comma-delimited list of administrative email addresses. These people <b>will</b> receive future updates.)" -msgstr "(Malkovich a Malkovich-copy of Malkovich to a Malkovich-Malkovich of Malkovich Malkovich Malkovich. Malkovich <b>will</b> Malkovich Malkovich.)" - -#: html/Ticket/Update.html:62 -msgid "(Sends a carbon-copy of this update to a comma-delimited list of email addresses. Does <b>not</b> change who will receive future updates.)" -msgstr "(Malkovich a Malkovich-copy of Malkovich to a Malkovich-Malkovich of Malkovich. Does <b>not</b> Malkovich Malkovich Malkovich Malkovich.)" - -#: html/Ticket/Create.html:68 -msgid "(Sends a carbon-copy of this update to a comma-delimited list of email addresses. These people <b>will</b> receive future updates.)" -msgstr "(Malkovich a Malkovich-copy of Malkovich to a Malkovich-Malkovich of Malkovich. Malkovich <b>will</b> Malkovich Malkovich.)" - -#: html/Admin/Groups/index.html:32 html/User/Groups/index.html:32 -msgid "(empty)" -msgstr "(Malkovich)" - -#: html/Admin/Users/index.html:38 -msgid "(no name listed)" -msgstr "(no Malkovich)" - -#: html/Admin/Elements/SelectRights:47 html/Elements/SelectCustomFieldValue:29 html/Ticket/Elements/EditCustomField:64 html/Ticket/Elements/ShowCustomFields:35 lib/RT/Transaction_Overlay.pm:511 -msgid "(no value)" -msgstr "(no Malkovich)" - -#: html/Elements/EditLinks:105 html/Ticket/Elements/BulkLinks:27 -msgid "(only one ticket)" -msgstr "(Malkovich)" - -#: html/Elements/TicketList:167 -msgid "(pending approval)" -msgstr "(Malkovich Malkovich)" - -#: html/Elements/TicketList:170 -msgid "(pending other Collection)" -msgstr "(Malkovich Malkovich)" - -#: NOT FOUND IN SOURCE -msgid "(pending other tickets)" -msgstr "(Malkovich Malkovich)" - -#: html/Admin/Users/Modify.html:49 -msgid "(required)" -msgstr "(Malkovich)" - -#: html/Ticket/Elements/ShowTransactionAttachments:60 -msgid "(untitled)" -msgstr "(Malkovich)" - -#: NOT FOUND IN SOURCE -msgid "..." -msgstr "..." - -#: html/Ticket/Elements/ShowBasics:31 -msgid "<% $Ticket->Status%>" -msgstr "<% $Ticket->Status %>" - -#: html/Elements/SelectTicketTypes:26 -msgid "<% $_ %>" -msgstr "<% $_ %>" - -#: docs/design_docs/string-extraction-guide.txt:54 html/Elements/CreateTicket:25 lib/RT/StyleGuide.pod:767 -#. ($m->scomp('/Elements/SelectNewTicketQueue')) -msgid "<input type=\"submit\" value=\"New ticket in\"> %1" -msgstr "<input type=\"submit\" value=\"Malkovich in\"> %1" - -#: etc/initialdata:218 -msgid "A blank template" -msgstr "A Malkovich" - -#: lib/RT/ACE_Overlay.pm:156 lib/RT/Principal_Overlay.pm:180 -msgid "ACE not found" -msgstr "Malkovich" - -#: lib/RT/ACE_Overlay.pm:830 -msgid "ACEs can only be created and deleted." -msgstr "Malkovich be Malkovich and Malkovich." - -#: NOT FOUND IN SOURCE -msgid "Aborting to avoid unintended ticket modifications.\\n" -msgstr "Malkovich to Malkovich Malkovich Malkovich Malkovich.\\n" - -#: html/User/Elements/Tabs:31 -msgid "About me" -msgstr "Malkovich me" - -#: html/Admin/Users/Modify.html:79 -msgid "Access control" -msgstr "Malkovich" - -#: html/Admin/Elements/EditScrip:49 -msgid "Action" -msgstr "Malkovich" - -#: lib/RT/Scrip_Overlay.pm:148 -#. ($args{'ScripAction'}) -msgid "Action %1 not found" -msgstr "Malkovich %1 Malkovich" - -#: bin/rt-crontool:119 -msgid "Action committed." -msgstr "Malkovich Malkovich." - -#: bin/rt-crontool:115 -msgid "Action prepared..." -msgstr "Malkovich..." - -#: html/Search/Bulk.html:93 -msgid "Add AdminCc" -msgstr "Malkovich" - -#: html/Search/Bulk.html:89 -msgid "Add Cc" -msgstr "Add Cc" - -#: html/Ticket/Create.html:113 html/Ticket/Update.html:81 -msgid "Add More Files" -msgstr "Malkovich" - -#: html/Search/Bulk.html:85 -msgid "Add Requestor" -msgstr "Malkovich" - -#: html/Admin/Elements/AddCustomFieldValue:24 -msgid "Add Value" -msgstr "Malkovich" - -#: html/Admin/Global/Scrip.html:54 -msgid "Add a scrip which will apply to all queues" -msgstr "Add a Malkovich Malkovich to Malkovich" - -#: html/Search/Bulk.html:125 -msgid "Add comments or replies to selected tickets" -msgstr "Malkovich or Malkovich to Malkovich Malkovich" - -#: html/Admin/Groups/Members.html:41 html/User/Groups/Members.html:38 -msgid "Add members" -msgstr "Malkovich" - -#: html/Admin/Queues/People.html:65 html/Ticket/Elements/AddWatchers:27 -msgid "Add new watchers" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:684 -#. ($args{'Type'}) -msgid "Added principal as a %1 for this queue" -msgstr "Malkovich as a %1 Malkovich" - -#: lib/RT/Ticket_Overlay.pm:1547 -#. ($self->loc($args{'Type'})) -msgid "Added principal as a %1 for this ticket" -msgstr "Malkovich as a %1 Malkovich" - -#: html/Admin/Users/Modify.html:119 html/User/Prefs.html:111 -msgid "Address1" -msgstr "Malkovich1" - -#: html/Admin/Users/Modify.html:124 html/User/Prefs.html:115 -msgid "Address2" -msgstr "Malkovich2" - -#: html/Ticket/Create.html:73 -msgid "Admin Cc" -msgstr "Malkovich Cc" - -#: etc/initialdata:295 -msgid "Admin Comment" -msgstr "Malkovich" - -#: etc/initialdata:274 -msgid "Admin Correspondence" -msgstr "Malkovich Malkovich" - -#: html/Admin/Queues/index.html:24 html/Admin/Queues/index.html:27 -msgid "Admin queues" -msgstr "Malkovich" - -#: html/Admin/Global/index.html:25 html/Admin/Global/index.html:27 -msgid "Admin/Global configuration" -msgstr "Malkovich/Malkovich Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Admin/Queue/Basics" -msgstr "Malkovich/Malkovich/Malkovich" - -#: etc/initialdata:56 html/Ticket/Elements/ShowPeople:38 lib/RT/ACE_Overlay.pm:88 -msgid "AdminCc" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:73 -msgid "AdminCustomFields" -msgstr "Malkovich Malkovich" - -#: lib/RT/Group_Overlay.pm:146 -msgid "AdminGroup" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:148 -msgid "AdminGroupMembership" -msgstr "Malkovich Malkovich" - -#: lib/RT/System.pm:58 -msgid "AdminOwnPersonalGroups" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:69 -msgid "AdminQueue" -msgstr "Malkovich" - -#: lib/RT/System.pm:59 -msgid "AdminUsers" -msgstr "Malkovich" - -#: html/Admin/Queues/People.html:47 html/Ticket/Elements/EditPeople:53 -msgid "Administrative Cc" -msgstr "Malkovich Cc" - -#: html/Elements/SelectDateRelation:35 -msgid "After" -msgstr "Malkovich" - -#: etc/initialdata:363 -msgid "All Approvals Passed" -msgstr "Malkovich Malkovich" - -#: html/Admin/Elements/EditCustomFields:94 -msgid "All Custom Fields" -msgstr "Malkovich Malkovich" - -#: html/Admin/Queues/index.html:52 -msgid "All Queues" -msgstr "Malkovich" - -#: html/Elements/Tabs:58 -msgid "Approval" -msgstr "Malkovich" - -#: html/Approvals/Display.html:45 html/Approvals/Elements/ShowDependency:41 html/Approvals/index.html:64 -#. ($Ticket->Id, $Ticket->Subject) -#. ($ticket->id, $msg) -#. ($link->BaseObj->Id, $link->BaseObj->Subject) -msgid "Approval #%1: %2" -msgstr "Malkovich #%1: %2" - -#: html/Approvals/index.html:53 -#. ($ticket->Id) -msgid "Approval #%1: Notes not recorded due to a system error" -msgstr "Malkovich #%1: Malkovich Malkovich to a Malkovich" - -#: html/Approvals/index.html:51 -#. ($ticket->Id) -msgid "Approval #%1: Notes recorded" -msgstr "Malkovich #%1: Malkovich" - -#: etc/initialdata:351 -msgid "Approval Passed" -msgstr "Malkovich" - -#: etc/initialdata:374 -msgid "Approval Rejected" -msgstr "Malkovich Malkovich" - -#: html/Approvals/Elements/Approve:43 -msgid "Approve" -msgstr "Malkovich" - -#: etc/initialdata:504 -msgid "Approver's notes: %1" -msgstr "Malkovich's Malkovich: %1" - -#: lib/RT/Date.pm:414 -msgid "Apr." -msgstr "Apr." - -#: html/Elements/SelectSortOrder:34 html/Search/Elements/DisplayOptions:52 -msgid "Ascending" -msgstr "Malkovich" - -#: html/Search/Bulk.html:134 html/SelfService/Update.html:47 html/Ticket/ModifyAll.html:82 html/Ticket/Update.html:81 -msgid "Attach" -msgstr "Malkovich" - -#: html/SelfService/Create.html:64 html/Ticket/Create.html:109 -msgid "Attach file" -msgstr "Malkovich" - -#: html/SelfService/Update.html:36 html/Ticket/Create.html:97 html/Ticket/Update.html:70 -msgid "Attached file" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:416 -msgid "Attachment created" -msgstr "Malkovich Malkovich" - -#: lib/RT/Tickets_Overlay.pm:1251 -msgid "Attachment filename" -msgstr "Malkovich Malkovich" - -#: html/Ticket/Elements/ShowAttachments:25 -msgid "Attachments" -msgstr "Malkovich" - -#: lib/RT/Attributes_Overlay.pm:158 -msgid "Attribute Deleted" -msgstr "Malkovich Malkovich" - -#: lib/RT/Date.pm:418 -msgid "Aug." -msgstr "Aug." - -#: NOT FOUND IN SOURCE -msgid "AuthSystem" -msgstr "Malkovich" - -#: etc/initialdata:221 -msgid "Autoreply" -msgstr "Malkovich" - -#: etc/initialdata:72 -msgid "Autoreply To Requestors" -msgstr "Malkovich To Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Bad data in %1" -msgstr "Malkovich in %1" - -#: html/Admin/Elements/GroupTabs:38 html/Admin/Elements/QueueTabs:38 html/Admin/Elements/UserTabs:37 html/Ticket/Elements/Tabs:91 html/User/Elements/GroupTabs:37 -msgid "Basics" -msgstr "Malkovich" - -#: html/Ticket/Update.html:64 -msgid "Bcc" -msgstr "Bcc" - -#: html/Admin/Elements/EditScrip:73 -msgid "Be sure to save your changes" -msgstr "Be sure to Malkovich Malkovich" - -#: html/Elements/SelectDateRelation:33 lib/RT/CurrentUser.pm:336 -msgid "Before" -msgstr "Malkovich" - -#: etc/initialdata:217 -msgid "Blank" -msgstr "Malkovich" - -#: html/Ticket/Elements/ShowHistory:38 html/Ticket/Elements/ShowHistory:44 -msgid "Brief headers" -msgstr "Malkovich" - -#: html/Search/Bulk.html:24 html/Search/Bulk.html:25 -msgid "Bulk ticket update" -msgstr "Malkovich Malkovich" - -#: lib/RT/User_Overlay.pm:1533 -msgid "Can not modify system users" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:68 -msgid "Can this principal see this queue" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/CustomField_Overlay.pm:211 -msgid "Can't add a custom field value without a name" -msgstr "Can't add a Malkovich Malkovich Malkovich a name" - -#: lib/RT/Link_Overlay.pm:126 -msgid "Can't link a ticket to itself" -msgstr "Can't link a Malkovich to Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2716 -msgid "Can't merge into a merged ticket. You should never get this error" -msgstr "Can't Malkovich a Malkovich. Malkovich Malkovich Malkovich" - -#: lib/RT/Record.pm:1060 lib/RT/Record.pm:1138 -msgid "Can't specifiy both base and target" -msgstr "Can't Malkovich Malkovich and Malkovich" - -#: html/autohandler:132 -#. ($msg) -msgid "Cannot create user: %1" -msgstr "Malkovich Malkovich: %1" - -#: etc/initialdata:50 html/Admin/Queues/People.html:43 html/SelfService/Create.html:48 html/Ticket/Create.html:63 html/Ticket/Elements/EditPeople:50 html/Ticket/Elements/ShowPeople:34 html/Ticket/Update.html:59 lib/RT/ACE_Overlay.pm:87 -msgid "Cc" -msgstr "Cc" - -#: html/SelfService/Prefs.html:30 -msgid "Change password" -msgstr "Malkovich" - -#: html/SelfService/Update.html:39 html/Ticket/Create.html:100 html/Ticket/Update.html:73 -msgid "Check box to delete" -msgstr "Malkovich to Malkovich" - -#: html/Admin/Elements/SelectRights:30 -msgid "Check box to revoke right" -msgstr "Malkovich to Malkovich" - -#: html/Elements/EditLinks:121 html/Elements/EditLinks:63 html/Elements/ShowLinks:56 html/Ticket/Create.html:183 html/Ticket/Elements/BulkLinks:42 -msgid "Children" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:129 html/User/Prefs.html:119 -msgid "City" -msgstr "City" - -#: html/Ticket/Elements/ShowDates:47 -msgid "Closed" -msgstr "Malkovich" - -#: html/SelfService/Closed.html:24 -msgid "Closed Tickets" -msgstr "Malkovich" - -#: html/SelfService/Elements/Tabs:44 -msgid "Closed tickets" -msgstr "Malkovich" - -#: html/Ticket/Elements/ShowTransaction:152 html/Ticket/Elements/Tabs:154 -msgid "Comment" -msgstr "Malkovich" - -#: html/Admin/Queues/Modify.html:57 -msgid "Comment Address" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:88 -msgid "Comment on tickets" -msgstr "Malkovich on Malkovich" - -#: lib/RT/Queue_Overlay.pm:88 -msgid "CommentOnTicket" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Comments" -msgstr "Malkovich" - -#: html/Ticket/ModifyAll.html:69 html/Ticket/Update.html:51 -msgid "Comments (Not sent to requestors)" -msgstr "Malkovich (Malkovich to Malkovich)" - -#: html/Search/Bulk.html:129 -msgid "Comments (not sent to requestors)" -msgstr "Malkovich (Malkovich to Malkovich)" - -#: NOT FOUND IN SOURCE -msgid "Comments about %1" -msgstr "Malkovich %1" - -#: html/Admin/Users/Modify.html:182 html/Ticket/Elements/ShowRequestor:45 -msgid "Comments about this user" -msgstr "Malkovich Malkovich" - -#: lib/RT/Transaction_Overlay.pm:537 -msgid "Comments added" -msgstr "Malkovich" - -#: lib/RT/Action/Generic.pm:149 -msgid "Commit Stubbed" -msgstr "Malkovich" - -#: html/Admin/Elements/EditScrip:41 -msgid "Condition" -msgstr "Malkovich" - -#: bin/rt-crontool:105 -msgid "Condition matches..." -msgstr "Malkovich Malkovich..." - -#: lib/RT/Scrip_Overlay.pm:164 -msgid "Condition not found" -msgstr "Malkovich Malkovich" - -#: html/Elements/Tabs:52 -msgid "Configuration" -msgstr "Malkovich" - -#: html/SelfService/Prefs.html:32 -msgid "Confirm" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "ContactInfoSystem" -msgstr "Malkovich Malkovich" - -#: html/Admin/Elements/ModifyTemplate:43 html/Elements/SelectAttachmentField:26 html/Ticket/ModifyAll.html:86 -msgid "Content" -msgstr "Malkovich" - -#: etc/initialdata:286 -msgid "Correspondence" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Correspondence Address" -msgstr "Malkovich Malkovich" - -#: lib/RT/Transaction_Overlay.pm:533 -msgid "Correspondence added" -msgstr "Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:3471 -msgid "Could not add new custom field value for ticket. " -msgstr "Malkovich Malkovich Malkovich Malkovich Malkovich. " - -#: lib/RT/Ticket_Overlay.pm:2967 lib/RT/Ticket_Overlay.pm:2975 lib/RT/Ticket_Overlay.pm:2992 -msgid "Could not change owner. " -msgstr "Malkovich Malkovich. " - -#: html/Admin/Elements/EditCustomField:84 html/Admin/Elements/EditCustomFields:164 -#. ($msg) -msgid "Could not create CustomField" -msgstr "Malkovich Malkovich Malkovich" - -#: html/User/Groups/Modify.html:76 lib/RT/Group_Overlay.pm:474 lib/RT/Group_Overlay.pm:481 -msgid "Could not create group" -msgstr "Malkovich Malkovich" - -#: html/Admin/Global/Template.html:74 html/Admin/Queues/Template.html:71 -#. ($msg) -msgid "Could not create template: %1" -msgstr "Malkovich Malkovich: %1" - -#: lib/RT/Ticket_Overlay.pm:1185 lib/RT/Ticket_Overlay.pm:364 -msgid "Could not create ticket. Queue not set" -msgstr "Malkovich Malkovich. Malkovich" - -#: lib/RT/User_Overlay.pm:226 lib/RT/User_Overlay.pm:240 lib/RT/User_Overlay.pm:249 lib/RT/User_Overlay.pm:258 lib/RT/User_Overlay.pm:267 lib/RT/User_Overlay.pm:281 lib/RT/User_Overlay.pm:291 lib/RT/User_Overlay.pm:462 -msgid "Could not create user" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:662 lib/RT/Ticket_Overlay.pm:1515 -msgid "Could not find or create that user" -msgstr "Malkovich or Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:723 lib/RT/Ticket_Overlay.pm:1596 -msgid "Could not find that principal" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Admin/Groups/Members.html:87 html/User/Groups/Members.html:89 html/User/Groups/Modify.html:81 -msgid "Could not load group" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:682 -#. ($args{'Type'}) -msgid "Could not make that principal a %1 for this queue" -msgstr "Malkovich Malkovich Malkovich a %1 Malkovich" - -#: lib/RT/Ticket_Overlay.pm:1536 -#. ($self->loc($args{'Type'})) -msgid "Could not make that principal a %1 for this ticket" -msgstr "Malkovich Malkovich Malkovich a %1 Malkovich" - -#: lib/RT/Queue_Overlay.pm:781 -#. ($args{'Type'}) -msgid "Could not remove that principal as a %1 for this queue" -msgstr "Malkovich Malkovich Malkovich as a %1 Malkovich" - -#: lib/RT/Group_Overlay.pm:977 -msgid "Couldn't add member to group" -msgstr "Couldn't Malkovich to Malkovich" - -#: lib/RT/Ticket_Overlay.pm:3481 lib/RT/Ticket_Overlay.pm:3537 -#. ($Msg) -msgid "Couldn't create a transaction: %1" -msgstr "Couldn't Malkovich a Malkovich: %1" - -#: lib/RT/Record.pm:748 -msgid "Couldn't find row" -msgstr "Couldn't Malkovich" - -#: lib/RT/Group_Overlay.pm:951 -msgid "Couldn't find that principal" -msgstr "Couldn't Malkovich Malkovich" - -#: lib/RT/CustomField_Overlay.pm:245 -msgid "Couldn't find that value" -msgstr "Couldn't Malkovich" - -#: lib/RT/CurrentUser.pm:123 -#. ($self->Id) -msgid "Couldn't load %1 from the users database.\\n" -msgstr "Couldn't load %1 from the Malkovich.\\n" - -#: html/Admin/Groups/GroupRights.html:87 html/Admin/Groups/UserRights.html:74 -#. ($id) -msgid "Couldn't load group %1" -msgstr "Couldn't Malkovich %1" - -#: lib/RT/Link_Overlay.pm:169 lib/RT/Link_Overlay.pm:178 lib/RT/Link_Overlay.pm:205 -msgid "Couldn't load link" -msgstr "Couldn't Malkovich" - -#: html/Admin/Elements/EditCustomFields:145 html/Admin/Queues/CustomFields.html:35 html/Admin/Queues/People.html:120 -#. ($id) -msgid "Couldn't load queue" -msgstr "Couldn't Malkovich" - -#: html/Admin/Queues/GroupRights.html:100 html/Admin/Queues/UserRights.html:71 -#. ($id) -msgid "Couldn't load queue %1" -msgstr "Couldn't Malkovich %1" - -#: NOT FOUND IN SOURCE -msgid "Couldn't load that user (%1)" -msgstr "Couldn't Malkovich (%1)" - -#: html/SelfService/Display.html:116 -#. ($id) -msgid "Couldn't load ticket '%1'" -msgstr "Couldn't Malkovich '%1'" - -#: html/Admin/Users/Modify.html:146 html/User/Prefs.html:131 -msgid "Country" -msgstr "Malkovich" - -#: html/Admin/Elements/CreateUserCalled:25 html/Admin/Elements/EditCustomField:62 html/Admin/Elements/EditScrip:110 html/Admin/Groups/Modify.html:55 html/Admin/Queues/Template.html:44 html/Elements/QuickCreate:23 html/Ticket/Create.html:134 html/Ticket/Create.html:195 html/User/Groups/Modify.html:55 -msgid "Create" -msgstr "Malkovich" - -#: etc/initialdata:135 -msgid "Create Tickets" -msgstr "Malkovich" - -#: html/Admin/Elements/EditCustomField:74 -msgid "Create a CustomField" -msgstr "Malkovich a Malkovich" - -#: html/Admin/Queues/CustomField.html:47 -#. ($QueueObj->Name()) -msgid "Create a CustomField for queue %1" -msgstr "Malkovich a Malkovich Malkovich %1" - -#: html/Admin/Global/CustomField.html:47 -msgid "Create a CustomField which applies to all queues" -msgstr "Malkovich a Malkovich Malkovich to Malkovich" - -#: html/Admin/Groups/Modify.html:66 html/Admin/Groups/Modify.html:92 -msgid "Create a new group" -msgstr "Malkovich a Malkovich" - -#: html/User/Groups/Modify.html:66 html/User/Groups/Modify.html:91 -msgid "Create a new personal group" -msgstr "Malkovich a Malkovich Malkovich" - -#: html/Ticket/Create.html:24 html/Ticket/Create.html:27 html/Ticket/Create.html:35 -msgid "Create a new ticket" -msgstr "Malkovich a Malkovich" - -#: html/Admin/Users/Modify.html:211 html/Admin/Users/Modify.html:268 -msgid "Create a new user" -msgstr "Malkovich a Malkovich" - -#: html/Admin/Queues/Modify.html:103 -msgid "Create a queue" -msgstr "Malkovich a Malkovich" - -#: html/Admin/Queues/Scrip.html:58 -#. ($QueueObj->Name) -msgid "Create a scrip for queue %1" -msgstr "Malkovich a Malkovich %1" - -#: html/Admin/Global/Template.html:68 html/Admin/Queues/Template.html:64 -msgid "Create a template" -msgstr "Malkovich a Malkovich" - -#: html/SelfService/Create.html:24 -msgid "Create a ticket" -msgstr "Malkovich a Malkovich" - -#: etc/initialdata:137 -msgid "Create new tickets based on this scrip's template" -msgstr "Malkovich Malkovich on Malkovich's Malkovich" - -#: html/SelfService/Create.html:77 -msgid "Create ticket" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:86 -msgid "Create tickets in this queue" -msgstr "Malkovich in Malkovich" - -#: lib/RT/Queue_Overlay.pm:73 -msgid "Create, delete and modify custom fields" -msgstr "Malkovich, Malkovich and Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:69 -msgid "Create, delete and modify queues" -msgstr "Malkovich, Malkovich and Malkovich" - -#: lib/RT/System.pm:58 -msgid "Create, delete and modify the members of personal groups" -msgstr "Malkovich, Malkovich and Malkovich the Malkovich of Malkovich" - -#: lib/RT/System.pm:59 -msgid "Create, delete and modify users" -msgstr "Malkovich, Malkovich and Malkovich" - -#: lib/RT/Queue_Overlay.pm:86 -msgid "CreateTicket" -msgstr "Malkovich" - -#: html/Elements/SelectDateType:25 html/Ticket/Elements/ShowDates:27 lib/RT/Ticket_Overlay.pm:1279 -msgid "Created" -msgstr "Malkovich" - -#: html/Admin/Elements/EditCustomField:87 -#. ($CustomFieldObj->Name()) -msgid "Created CustomField %1" -msgstr "Malkovich Malkovich %1" - -#: html/Elements/EditLinks:27 -msgid "Current Links" -msgstr "Malkovich Malkovich" - -#: html/Admin/Elements/EditScrips:29 -msgid "Current Scrips" -msgstr "Malkovich" - -#: html/Admin/Groups/Members.html:38 html/User/Groups/Members.html:41 -msgid "Current members" -msgstr "Malkovich" - -#: html/Admin/Elements/SelectRights:28 -msgid "Current rights" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Current search criteria" -msgstr "Malkovich Malkovich" - -#: html/Admin/Queues/People.html:40 html/Ticket/Elements/EditPeople:44 -msgid "Current watchers" -msgstr "Malkovich Malkovich" - -#: html/Admin/Global/CustomField.html:54 -#. ($CustomField) -msgid "Custom Field #%1" -msgstr "Malkovich #%1" - -#: html/Admin/Elements/QueueTabs:52 html/Admin/Elements/SystemTabs:39 html/Admin/Global/index.html:49 html/Ticket/Elements/ShowSummary:35 -msgid "Custom Fields" -msgstr "Malkovich" - -#: html/Admin/Elements/EditScrip:101 -msgid "Custom action cleanup code" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Admin/Elements/EditScrip:93 -msgid "Custom action preparation code" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Admin/Elements/EditScrip:85 -msgid "Custom condition" -msgstr "Malkovich Malkovich" - -#: lib/RT/Tickets_Overlay.pm:1693 -#. ($CF->Name , $args{OPERATOR} , $args{VALUE}) -msgid "Custom field %1 %2 %3" -msgstr "Malkovich %1 %2 %3" - -#: lib/RT/Tickets_Overlay.pm:1688 -#. ($CF->Name) -msgid "Custom field %1 has a value." -msgstr "Malkovich %1 has a Malkovich." - -#: lib/RT/Tickets_Overlay.pm:1685 -#. ($CF->Name) -msgid "Custom field %1 has no value." -msgstr "Malkovich %1 has no Malkovich." - -#: lib/RT/Ticket_Overlay.pm:3373 -#. ($args{'Field'}) -msgid "Custom field %1 not found" -msgstr "Malkovich %1 Malkovich" - -#: html/Admin/Elements/EditCustomFields:195 -msgid "Custom field deleted" -msgstr "Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:3523 -msgid "Custom field not found" -msgstr "Malkovich Malkovich" - -#: lib/RT/CustomField_Overlay.pm:355 -#. ($args{'Content'}, $self->Name) -msgid "Custom field value %1 could not be found for custom field %2" -msgstr "Malkovich Malkovich %1 Malkovich be Malkovich Malkovich %2" - -#: lib/RT/CustomField_Overlay.pm:255 -msgid "Custom field value could not be deleted" -msgstr "Malkovich Malkovich Malkovich be Malkovich" - -#: lib/RT/CustomField_Overlay.pm:361 -msgid "Custom field value could not be found" -msgstr "Malkovich Malkovich Malkovich be Malkovich" - -#: lib/RT/CustomField_Overlay.pm:253 lib/RT/CustomField_Overlay.pm:363 -msgid "Custom field value deleted" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/Transaction_Overlay.pm:541 -msgid "CustomField" -msgstr "Malkovich" - -#: html/SelfService/Display.html:38 html/Ticket/Create.html:160 html/Ticket/Elements/ShowSummary:54 html/Ticket/Elements/Tabs:94 html/Ticket/ModifyAll.html:43 -msgid "Dates" -msgstr "Malkovich" - -#: lib/RT/Date.pm:422 -msgid "Dec." -msgstr "Dec." - -#: etc/initialdata:222 -msgid "Default Autoresponse template" -msgstr "Malkovich Malkovich Malkovich" - -#: etc/initialdata:296 -msgid "Default admin comment template" -msgstr "Malkovich Malkovich Malkovich" - -#: etc/initialdata:287 -msgid "Default correspondence template" -msgstr "Malkovich Malkovich Malkovich" - -#: etc/initialdata:253 -msgid "Default transaction template" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/Transaction_Overlay.pm:519 -#. ($type, $self->Field, $self->OldValue, $self->NewValue) -msgid "Default: %1/%2 changed from %3 to %4" -msgstr "Malkovich: %1/%2 Malkovich %3 to %4" - -#: html/User/Delegation.html:24 html/User/Delegation.html:27 -msgid "Delegate rights" -msgstr "Malkovich" - -#: lib/RT/System.pm:62 -msgid "Delegate specific rights which have been granted to you." -msgstr "Malkovich Malkovich Malkovich Malkovich Malkovich to you." - -#: lib/RT/System.pm:62 -msgid "DelegateRights" -msgstr "Malkovich" - -#: html/User/Elements/Tabs:37 -msgid "Delegation" -msgstr "Malkovich" - -#: html/Admin/Elements/EditScrips:53 html/Search/Elements/EditFormat:66 html/Search/Elements/EditSearches:15 -msgid "Delete" -msgstr "Malkovich" - -#: html/Admin/Elements/EditScrips:52 -msgid "Delete selected scrips" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:91 -msgid "Delete tickets" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:91 -msgid "DeleteTicket" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:162 -msgid "Deleting this object could break referential integrity" -msgstr "Malkovich Malkovich Malkovich Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:329 -msgid "Deleting this object would break referential integrity" -msgstr "Malkovich Malkovich Malkovich Malkovich Malkovich" - -#: lib/RT/User_Overlay.pm:478 -msgid "Deleting this object would violate referential integrity" -msgstr "Malkovich Malkovich Malkovich Malkovich Malkovich Malkovich" - -#: html/Approvals/Elements/Approve:44 -msgid "Deny" -msgstr "Deny" - -#: html/Elements/EditLinks:113 html/Elements/EditLinks:44 html/Elements/ShowLinks:36 html/Ticket/Create.html:181 html/Ticket/Elements/BulkLinks:34 html/Ticket/Elements/ShowDependencies:31 -msgid "Depended on by" -msgstr "Malkovich on by" - -#: lib/RT/Transaction_Overlay.pm:621 -#. ($value) -msgid "Dependency by %1 added" -msgstr "Malkovich by %1 Malkovich" - -#: lib/RT/Transaction_Overlay.pm:661 -#. ($value) -msgid "Dependency by %1 deleted" -msgstr "Malkovich by %1 Malkovich" - -#: lib/RT/Transaction_Overlay.pm:618 -#. ($value) -msgid "Dependency on %1 added" -msgstr "Malkovich on %1 Malkovich" - -#: lib/RT/Transaction_Overlay.pm:658 -#. ($value) -msgid "Dependency on %1 deleted" -msgstr "Malkovich on %1 Malkovich" - -#: html/Elements/EditLinks:109 html/Elements/EditLinks:35 html/Elements/SelectLinkType:26 html/Elements/ShowLinks:26 html/Ticket/Create.html:180 html/Ticket/Elements/BulkLinks:30 html/Ticket/Elements/ShowDependencies:24 -msgid "Depends on" -msgstr "Malkovich on" - -#: html/Elements/SelectSortOrder:34 html/Search/Elements/DisplayOptions:57 -msgid "Descending" -msgstr "Malkovich" - -#: html/SelfService/Create.html:72 html/Ticket/Create.html:118 -msgid "Describe the issue below" -msgstr "Malkovich the Malkovich" - -#: html/Admin/Elements/AddCustomFieldValue:35 html/Admin/Elements/EditCustomField:38 html/Admin/Elements/EditScrip:34 html/Admin/Elements/ModifyTemplate:35 html/Admin/Groups/Modify.html:48 html/Admin/Queues/Modify.html:47 html/Elements/SelectGroups:26 html/Search/Elements/EditSearches:8 html/User/Groups/Modify.html:48 -msgid "Description" -msgstr "Malkovich" - -#: html/Ticket/Elements/Tabs:86 -msgid "Display" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:70 -msgid "Display Access Control List" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:76 -msgid "Display Scrip templates for this queue" -msgstr "Malkovich Malkovich Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:79 -msgid "Display Scrips for this queue" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Ticket/Elements/ShowHistory:34 -msgid "Display mode" -msgstr "Malkovich" - -#: lib/RT/System.pm:53 -msgid "Do anything and everything" -msgstr "Do Malkovich and Malkovich" - -#: html/Elements/Refresh:29 -msgid "Don't refresh this page." -msgstr "Don't Malkovich Malkovich." - -#: NOT FOUND IN SOURCE -msgid "Don't show search results" -msgstr "Don't Malkovich Malkovich" - -#: html/Ticket/Elements/ShowTransactionAttachments:60 -msgid "Download" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Download all the tickets as a tab delimited file" -msgstr "Malkovich the Malkovich as a Malkovich Malkovich" - -#: html/Elements/SelectDateType:31 html/Ticket/Create.html:166 html/Ticket/Elements/EditDates:44 html/Ticket/Elements/ShowDates:43 lib/RT/Ticket_Overlay.pm:1283 -msgid "Due" -msgstr "Due" - -#: NOT FOUND IN SOURCE -msgid "ERROR: Couldn't load ticket '%1': %2.\\n" -msgstr "MALKOVICH: Couldn't Malkovich '%1': %2.\\n" - -#: html/Admin/Queues/CustomFields.html:45 -#. ($Queue->Name) -msgid "Edit Custom Fields for %1" -msgstr "Malkovich Malkovich %1" - -#: html/Search/Bulk.html:141 html/Ticket/ModifyLinks.html:35 -msgid "Edit Links" -msgstr "Malkovich Malkovich" - -#: html/Admin/Queues/Templates.html:41 -#. ($QueueObj->Name) -msgid "Edit Templates for queue %1" -msgstr "Malkovich Malkovich %1" - -#: html/Admin/Global/index.html:45 -msgid "Edit system templates" -msgstr "Malkovich Malkovich" - -#: html/Admin/Queues/Modify.html:118 -#. ($QueueObj->Name) -msgid "Editing Configuration for queue %1" -msgstr "Malkovich Malkovich Malkovich %1" - -#: NOT FOUND IN SOURCE -msgid "Editing Configuration for user %1" -msgstr "Malkovich Malkovich Malkovich %1" - -#: html/Admin/Elements/EditCustomField:90 -#. ($CustomFieldObj->Name()) -msgid "Editing CustomField %1" -msgstr "Malkovich Malkovich %1" - -#: html/Admin/Groups/Members.html:31 -#. ($Group->Name) -msgid "Editing membership for group %1" -msgstr "Malkovich Malkovich Malkovich %1" - -#: html/User/Groups/Members.html:128 -#. ($Group->Name) -msgid "Editing membership for personal group %1" -msgstr "Malkovich Malkovich Malkovich Malkovich %1" - -#: lib/RT/Record.pm:1075 lib/RT/Record.pm:1152 -msgid "Either base or target must be specified" -msgstr "Malkovich or Malkovich be Malkovich" - -#: html/Admin/Users/Modify.html:52 html/Elements/SelectUsers:26 html/Ticket/Elements/AddWatchers:55 html/User/Prefs.html:43 -msgid "Email" -msgstr "Malkovich" - -#: lib/RT/User_Overlay.pm:206 -msgid "Email address in use" -msgstr "Malkovich in use" - -#: NOT FOUND IN SOURCE -msgid "EmailAddress" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "EmailEncoding" -msgstr "Malkovich" - -#: html/Admin/Elements/EditCustomField:50 -msgid "Enabled (Unchecking this box disables this custom field)" -msgstr "Malkovich (Malkovich Malkovich Malkovich Malkovich Malkovich)" - -#: html/Admin/Groups/Modify.html:52 html/User/Groups/Modify.html:52 -msgid "Enabled (Unchecking this box disables this group)" -msgstr "Malkovich (Malkovich Malkovich Malkovich Malkovich)" - -#: html/Admin/Queues/Modify.html:83 -msgid "Enabled (Unchecking this box disables this queue)" -msgstr "Malkovich (Malkovich Malkovich Malkovich Malkovich)" - -#: html/Admin/Elements/EditCustomFields:97 -msgid "Enabled Custom Fields" -msgstr "Malkovich Malkovich" - -#: html/Admin/Queues/index.html:55 -msgid "Enabled Queues" -msgstr "Malkovich" - -#: html/Admin/Elements/EditCustomField:106 html/Admin/Groups/Modify.html:116 html/Admin/Queues/Modify.html:140 html/Admin/Users/Modify.html:308 html/User/Groups/Modify.html:116 -#. (loc_fuzzy($msg)) -msgid "Enabled status %1" -msgstr "Malkovich %1" - -#: lib/RT/CustomField_Overlay.pm:433 -msgid "Enter multiple values" -msgstr "Malkovich Malkovich" - -#: lib/RT/CustomField_Overlay.pm:430 -msgid "Enter one value" -msgstr "Malkovich" - -#: html/Search/Bulk.html:142 -msgid "Enter tickets or URIs to link tickets to. Seperate multiple entries with spaces." -msgstr "Malkovich or URIs to Malkovich to. Malkovich Malkovich Malkovich Malkovich." - -#: html/Elements/Login:39 html/SelfService/Error.html:24 html/SelfService/Error.html:25 -msgid "Error" -msgstr "Error" - -#: lib/RT/Queue_Overlay.pm:593 -msgid "Error in parameters to Queue->AddWatcher" -msgstr "Malkovich in Malkovich to Malkovich->Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Error in parameters to Queue->DelWatcher" -msgstr "Malkovich in Malkovich to Malkovich->Malkovich" - -#: lib/RT/Ticket_Overlay.pm:1468 -msgid "Error in parameters to Ticket->AddWatcher" -msgstr "Malkovich in Malkovich to Malkovich->Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Error in parameters to Ticket->DelWatcher" -msgstr "Malkovich in Malkovich to Malkovich->Malkovich" - -#: etc/initialdata:20 -msgid "Everyone" -msgstr "Malkovich" - -#: bin/rt-crontool:190 -msgid "Example:" -msgstr "Malkovich:" - -#: NOT FOUND IN SOURCE -msgid "ExternalAuthId" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "ExternalContactInfoId" -msgstr "Malkovich Malkovich" - -#: html/Admin/Users/Modify.html:72 -msgid "Extra info" -msgstr "Malkovich" - -#: lib/RT/User_Overlay.pm:342 -msgid "Failed to find 'Privileged' users pseudogroup." -msgstr "Malkovich to find 'Malkovich' Malkovich Malkovich." - -#: lib/RT/User_Overlay.pm:349 -msgid "Failed to find 'Unprivileged' users pseudogroup" -msgstr "Malkovich to find 'Malkovich' Malkovich Malkovich" - -#: bin/rt-crontool:134 -#. ($modname, $@) -msgid "Failed to load module %1. (%2)" -msgstr "Malkovich to Malkovich %1. (%2)" - -#: lib/RT/Date.pm:412 -msgid "Feb." -msgstr "Feb." - -#: html/Search/Elements/PickBasics:60 html/Ticket/Create.html:154 html/Ticket/Elements/EditBasics:57 lib/RT/Tickets_Overlay.pm:1153 -msgid "Final Priority" -msgstr "Malkovich" - -#: lib/RT/Ticket_Overlay.pm:1274 -msgid "FinalPriority" -msgstr "Malkovich" - -#: html/Admin/Queues/People.html:60 html/Ticket/Elements/EditPeople:33 -msgid "Find group whose" -msgstr "Malkovich Malkovich" - -#: html/Admin/Queues/People.html:56 html/Admin/Users/index.html:45 html/Ticket/Elements/EditPeople:29 -msgid "Find people whose" -msgstr "Malkovich Malkovich" - -#: html/Search/Results.html:72 -msgid "Find tickets" -msgstr "Malkovich" - -#: html/Ticket/Elements/Tabs:59 -msgid "First" -msgstr "Malkovich" - -#: docs/design_docs/string-extraction-guide.txt:33 lib/RT/StyleGuide.pod:746 -msgid "Foo Bar Baz" -msgstr "Malkovich" - -#: docs/design_docs/string-extraction-guide.txt:24 lib/RT/StyleGuide.pod:737 -msgid "Foo!" -msgstr "Foo!" - -#: html/Search/Bulk.html:84 -msgid "Force change" -msgstr "Malkovich" - -#: html/Search/Results.html:70 -#. ($ticketcount) -msgid "Found %quant(%1,ticket)" -msgstr "Malkovich %quant(%1,Malkovich)" - -#: lib/RT/Record.pm:750 -msgid "Found Object" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "FreeformContactInfo" -msgstr "Malkovich Malkovich" - -#: lib/RT/CustomField_Overlay.pm:37 -msgid "FreeformMultiple" -msgstr "Malkovich Malkovich" - -#: lib/RT/CustomField_Overlay.pm:36 -msgid "FreeformSingle" -msgstr "Malkovich" - -#: lib/RT/Date.pm:392 -msgid "Fri." -msgstr "Fri." - -#: html/Ticket/Elements/ShowHistory:40 html/Ticket/Elements/ShowHistory:50 -msgid "Full headers" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:587 -#. ($New->Name) -msgid "Given to %1" -msgstr "Malkovich to %1" - -#: html/Admin/Elements/Tabs:40 html/Admin/index.html:37 -msgid "Global" -msgstr "Malkovich" - -#: html/Admin/Elements/SelectTemplate:37 -#. (loc($Template->Name)) -msgid "Global template: %1" -msgstr "Malkovich: %1" - -#: html/Tools/Offline.html:69 -msgid "Go" -msgstr "Go" - -#: html/Admin/Elements/EditCustomFields:73 html/Admin/Groups/index.html:39 html/Admin/Queues/People.html:58 html/Admin/Queues/People.html:62 html/Admin/Queues/index.html:43 html/Admin/Users/index.html:48 html/Ticket/Elements/EditPeople:31 html/Ticket/Elements/EditPeople:35 html/index.html:69 -msgid "Go!" -msgstr "Go!" - -#: html/Elements/GotoTicket:24 html/SelfService/Elements/GotoTicket:24 -msgid "Goto ticket" -msgstr "Malkovich" - -#: html/Ticket/Elements/AddWatchers:45 html/Ticket/Elements/ShowGroupMembers:33 html/User/Elements/DelegateRights:77 -msgid "Group" -msgstr "Malkovich" - -#: html/Admin/Elements/GroupTabs:44 html/Admin/Elements/QueueTabs:56 html/Admin/Elements/SystemTabs:43 html/Admin/Global/index.html:54 -msgid "Group Rights" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:957 -msgid "Group already has member" -msgstr "Malkovich Malkovich" - -#: html/Admin/Groups/Modify.html:76 -#. ($create_msg) -msgid "Group could not be created: %1" -msgstr "Malkovich be Malkovich: %1" - -#: lib/RT/Group_Overlay.pm:497 -msgid "Group created" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:1129 -msgid "Group has no such member" -msgstr "Malkovich no Malkovich" - -#: lib/RT/Group_Overlay.pm:937 lib/RT/Queue_Overlay.pm:669 lib/RT/Queue_Overlay.pm:729 lib/RT/Ticket_Overlay.pm:1522 lib/RT/Ticket_Overlay.pm:1602 -msgid "Group not found" -msgstr "Malkovich" - -#: html/Admin/Elements/SelectNewGroupMembers:34 html/Admin/Elements/Tabs:34 html/Admin/Groups/Members.html:63 html/Admin/Queues/People.html:82 html/Admin/index.html:31 html/User/Groups/Members.html:66 -msgid "Groups" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:963 -msgid "Groups can't be members of their members" -msgstr "Malkovich can't be Malkovich of Malkovich" - -#: lib/RT/Interface/CLI.pm:72 lib/RT/Interface/CLI.pm:72 -msgid "Hello!" -msgstr "Malkovich!" - -#: docs/design_docs/string-extraction-guide.txt:40 lib/RT/StyleGuide.pod:753 -#. ($name) -msgid "Hello, %1" -msgstr "Malkovich, %1" - -#: html/Ticket/Elements/ShowHistory:29 html/Ticket/Elements/Tabs:89 -msgid "History" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "HomePhone" -msgstr "Malkovich" - -#: html/Elements/Tabs:43 -msgid "Homepage" -msgstr "Malkovich" - -#: lib/RT/Base.pm:86 -#. (6) -msgid "I have %quant(%1,concrete mixer)." -msgstr "I have %quant(%1,Malkovich)." - -#: html/Search/Elements/PickBasics:104 html/Ticket/Elements/ShowBasics:26 lib/RT/Tickets_Overlay.pm:1080 -msgid "Id" -msgstr "Id" - -#: html/Admin/Users/Modify.html:43 html/User/Prefs.html:38 -msgid "Identity" -msgstr "Malkovich" - -#: etc/initialdata:429 -msgid "If an approval is rejected, reject the original and delete pending approvals" -msgstr "If a Malkovich is Malkovich, Malkovich the Malkovich and Malkovich Malkovich" - -#: bin/rt-crontool:186 -msgid "If this tool were setgid, a hostile local user could use this tool to gain administrative access to RT." -msgstr "If Malkovich Malkovich, a Malkovich Malkovich Malkovich Malkovich to Malkovich Malkovich Malkovich to RT." - -#: html/Admin/Queues/People.html:104 html/Ticket/Modify.html:38 html/Ticket/ModifyAll.html:93 html/Ticket/ModifyPeople.html:37 -msgid "If you've updated anything above, be sure to" -msgstr "If you've Malkovich Malkovich, be sure to" - -#: lib/RT/Record.pm:742 -msgid "Illegal value for %1" -msgstr "Malkovich Malkovich %1" - -#: lib/RT/Record.pm:745 -msgid "Immutable field" -msgstr "Malkovich" - -#: html/Admin/Elements/EditCustomFields:72 -msgid "Include disabled custom fields in listing." -msgstr "Malkovich Malkovich Malkovich in Malkovich." - -#: html/Admin/Queues/index.html:42 -msgid "Include disabled queues in listing." -msgstr "Malkovich Malkovich in Malkovich." - -#: html/Admin/Users/index.html:46 -msgid "Include disabled users in search." -msgstr "Malkovich Malkovich in Malkovich." - -#: html/Search/Elements/PickBasics:59 lib/RT/Tickets_Overlay.pm:1129 -msgid "Initial Priority" -msgstr "Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:1273 lib/RT/Ticket_Overlay.pm:1275 -msgid "InitialPriority" -msgstr "Malkovich" - -#: lib/RT/ScripAction_Overlay.pm:97 -msgid "Input error" -msgstr "Malkovich" - -#: lib/RT/Ticket_Overlay.pm:3797 -msgid "Internal Error" -msgstr "Malkovich" - -#: lib/RT/Record.pm:186 -#. ($id->{error_message}) -msgid "Internal Error: %1" -msgstr "Malkovich: %1" - -#: lib/RT/Group_Overlay.pm:644 -msgid "Invalid Group Type" -msgstr "Malkovich Malkovich" - -#: lib/RT/Principal_Overlay.pm:127 -msgid "Invalid Right" -msgstr "Malkovich" - -#: lib/RT/Record.pm:747 -msgid "Invalid data" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Invalid owner. Defaulting to 'nobody'." -msgstr "Malkovich. Malkovich to 'Malkovich'." - -#: lib/RT/Scrip_Overlay.pm:133 lib/RT/Template_Overlay.pm:251 -msgid "Invalid queue" -msgstr "Malkovich" - -#: lib/RT/ACE_Overlay.pm:243 lib/RT/ACE_Overlay.pm:252 lib/RT/ACE_Overlay.pm:258 lib/RT/ACE_Overlay.pm:269 lib/RT/ACE_Overlay.pm:274 -msgid "Invalid right" -msgstr "Malkovich" - -#: lib/RT/Record.pm:161 -#. ($key) -msgid "Invalid value for %1" -msgstr "Malkovich Malkovich %1" - -#: lib/RT/Ticket_Overlay.pm:3380 -msgid "Invalid value for custom field" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:385 -msgid "Invalid value for status" -msgstr "Malkovich Malkovich" - -#: bin/rt-crontool:187 -msgid "It is incredibly important that nonprivileged users not be allowed to run this tool." -msgstr "It is Malkovich Malkovich Malkovich Malkovich Malkovich be Malkovich to Malkovich." - -#: bin/rt-crontool:188 -msgid "It is suggested that you create a non-privileged unix user with the correct group membership and RT access to run this tool." -msgstr "It is Malkovich Malkovich a non-Malkovich Malkovich the Malkovich Malkovich and RT Malkovich to Malkovich." - -#: bin/rt-crontool:159 -msgid "It takes several arguments:" -msgstr "It Malkovich Malkovich:" - -#: lib/RT/Date.pm:411 -msgid "Jan." -msgstr "Jan." - -#: lib/RT/Group_Overlay.pm:149 -msgid "Join or leave this group" -msgstr "Join or Malkovich Malkovich" - -#: lib/RT/Date.pm:417 -msgid "Jul." -msgstr "Jul." - -#: html/Ticket/Elements/Tabs:100 -msgid "Jumbo" -msgstr "Malkovich" - -#: lib/RT/Date.pm:416 -msgid "Jun." -msgstr "Jun." - -#: NOT FOUND IN SOURCE -msgid "Lang" -msgstr "Lang" - -#: html/User/Prefs.html:54 -msgid "Language" -msgstr "Malkovich" - -#: html/Ticket/Elements/Tabs:74 -msgid "Last" -msgstr "Last" - -#: html/Ticket/Elements/EditDates:37 html/Ticket/Elements/ShowDates:39 -msgid "Last Contact" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Last Contact</a>" -msgstr "Malkovich</a>" - -#: html/Elements/SelectDateType:28 -msgid "Last Contacted" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Last Notified" -msgstr "Malkovich" - -#: html/Elements/SelectDateType:29 -msgid "Last Updated" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:82 -msgid "Let this user access RT" -msgstr "Malkovich Malkovich RT" - -#: html/Admin/Users/Modify.html:86 -msgid "Let this user be granted rights" -msgstr "Malkovich be Malkovich" - -#: lib/RT/Record.pm:1086 -msgid "Link already exists" -msgstr "Malkovich Malkovich" - -#: lib/RT/Record.pm:1100 -msgid "Link could not be created" -msgstr "Malkovich be Malkovich" - -#: lib/RT/Record.pm:1106 -#. ($TransString) -msgid "Link created (%1)" -msgstr "Malkovich (%1)" - -#: lib/RT/Record.pm:1167 -#. ($TransString) -msgid "Link deleted (%1)" -msgstr "Malkovich (%1)" - -#: lib/RT/Record.pm:1173 -msgid "Link not found" -msgstr "Malkovich" - -#: html/Ticket/ModifyLinks.html:24 html/Ticket/ModifyLinks.html:28 -#. ($Ticket->Id) -msgid "Link ticket #%1" -msgstr "Malkovich #%1" - -#: html/Ticket/Create.html:174 html/Ticket/Elements/ShowSummary:61 html/Ticket/Elements/Tabs:98 html/Ticket/ModifyAll.html:56 -msgid "Links" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:111 html/User/Prefs.html:104 -msgid "Location" -msgstr "Malkovich" - -#: lib/RT.pm:184 -#. ($RT::LogDir) -msgid "Log directory %1 not found or couldn't be written.\\n RT can't run." -msgstr "Malkovich %1 Malkovich or couldn't be Malkovich.\\n RT can't run." - -#: html/Elements/Header:69 -#. ("<b>".$session{'CurrentUser'}->Name."</b>") -msgid "Logged in as %1" -msgstr "Malkovich in as %1" - -#: docs/design_docs/string-extraction-guide.txt:71 html/Elements/Login:35 html/Elements/Login:44 html/Elements/Login:54 lib/RT/StyleGuide.pod:777 -msgid "Login" -msgstr "Malkovich" - -#: html/Elements/Header:66 -msgid "Logout" -msgstr "Malkovich" - -#: html/Search/Bulk.html:83 -msgid "Make Owner" -msgstr "Malkovich" - -#: html/Search/Bulk.html:107 -msgid "Make Status" -msgstr "Malkovich" - -#: html/Search/Bulk.html:115 -msgid "Make date Due" -msgstr "Malkovich" - -#: html/Search/Bulk.html:117 -msgid "Make date Resolved" -msgstr "Malkovich Malkovich" - -#: html/Search/Bulk.html:111 -msgid "Make date Started" -msgstr "Malkovich Malkovich" - -#: html/Search/Bulk.html:109 -msgid "Make date Starts" -msgstr "Malkovich Malkovich" - -#: html/Search/Bulk.html:113 -msgid "Make date Told" -msgstr "Malkovich" - -#: html/Search/Bulk.html:103 -msgid "Make priority" -msgstr "Malkovich" - -#: html/Search/Bulk.html:105 -msgid "Make queue" -msgstr "Malkovich" - -#: html/Search/Bulk.html:101 -msgid "Make subject" -msgstr "Malkovich" - -#: html/Admin/index.html:32 -msgid "Manage groups and group membership" -msgstr "Malkovich and Malkovich Malkovich" - -#: html/Admin/index.html:38 -msgid "Manage properties and configuration which apply to all queues" -msgstr "Malkovich Malkovich and Malkovich Malkovich to Malkovich" - -#: html/Admin/index.html:35 -msgid "Manage queues and queue-specific properties" -msgstr "Malkovich and Malkovich-Malkovich Malkovich" - -#: html/Admin/index.html:29 -msgid "Manage users and passwords" -msgstr "Malkovich and Malkovich" - -#: lib/RT/Date.pm:413 -msgid "Mar." -msgstr "Mar." - -#: lib/RT/Date.pm:415 -msgid "May." -msgstr "May." - -#: lib/RT/Transaction_Overlay.pm:634 -#. ($value) -msgid "Member %1 added" -msgstr "Malkovich %1 Malkovich" - -#: lib/RT/Transaction_Overlay.pm:674 -#. ($value) -msgid "Member %1 deleted" -msgstr "Malkovich %1 Malkovich" - -#: lib/RT/Group_Overlay.pm:974 -msgid "Member added" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:1136 -msgid "Member deleted" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:1140 -msgid "Member not deleted" -msgstr "Malkovich Malkovich" - -#: html/Elements/SelectLinkType:25 -msgid "Member of" -msgstr "Malkovich of" - -#: html/Admin/Elements/GroupTabs:41 html/User/Elements/GroupTabs:41 -msgid "Members" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:631 -#. ($value) -msgid "Membership in %1 added" -msgstr "Malkovich in %1 Malkovich" - -#: lib/RT/Transaction_Overlay.pm:671 -#. ($value) -msgid "Membership in %1 deleted" -msgstr "Malkovich in %1 Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2813 -msgid "Merge Successful" -msgstr "Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2733 -msgid "Merge failed. Couldn't set EffectiveId" -msgstr "Malkovich. Couldn't Malkovich" - -#: html/Elements/EditLinks:104 html/Ticket/Elements/BulkLinks:26 -msgid "Merge into" -msgstr "Malkovich" - -#: html/Search/Bulk.html:135 html/Ticket/Update.html:83 -msgid "Message" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Message body not shown because it is too large or is not plain text." -msgstr "Malkovich Malkovich Malkovich it is Malkovich or is Malkovich." - -#: lib/RT/Ticket_Overlay.pm:2514 -msgid "Message could not be recorded" -msgstr "Malkovich Malkovich be Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Message recipients" -msgstr "Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2517 -msgid "Message recorded" -msgstr "Malkovich Malkovich" - -#: lib/RT/Record.pm:749 -msgid "Missing a primary key?: %1" -msgstr "Malkovich a Malkovich?: %1" - -#: html/Admin/Users/Modify.html:166 html/User/Prefs.html:71 -msgid "Mobile" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "MobilePhone" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:71 -msgid "Modify Access Control List" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Admin/Global/CustomFields.html:43 html/Admin/Global/index.html:50 -msgid "Modify Custom Fields which apply to all queues" -msgstr "Malkovich Malkovich Malkovich to Malkovich" - -#: lib/RT/Queue_Overlay.pm:74 -msgid "Modify Scrip templates for this queue" -msgstr "Malkovich Malkovich Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:77 -msgid "Modify Scrips for this queue" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Admin/Queues/CustomField.html:44 -#. ($QueueObj->Name()) -msgid "Modify a CustomField for queue %1" -msgstr "Malkovich a Malkovich Malkovich %1" - -#: html/Admin/Global/CustomField.html:52 -msgid "Modify a CustomField which applies to all queues" -msgstr "Malkovich a Malkovich Malkovich to Malkovich" - -#: html/Admin/Queues/Scrip.html:53 -#. ($QueueObj->Name) -msgid "Modify a scrip for queue %1" -msgstr "Malkovich a Malkovich %1" - -#: html/Admin/Global/Scrip.html:47 -msgid "Modify a scrip which applies to all queues" -msgstr "Malkovich a Malkovich Malkovich to Malkovich" - -#: html/Ticket/ModifyDates.html:24 html/Ticket/ModifyDates.html:28 -#. ($TicketObj->Id) -msgid "Modify dates for #%1" -msgstr "Malkovich Malkovich #%1" - -#: html/Ticket/ModifyDates.html:34 -#. ($TicketObj->Id) -msgid "Modify dates for ticket # %1" -msgstr "Malkovich Malkovich # %1" - -#: html/Admin/Global/GroupRights.html:24 html/Admin/Global/GroupRights.html:27 html/Admin/Global/index.html:55 -msgid "Modify global group rights" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Admin/Global/GroupRights.html:32 -msgid "Modify global group rights." -msgstr "Malkovich Malkovich Malkovich." - -#: html/Admin/Global/UserRights.html:24 html/Admin/Global/UserRights.html:27 html/Admin/Global/index.html:59 -msgid "Modify global user rights" -msgstr "Malkovich Malkovich" - -#: html/Admin/Global/UserRights.html:32 -msgid "Modify global user rights." -msgstr "Malkovich Malkovich." - -#: lib/RT/Group_Overlay.pm:146 -msgid "Modify group metadata or delete group" -msgstr "Malkovich Malkovich or Malkovich" - -#: html/Admin/Groups/GroupRights.html:24 html/Admin/Groups/GroupRights.html:28 html/Admin/Groups/GroupRights.html:34 -#. ($GroupObj->Name) -msgid "Modify group rights for group %1" -msgstr "Malkovich Malkovich Malkovich %1" - -#: html/Admin/Queues/GroupRights.html:24 html/Admin/Queues/GroupRights.html:28 -#. ($QueueObj->Name) -msgid "Modify group rights for queue %1" -msgstr "Malkovich Malkovich Malkovich %1" - -#: lib/RT/Group_Overlay.pm:148 -msgid "Modify membership roster for this group" -msgstr "Malkovich Malkovich Malkovich Malkovich" - -#: lib/RT/System.pm:60 -msgid "Modify one's own RT account" -msgstr "Malkovich's own RT Malkovich" - -#: html/Admin/Queues/People.html:24 html/Admin/Queues/People.html:28 -#. ($QueueObj->Name) -msgid "Modify people related to queue %1" -msgstr "Malkovich Malkovich to Malkovich %1" - -#: html/Ticket/ModifyPeople.html:24 html/Ticket/ModifyPeople.html:28 html/Ticket/ModifyPeople.html:34 -#. ($Ticket->id) -#. ($Ticket->Id) -msgid "Modify people related to ticket #%1" -msgstr "Malkovich Malkovich to Malkovich #%1" - -#: html/Admin/Queues/Scrips.html:45 -#. ($QueueObj->Name) -msgid "Modify scrips for queue %1" -msgstr "Malkovich Malkovich %1" - -#: html/Admin/Global/Scrips.html:43 html/Admin/Global/index.html:41 -msgid "Modify scrips which apply to all queues" -msgstr "Malkovich Malkovich to Malkovich" - -#: html/Admin/Global/Template.html:24 html/Admin/Global/Template.html:29 html/Admin/Global/Template.html:80 html/Admin/Queues/Template.html:77 -#. (loc($TemplateObj->Name())) -#. ($TemplateObj->id) -msgid "Modify template %1" -msgstr "Malkovich %1" - -#: html/Admin/Global/Templates.html:43 -msgid "Modify templates which apply to all queues" -msgstr "Malkovich Malkovich Malkovich to Malkovich" - -#: html/Admin/Groups/Modify.html:86 html/User/Groups/Modify.html:85 -#. ($Group->Name) -msgid "Modify the group %1" -msgstr "Malkovich the Malkovich %1" - -#: lib/RT/Queue_Overlay.pm:72 -msgid "Modify the queue watchers" -msgstr "Malkovich the Malkovich" - -#: html/Admin/Users/Modify.html:263 -#. ($UserObj->Name) -msgid "Modify the user %1" -msgstr "Malkovich the user %1" - -#: html/Ticket/ModifyAll.html:36 -#. ($Ticket->Id) -msgid "Modify ticket # %1" -msgstr "Malkovich # %1" - -#: html/Ticket/Modify.html:24 html/Ticket/Modify.html:27 html/Ticket/Modify.html:33 -#. ($TicketObj->Id) -msgid "Modify ticket #%1" -msgstr "Malkovich #%1" - -#: lib/RT/Queue_Overlay.pm:90 -msgid "Modify tickets" -msgstr "Malkovich" - -#: html/Admin/Groups/UserRights.html:24 html/Admin/Groups/UserRights.html:28 html/Admin/Groups/UserRights.html:34 -#. ($GroupObj->Name) -msgid "Modify user rights for group %1" -msgstr "Malkovich Malkovich Malkovich %1" - -#: html/Admin/Queues/UserRights.html:24 html/Admin/Queues/UserRights.html:28 -#. ($QueueObj->Name) -msgid "Modify user rights for queue %1" -msgstr "Malkovich Malkovich Malkovich %1" - -#: lib/RT/Queue_Overlay.pm:71 -msgid "ModifyACL" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:149 -msgid "ModifyOwnMembership" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:72 -msgid "ModifyQueueWatchers" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:77 -msgid "ModifyScrips" -msgstr "Malkovich" - -#: lib/RT/System.pm:60 -msgid "ModifySelf" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:74 -msgid "ModifyTemplate" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:90 -msgid "ModifyTicket" -msgstr "Malkovich" - -#: lib/RT/Date.pm:388 -msgid "Mon." -msgstr "Mon." - -#: html/Ticket/Elements/ShowRequestor:40 -#. ($name) -msgid "More about %1" -msgstr "Malkovich %1" - -#: html/Admin/Elements/EditCustomFields:60 -msgid "Move down" -msgstr "Malkovich" - -#: html/Admin/Elements/SelectSingleOrMultiple:26 -msgid "Multiple" -msgstr "Malkovich" - -#: lib/RT/User_Overlay.pm:197 -msgid "Must specify 'Name' attribute" -msgstr "Malkovich 'Name' Malkovich" - -#: html/SelfService/Elements/MyRequests:48 -#. ($friendly_status) -msgid "My %1 tickets" -msgstr "My %1 Malkovich" - -#: html/Approvals/index.html:24 html/Approvals/index.html:25 -msgid "My approvals" -msgstr "My Malkovich" - -#: html/Admin/Elements/AddCustomFieldValue:31 html/Admin/Elements/EditCustomField:33 html/Admin/Elements/ModifyTemplate:27 html/Admin/Groups/Modify.html:43 html/Elements/SelectGroups:25 html/Elements/SelectUsers:27 html/User/Groups/Modify.html:43 -msgid "Name" -msgstr "Name" - -#: lib/RT/User_Overlay.pm:204 -msgid "Name in use" -msgstr "Name in use" - -#: html/Ticket/Elements/ShowDates:52 -msgid "Never" -msgstr "Malkovich" - -#: html/Elements/Quicksearch:29 -msgid "New" -msgstr "New" - -#: html/Elements/EditLinks:93 -msgid "New Links" -msgstr "Malkovich Malkovich" - -#: html/Admin/Users/Modify.html:92 html/User/Prefs.html:87 -msgid "New Password" -msgstr "Malkovich" - -#: etc/initialdata:332 -msgid "New Pending Approval" -msgstr "Malkovich Malkovich" - -#: NOT FOUND IN SOURCE -msgid "New Search" -msgstr "Malkovich" - -#: html/Admin/Global/CustomField.html:40 html/Admin/Global/CustomFields.html:38 html/Admin/Queues/CustomField.html:51 html/Admin/Queues/CustomFields.html:40 -msgid "New custom field" -msgstr "Malkovich Malkovich" - -#: html/Admin/Elements/GroupTabs:53 html/User/Elements/GroupTabs:51 -msgid "New group" -msgstr "Malkovich" - -#: html/SelfService/Prefs.html:31 -msgid "New password" -msgstr "Malkovich" - -#: lib/RT/User_Overlay.pm:773 -msgid "New password notification sent" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Admin/Elements/QueueTabs:69 -msgid "New queue" -msgstr "Malkovich" - -#: html/Admin/Elements/SelectRights:41 -msgid "New rights" -msgstr "Malkovich" - -#: html/Admin/Global/Scrip.html:39 html/Admin/Global/Scrips.html:38 html/Admin/Queues/Scrip.html:42 html/Admin/Queues/Scrips.html:54 -msgid "New scrip" -msgstr "Malkovich" - -#: html/Admin/Global/Template.html:59 html/Admin/Global/Templates.html:38 html/Admin/Queues/Template.html:57 html/Admin/Queues/Templates.html:49 -msgid "New template" -msgstr "Malkovich" - -#: html/SelfService/Elements/Tabs:47 -msgid "New ticket" -msgstr "Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2700 -msgid "New ticket doesn't exist" -msgstr "Malkovich doesn't Malkovich" - -#: html/Admin/Elements/UserTabs:50 -msgid "New user" -msgstr "Malkovich" - -#: html/Admin/Elements/CreateUserCalled:25 -msgid "New user called" -msgstr "Malkovich" - -#: html/Admin/Queues/People.html:54 html/Ticket/Elements/EditPeople:28 -msgid "New watchers" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "New window setting" -msgstr "Malkovich Malkovich" - -#: html/Ticket/Elements/Tabs:70 -msgid "Next" -msgstr "Next" - -#: NOT FOUND IN SOURCE -msgid "NickName" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:62 html/User/Prefs.html:50 -msgid "Nickname" -msgstr "Malkovich" - -#: html/Admin/Elements/EditCustomField:89 html/Admin/Elements/EditCustomFields:103 -msgid "No CustomField" -msgstr "No Malkovich" - -#: html/Admin/Groups/GroupRights.html:83 html/Admin/Groups/UserRights.html:70 -msgid "No Group defined" -msgstr "No Malkovich" - -#: lib/RT/Tickets_Overlay_SQL.pm:452 -msgid "No Query" -msgstr "No Malkovich" - -#: html/Admin/Queues/GroupRights.html:96 html/Admin/Queues/UserRights.html:67 -msgid "No Queue defined" -msgstr "No Malkovich" - -#: bin/rt-crontool:52 -msgid "No RT user found. Please consult your RT administrator.\\n" -msgstr "No RT Malkovich. Malkovich Malkovich RT Malkovich.\\n" - -#: html/Admin/Global/Template.html:78 html/Admin/Queues/Template.html:75 -msgid "No Template" -msgstr "No Malkovich" - -#: NOT FOUND IN SOURCE -msgid "No Ticket specified. Aborting ticket " -msgstr "No Malkovich Malkovich. Malkovich " - -#: html/Approvals/Elements/Approve:45 -msgid "No action" -msgstr "No Malkovich" - -#: lib/RT/Record.pm:744 -msgid "No column specified" -msgstr "No Malkovich Malkovich" - -#: html/Ticket/Elements/ShowRequestor:46 -msgid "No comment entered about this user" -msgstr "No Malkovich Malkovich Malkovich" - -#: lib/RT/Action/Generic.pm:159 lib/RT/Condition/Generic.pm:175 lib/RT/Search/ActiveTicketsInQueue.pm:55 lib/RT/Search/Generic.pm:112 -#. (ref $self) -msgid "No description for %1" -msgstr "No Malkovich %1" - -#: lib/RT/Users_Overlay.pm:159 -msgid "No group specified" -msgstr "No Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2475 -msgid "No message attached" -msgstr "No Malkovich Malkovich" - -#: lib/RT/User_Overlay.pm:991 -msgid "No password set" -msgstr "No Malkovich" - -#: lib/RT/Queue_Overlay.pm:296 -msgid "No permission to create queues" -msgstr "No Malkovich to Malkovich" - -#: NOT FOUND IN SOURCE -msgid "No permission to create tickets in the queue '%1'" -msgstr "No Malkovich to Malkovich in the Malkovich '%1'" - -#: lib/RT/User_Overlay.pm:157 -msgid "No permission to create users" -msgstr "No Malkovich to Malkovich" - -#: html/SelfService/Display.html:125 -msgid "No permission to display that ticket" -msgstr "No Malkovich to Malkovich Malkovich" - -#: html/SelfService/Update.html:68 -msgid "No permission to view update ticket" -msgstr "No Malkovich to Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:716 lib/RT/Ticket_Overlay.pm:1581 -msgid "No principal specified" -msgstr "No Malkovich Malkovich" - -#: html/Admin/Queues/People.html:153 html/Admin/Queues/People.html:163 -msgid "No principals selected." -msgstr "No Malkovich Malkovich." - -#: html/Admin/Queues/index.html:34 -msgid "No queues matching search criteria found." -msgstr "No Malkovich Malkovich Malkovich Malkovich." - -#: html/Admin/Elements/SelectRights:81 -msgid "No rights found" -msgstr "No Malkovich" - -#: html/Admin/Elements/SelectRights:32 -msgid "No rights granted." -msgstr "No Malkovich." - -#: html/Search/Bulk.html:162 -msgid "No search to operate on." -msgstr "No Malkovich to Malkovich on." - -#: lib/RT/Transaction_Overlay.pm:455 lib/RT/Transaction_Overlay.pm:493 -msgid "No transaction type specified" -msgstr "No Malkovich Malkovich Malkovich" - -#: html/Admin/Users/index.html:35 -msgid "No users matching search criteria found." -msgstr "No Malkovich Malkovich Malkovich Malkovich." - -#: NOT FOUND IN SOURCE -msgid "No valid RT user found. RT cvs handler disengaged. Please consult your RT administrator.\\n" -msgstr "No Malkovich RT Malkovich. RT Malkovich Malkovich. Malkovich Malkovich RT Malkovich.\\n" - -#: lib/RT/Record.pm:741 -msgid "No value sent to _Set!\\n" -msgstr "No Malkovich to _Set!\\n" - -#: lib/RT/Record.pm:746 -msgid "Nonexistant field?" -msgstr "Malkovich Malkovich?" - -#: html/Elements/Header:71 -msgid "Not logged in." -msgstr "Malkovich in." - -#: lib/RT/Date.pm:369 -msgid "Not set" -msgstr "Malkovich" - -#: html/NoAuth/Reminder.html:26 -msgid "Not yet implemented." -msgstr "Malkovich Malkovich." - -#: html/Approvals/Elements/Approve:48 -msgid "Notes" -msgstr "Malkovich" - -#: lib/RT/User_Overlay.pm:776 -msgid "Notification could not be sent" -msgstr "Malkovich Malkovich be sent" - -#: etc/initialdata:101 -msgid "Notify AdminCcs" -msgstr "Malkovich" - -#: etc/initialdata:97 -msgid "Notify AdminCcs as Comment" -msgstr "Malkovich as Malkovich" - -#: etc/initialdata:128 -msgid "Notify Other Recipients" -msgstr "Malkovich Malkovich" - -#: etc/initialdata:124 -msgid "Notify Other Recipients as Comment" -msgstr "Malkovich Malkovich as Malkovich" - -#: etc/initialdata:85 -msgid "Notify Owner" -msgstr "Malkovich" - -#: etc/initialdata:81 -msgid "Notify Owner as Comment" -msgstr "Malkovich as Malkovich" - -#: etc/initialdata:376 -msgid "Notify Owner of their rejected ticket" -msgstr "Malkovich of Malkovich Malkovich" - -#: etc/initialdata:365 -msgid "Notify Owner of their ticket has been approved by all approvers" -msgstr "Malkovich of Malkovich Malkovich Malkovich by Malkovich" - -#: etc/initialdata:353 -msgid "Notify Owner of their ticket has been approved by some approver" -msgstr "Malkovich of Malkovich Malkovich Malkovich by Malkovich" - -#: etc/initialdata:334 -msgid "Notify Owners and AdminCcs of new items pending their approval" -msgstr "Malkovich and Malkovich of Malkovich Malkovich Malkovich" - -#: etc/initialdata:77 -msgid "Notify Requestors" -msgstr "Malkovich Malkovich" - -#: etc/initialdata:111 -msgid "Notify Requestors and Ccs" -msgstr "Malkovich Malkovich and Ccs" - -#: etc/initialdata:106 -msgid "Notify Requestors and Ccs as Comment" -msgstr "Malkovich Malkovich and Ccs as Malkovich" - -#: etc/initialdata:120 -msgid "Notify Requestors, Ccs and AdminCcs" -msgstr "Malkovich Malkovich, Ccs and Malkovich" - -#: etc/initialdata:116 -msgid "Notify Requestors, Ccs and AdminCcs as Comment" -msgstr "Malkovich Malkovich, Ccs and Malkovich as Malkovich" - -#: lib/RT/Date.pm:421 -msgid "Nov." -msgstr "Nov." - -#: lib/RT/Record.pm:200 -msgid "Object could not be created" -msgstr "Malkovich Malkovich be Malkovich" - -#: lib/RT/Record.pm:219 -msgid "Object created" -msgstr "Malkovich" - -#: lib/RT/Date.pm:420 -msgid "Oct." -msgstr "Oct." - -#: html/Elements/SelectDateRelation:34 -msgid "On" -msgstr "On" - -#: etc/initialdata:163 -msgid "On Comment" -msgstr "On Malkovich" - -#: etc/initialdata:156 -msgid "On Correspond" -msgstr "On Malkovich" - -#: etc/initialdata:145 -msgid "On Create" -msgstr "On Malkovich" - -#: etc/initialdata:184 -msgid "On Owner Change" -msgstr "On Malkovich" - -#: etc/initialdata:192 -msgid "On Queue Change" -msgstr "On Malkovich" - -#: etc/initialdata:198 -msgid "On Resolve" -msgstr "On Malkovich" - -#: etc/initialdata:169 -msgid "On Status Change" -msgstr "On Malkovich" - -#: etc/initialdata:150 -msgid "On Transaction" -msgstr "On Malkovich" - -#: html/Approvals/Elements/PendingMyApproval:49 -#. ("<input size='15' value='".( $created_after->Unix >0 && $created_after->ISO)."' name='CreatedAfter'>") -msgid "Only show approvals for requests created after %1" -msgstr "Malkovich Malkovich Malkovich Malkovich Malkovich %1" - -#: html/Approvals/Elements/PendingMyApproval:47 -#. ("<input size='15' value='".($created_before->Unix > 0 &&$created_before->ISO)."' name='CreatedBefore'>") -msgid "Only show approvals for requests created before %1" -msgstr "Malkovich Malkovich Malkovich Malkovich Malkovich %1" - -#: html/Elements/Quicksearch:30 -msgid "Open" -msgstr "Open" - -#: html/Ticket/Elements/Tabs:137 -msgid "Open it" -msgstr "Open it" - -#: html/SelfService/Elements/Tabs:41 -msgid "Open tickets" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Open tickets (from listing) in a new window" -msgstr "Malkovich (Malkovich) in a Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Open tickets (from listing) in another window" -msgstr "Malkovich (Malkovich) in Malkovich" - -#: etc/initialdata:140 -msgid "Open tickets on correspondence" -msgstr "Malkovich on Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Ordering and sorting" -msgstr "Malkovich and Malkovich" - -#: html/Admin/Users/Modify.html:114 html/Elements/SelectUsers:28 html/User/Prefs.html:107 -msgid "Organization" -msgstr "Malkovich" - -#: html/Approvals/Elements/Approve:32 -#. ($approving->Id, $approving->Subject) -msgid "Originating ticket: #%1" -msgstr "Malkovich Malkovich: #%1" - -#: html/Admin/Queues/Modify.html:68 -msgid "Over time, priority moves toward" -msgstr "Malkovich, Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:89 -msgid "Own tickets" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:89 -msgid "OwnTicket" -msgstr "Malkovich" - -#: etc/initialdata:38 html/Elements/QuickCreate:13 html/Search/Elements/PickBasics:114 html/SelfService/Elements/MyRequests:29 html/Ticket/Create.html:47 html/Ticket/Elements/EditPeople:42 html/Ticket/Elements/EditPeople:43 html/Ticket/Elements/ShowPeople:26 html/Ticket/Update.html:40 lib/RT/ACE_Overlay.pm:85 lib/RT/Tickets_Overlay.pm:1306 -msgid "Owner" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:575 -#. ($Old->Name , $New->Name) -msgid "Owner forcibly changed from %1 to %2" -msgstr "Malkovich Malkovich Malkovich %1 to %2" - -#: NOT FOUND IN SOURCE -msgid "Owner is" -msgstr "Malkovich is" - -#: html/Admin/Users/Modify.html:171 html/User/Prefs.html:75 -msgid "Pager" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "PagerPhone" -msgstr "Malkovich" - -#: html/Elements/EditLinks:117 html/Elements/EditLinks:54 html/Elements/ShowLinks:46 html/Ticket/Create.html:182 html/Ticket/Elements/BulkLinks:38 -msgid "Parents" -msgstr "Malkovich" - -#: html/Elements/Login:52 html/User/Prefs.html:83 -msgid "Password" -msgstr "Malkovich" - -#: html/NoAuth/Reminder.html:24 -msgid "Password Reminder" -msgstr "Malkovich Malkovich" - -#: lib/RT/User_Overlay.pm:185 lib/RT/User_Overlay.pm:994 -msgid "Password too short" -msgstr "Malkovich Malkovich" - -#: html/Admin/Users/Modify.html:316 html/User/Prefs.html:209 -#. (loc_fuzzy($msg)) -msgid "Password: %1" -msgstr "Malkovich: %1" - -#: html/Admin/Users/Modify.html:318 -msgid "Passwords do not match." -msgstr "Malkovich do Malkovich." - -#: html/User/Prefs.html:211 -msgid "Passwords do not match. Your password has not been changed" -msgstr "Malkovich do Malkovich. Malkovich Malkovich Malkovich" - -#: html/Ticket/Elements/ShowSummary:44 html/Ticket/Elements/Tabs:97 html/Ticket/ModifyAll.html:50 -msgid "People" -msgstr "Malkovich" - -#: etc/initialdata:133 -msgid "Perform a user-defined action" -msgstr "Malkovich a user-Malkovich" - -#: lib/RT/ACE_Overlay.pm:230 lib/RT/ACE_Overlay.pm:236 lib/RT/ACE_Overlay.pm:562 lib/RT/ACE_Overlay.pm:572 lib/RT/ACE_Overlay.pm:582 lib/RT/ACE_Overlay.pm:647 lib/RT/Attribute_Overlay.pm:135 lib/RT/Attribute_Overlay.pm:141 lib/RT/Attribute_Overlay.pm:379 lib/RT/Attribute_Overlay.pm:388 lib/RT/Attribute_Overlay.pm:401 lib/RT/CurrentUser.pm:103 lib/RT/CurrentUser.pm:94 lib/RT/CustomField_Overlay.pm:100 lib/RT/CustomField_Overlay.pm:207 lib/RT/CustomField_Overlay.pm:239 lib/RT/CustomField_Overlay.pm:517 lib/RT/CustomField_Overlay.pm:90 lib/RT/Group_Overlay.pm:1091 lib/RT/Group_Overlay.pm:1095 lib/RT/Group_Overlay.pm:1104 lib/RT/Group_Overlay.pm:1155 lib/RT/Group_Overlay.pm:1159 lib/RT/Group_Overlay.pm:1165 lib/RT/Group_Overlay.pm:426 lib/RT/Group_Overlay.pm:518 lib/RT/Group_Overlay.pm:596 lib/RT/Group_Overlay.pm:604 lib/RT/Group_Overlay.pm:701 lib/RT/Group_Overlay.pm:705 lib/RT/Group_Overlay.pm:711 lib/RT/Group_Overlay.pm:896 lib/RT/Group_Overlay.pm:900 lib/RT/Group_Overlay.pm:913 lib/RT/Queue_Overlay.pm:117 lib/RT/Queue_Overlay.pm:135 lib/RT/Queue_Overlay.pm:578 lib/RT/Queue_Overlay.pm:588 lib/RT/Queue_Overlay.pm:602 lib/RT/Queue_Overlay.pm:740 lib/RT/Queue_Overlay.pm:749 lib/RT/Queue_Overlay.pm:762 lib/RT/Queue_Overlay.pm:975 lib/RT/Scrip_Overlay.pm:125 lib/RT/Scrip_Overlay.pm:136 lib/RT/Scrip_Overlay.pm:201 lib/RT/Scrip_Overlay.pm:473 lib/RT/Template_Overlay.pm:284 lib/RT/Template_Overlay.pm:87 lib/RT/Template_Overlay.pm:93 lib/RT/Ticket_Overlay.pm:1453 lib/RT/Ticket_Overlay.pm:1463 lib/RT/Ticket_Overlay.pm:1477 lib/RT/Ticket_Overlay.pm:1614 lib/RT/Ticket_Overlay.pm:1624 lib/RT/Ticket_Overlay.pm:1638 lib/RT/Ticket_Overlay.pm:1755 lib/RT/Ticket_Overlay.pm:2075 lib/RT/Ticket_Overlay.pm:2213 lib/RT/Ticket_Overlay.pm:2381 lib/RT/Ticket_Overlay.pm:2428 lib/RT/Ticket_Overlay.pm:2582 lib/RT/Ticket_Overlay.pm:2640 lib/RT/Ticket_Overlay.pm:2691 lib/RT/Ticket_Overlay.pm:2706 lib/RT/Ticket_Overlay.pm:2905 lib/RT/Ticket_Overlay.pm:2915 lib/RT/Ticket_Overlay.pm:2920 lib/RT/Ticket_Overlay.pm:3143 lib/RT/Ticket_Overlay.pm:3147 lib/RT/Ticket_Overlay.pm:3350 lib/RT/Ticket_Overlay.pm:3512 lib/RT/Ticket_Overlay.pm:3564 lib/RT/Ticket_Overlay.pm:3791 lib/RT/Transaction_Overlay.pm:443 lib/RT/Transaction_Overlay.pm:450 lib/RT/Transaction_Overlay.pm:479 lib/RT/Transaction_Overlay.pm:486 lib/RT/User_Overlay.pm:1088 lib/RT/User_Overlay.pm:1536 lib/RT/User_Overlay.pm:335 lib/RT/User_Overlay.pm:696 lib/RT/User_Overlay.pm:731 lib/RT/User_Overlay.pm:987 -msgid "Permission Denied" -msgstr "Malkovich Malkovich" - -#: html/User/Elements/Tabs:34 -msgid "Personal Groups" -msgstr "Malkovich" - -#: html/User/Groups/index.html:29 html/User/Groups/index.html:39 -msgid "Personal groups" -msgstr "Malkovich" - -#: html/User/Elements/DelegateRights:36 -msgid "Personal groups:" -msgstr "Malkovich:" - -#: html/Admin/Users/Modify.html:153 html/User/Prefs.html:60 -msgid "Phone numbers" -msgstr "Malkovich" - -#: html/Elements/Header:63 html/Elements/Tabs:55 html/SelfService/Elements/Tabs:50 html/SelfService/Prefs.html:24 html/User/Prefs.html:24 html/User/Prefs.html:27 -msgid "Preferences" -msgstr "Malkovich" - -#: lib/RT/Action/Generic.pm:169 -msgid "Prepare Stubbed" -msgstr "Malkovich" - -#: html/Ticket/Elements/Tabs:62 -msgid "Prev" -msgstr "Prev" - -#: lib/RT/ACE_Overlay.pm:132 lib/RT/ACE_Overlay.pm:207 lib/RT/ACE_Overlay.pm:551 -#. ($args{'PrincipalId'}) -msgid "Principal %1 not found." -msgstr "Malkovich %1 Malkovich." - -#: html/Search/Elements/PickBasics:58 html/Ticket/Create.html:153 html/Ticket/Elements/EditBasics:52 html/Ticket/Elements/ShowBasics:50 lib/RT/Tickets_Overlay.pm:1104 -msgid "Priority" -msgstr "Malkovich" - -#: html/Admin/Queues/Modify.html:64 -msgid "Priority starts at" -msgstr "Malkovich at" - -#: etc/initialdata:25 -msgid "Privileged" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:296 html/User/Prefs.html:200 -#. (loc_fuzzy($msg)) -msgid "Privileged status: %1" -msgstr "Malkovich Malkovich: %1" - -#: html/Admin/Users/index.html:61 -msgid "Privileged users" -msgstr "Malkovich Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Projects" -msgstr "Malkovich" - -#: etc/initialdata:23 etc/initialdata:29 etc/initialdata:35 etc/initialdata:59 -msgid "Pseudogroup for internal use" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Elements/QuickCreate:10 html/Elements/Quicksearch:28 html/Search/Elements/PickBasics:94 html/SelfService/Create.html:32 html/Ticket/Create.html:37 html/Ticket/Elements/EditBasics:35 html/Ticket/Elements/ShowBasics:54 html/User/Elements/DelegateRights:79 lib/RT/Tickets_Overlay.pm:945 -msgid "Queue" -msgstr "Malkovich" - -#: html/Admin/Queues/CustomField.html:41 html/Admin/Queues/Scrip.html:49 html/Admin/Queues/Scrips.html:47 html/Admin/Queues/Templates.html:43 -#. ($Queue) -#. ($id) -msgid "Queue %1 not found" -msgstr "Malkovich %1 Malkovich" - -#: html/Admin/Queues/Modify.html:42 -msgid "Queue Name" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:300 -msgid "Queue already exists" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:309 lib/RT/Queue_Overlay.pm:315 -msgid "Queue could not be created" -msgstr "Malkovich not be Malkovich" - -#: html/Ticket/Create.html:208 -msgid "Queue could not be loaded." -msgstr "Malkovich be Malkovich." - -#: docs/design_docs/string-extraction-guide.txt:83 lib/RT/Queue_Overlay.pm:319 lib/RT/StyleGuide.pod:789 -msgid "Queue created" -msgstr "Malkovich" - -#: html/SelfService/Display.html:72 lib/RT/CustomField_Overlay.pm:97 -msgid "Queue not found" -msgstr "Malkovich" - -#: html/Admin/Elements/Tabs:37 html/Admin/index.html:34 -msgid "Queues" -msgstr "Malkovich" - -#: html/Elements/Quicksearch:24 -msgid "Quick search" -msgstr "Malkovich" - -#: html/Elements/Login:44 -#. ($RT::VERSION) -msgid "RT %1" -msgstr "RT %1" - -#: docs/design_docs/string-extraction-guide.txt:70 lib/RT/StyleGuide.pod:776 -#. ($RT::VERSION, $RT::rtname) -msgid "RT %1 for %2" -msgstr "RT %1 for %2" - -#: NOT FOUND IN SOURCE -msgid "RT %1 from <a href=\"http://bestpractical.com\">Best Practical Solutions, LLC</a>." -msgstr "RT %1 from <a href=\"http://Malkovich.com\">Malkovich Malkovich, LLC</a>." - -#: html/Admin/index.html:24 html/Admin/index.html:25 -msgid "RT Administration" -msgstr "RT Malkovich" - -#: html/Elements/Error:41 html/SelfService/Error.html:40 -msgid "RT Error" -msgstr "RT Malkovich" - -#: html/index.html:50 html/index.html:53 -msgid "RT at a glance" -msgstr "RT at a Malkovich" - -#: html/Elements/PageLayout:85 -#. ($RT::rtname) -msgid "RT for %1" -msgstr "RT for %1" - -#: NOT FOUND IN SOURCE -msgid "RT is © Copyright 1996-%1 Jesse Vincent <jesse@bestpractical.com>. It is distributed under <a href=\"http://www.gnu.org/copyleft/gpl.html\">Version 2 of the GNU General Public License.</a>" -msgstr "RT is © Malkovich 1996-%1 Malkovich <Malkovich@Malkovich.com>. It is Malkovich Malkovich <a href=\"http://www.gnu.org/copyleft/gpl.html\">Malkovich 2 of the Malkovich Malkovich Malkovich.</a>" - -#: html/Admin/Users/Modify.html:57 html/User/Prefs.html:47 -msgid "Real Name" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "RealName" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:628 -#. ($value) -msgid "Reference by %1 added" -msgstr "Malkovich by %1 Malkovich" - -#: lib/RT/Transaction_Overlay.pm:668 -#. ($value) -msgid "Reference by %1 deleted" -msgstr "Malkovich by %1 Malkovich" - -#: lib/RT/Transaction_Overlay.pm:625 -#. ($value) -msgid "Reference to %1 added" -msgstr "Malkovich to %1 Malkovich" - -#: lib/RT/Transaction_Overlay.pm:665 -#. ($value) -msgid "Reference to %1 deleted" -msgstr "Malkovich to %1 Malkovich" - -#: html/Elements/EditLinks:129 html/Elements/EditLinks:81 html/Elements/ShowLinks:70 html/Ticket/Create.html:185 html/Ticket/Elements/BulkLinks:50 -msgid "Referred to by" -msgstr "Malkovich to by" - -#: html/Elements/EditLinks:125 html/Elements/EditLinks:72 html/Elements/SelectLinkType:27 html/Elements/ShowLinks:60 html/Ticket/Create.html:184 html/Ticket/Elements/BulkLinks:46 -msgid "Refers to" -msgstr "Malkovich to" - -#: NOT FOUND IN SOURCE -msgid "Refine search" -msgstr "Malkovich" - -#: html/Elements/Refresh:35 -#. ($value/60) -msgid "Refresh this page every %1 minutes." -msgstr "Malkovich Malkovich %1 Malkovich." - -#: html/Search/Bulk.html:95 -msgid "Remove AdminCc" -msgstr "Malkovich" - -#: html/Search/Bulk.html:91 -msgid "Remove Cc" -msgstr "Malkovich Cc" - -#: html/Search/Bulk.html:87 -msgid "Remove Requestor" -msgstr "Malkovich Malkovich" - -#: html/Ticket/Elements/ShowTransaction:142 html/Ticket/Elements/Tabs:123 -msgid "Reply" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:87 -msgid "Reply to tickets" -msgstr "Malkovich to Malkovich" - -#: lib/RT/Queue_Overlay.pm:87 -msgid "ReplyToTicket" -msgstr "Malkovich" - -#: etc/initialdata:44 lib/RT/ACE_Overlay.pm:86 -msgid "Requestor" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Requestor email address" -msgstr "Malkovich Malkovich" - -#: html/SelfService/Create.html:40 html/Ticket/Create.html:55 html/Ticket/Elements/EditPeople:47 html/Ticket/Elements/ShowPeople:30 -msgid "Requestors" -msgstr "Malkovich" - -#: html/Admin/Queues/Modify.html:74 -msgid "Requests should be due in" -msgstr "Malkovich be due in" - -#: html/Elements/Submit:61 -msgid "Reset" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:156 html/User/Prefs.html:63 -msgid "Residence" -msgstr "Malkovich" - -#: html/Ticket/Elements/Tabs:133 -msgid "Resolve" -msgstr "Malkovich" - -#: html/Ticket/Update.html:119 -#. ($TicketObj->id, $TicketObj->Subject) -msgid "Resolve ticket #%1 (%2)" -msgstr "Malkovich #%1 (%2)" - -#: etc/initialdata:323 html/Elements/SelectDateType:27 lib/RT/Ticket_Overlay.pm:1282 -msgid "Resolved" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Response to requestors" -msgstr "Malkovich to Malkovich" - -#: html/Elements/ListActions:25 html/Search/Elements/NewListActions:25 -msgid "Results" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Results per page" -msgstr "Malkovich Malkovich" - -#: html/Admin/Users/Modify.html:99 html/User/Prefs.html:94 -msgid "Retype Password" -msgstr "Malkovich" - -#: lib/RT/ACE_Overlay.pm:612 -msgid "Right Delegated" -msgstr "Malkovich" - -#: lib/RT/ACE_Overlay.pm:302 -msgid "Right Granted" -msgstr "Malkovich" - -#: lib/RT/ACE_Overlay.pm:160 -msgid "Right Loaded" -msgstr "Malkovich" - -#: lib/RT/ACE_Overlay.pm:677 lib/RT/ACE_Overlay.pm:692 -msgid "Right could not be revoked" -msgstr "Malkovich be Malkovich" - -#: html/User/Delegation.html:63 -msgid "Right not found" -msgstr "Malkovich" - -#: lib/RT/ACE_Overlay.pm:542 lib/RT/ACE_Overlay.pm:637 -msgid "Right not loaded." -msgstr "Malkovich Malkovich." - -#: lib/RT/ACE_Overlay.pm:688 -msgid "Right revoked" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Rights" -msgstr "Malkovich" - -#: lib/RT/Interface/Web.pm:869 -#. ($object_type) -msgid "Rights could not be granted for %1" -msgstr "Malkovich Malkovich be Malkovich %1" - -#: lib/RT/Interface/Web.pm:899 -#. ($object_type) -msgid "Rights could not be revoked for %1" -msgstr "Malkovich Malkovich be Malkovich %1" - -#: html/Admin/Global/GroupRights.html:50 html/Admin/Queues/GroupRights.html:52 -msgid "Roles" -msgstr "Malkovich" - -#: lib/RT/Date.pm:393 -msgid "Sat." -msgstr "Sat." - -#: html/Admin/Global/Template.html:45 html/Admin/Queues/Modify.html:89 html/Admin/Queues/People.html:104 html/Admin/Users/Modify.html:198 html/SelfService/Prefs.html:36 html/Ticket/Modify.html:38 html/Ticket/ModifyAll.html:93 html/Ticket/ModifyDates.html:38 html/Ticket/ModifyLinks.html:38 html/Ticket/ModifyPeople.html:37 -msgid "Save Changes" -msgstr "Malkovich" - -#: html/Ticket/Elements/PreviewScrips:79 -msgid "Save changes" -msgstr "Malkovich" - -#: html/Admin/Global/Scrip.html:48 html/Admin/Queues/Scrip.html:54 -#. ($id) -#. ($ARGS{'id'}) -msgid "Scrip #%1" -msgstr "Malkovich #%1" - -#: lib/RT/Scrip_Overlay.pm:180 -msgid "Scrip Created" -msgstr "Malkovich" - -#: html/Admin/Elements/EditScrips:85 -msgid "Scrip deleted" -msgstr "Malkovich" - -#: html/Admin/Elements/QueueTabs:45 html/Admin/Elements/SystemTabs:32 html/Admin/Global/index.html:40 -msgid "Scrips" -msgstr "Malkovich" - -#: html/Admin/Queues/Scrips.html:33 -msgid "Scrips which apply to all queues" -msgstr "Malkovich Malkovich to Malkovich" - -#: html/Elements/SimpleSearch:26 html/Search/Elements/DisplayOptions:73 -msgid "Search" -msgstr "Malkovich" - -#: html/Approvals/Elements/PendingMyApproval:38 -msgid "Search for approvals" -msgstr "Malkovich Malkovich" - -#: bin/rt-crontool:184 -msgid "Security:" -msgstr "Malkovich:" - -#: lib/RT/Queue_Overlay.pm:68 -msgid "SeeQueue" -msgstr "Malkovich" - -#: html/Admin/Groups/index.html:50 -msgid "Select a group" -msgstr "Malkovich a Malkovich" - -#: html/Admin/Users/index.html:24 html/Admin/Users/index.html:27 -msgid "Select a user" -msgstr "Malkovich a user" - -#: html/Admin/Global/CustomField.html:37 html/Admin/Global/CustomFields.html:35 -msgid "Select custom field" -msgstr "Malkovich Malkovich" - -#: html/Admin/Elements/GroupTabs:51 html/User/Elements/GroupTabs:49 -msgid "Select group" -msgstr "Malkovich" - -#: lib/RT/CustomField_Overlay.pm:427 -msgid "Select multiple values" -msgstr "Malkovich Malkovich" - -#: lib/RT/CustomField_Overlay.pm:424 -msgid "Select one value" -msgstr "Malkovich Malkovich" - -#: html/Admin/Elements/QueueTabs:66 -msgid "Select queue" -msgstr "Malkovich" - -#: html/Admin/Global/Scrip.html:36 html/Admin/Global/Scrips.html:35 html/Admin/Queues/Scrip.html:39 html/Admin/Queues/Scrips.html:51 -msgid "Select scrip" -msgstr "Malkovich" - -#: html/Admin/Global/Template.html:56 html/Admin/Global/Templates.html:35 html/Admin/Queues/Template.html:54 html/Admin/Queues/Templates.html:46 -msgid "Select template" -msgstr "Malkovich" - -#: html/Admin/Elements/UserTabs:46 -msgid "Select user" -msgstr "Malkovich" - -#: lib/RT/CustomField_Overlay.pm:35 -msgid "SelectMultiple" -msgstr "Malkovich" - -#: lib/RT/CustomField_Overlay.pm:34 -msgid "SelectSingle" -msgstr "Malkovich" - -#: etc/initialdata:121 -msgid "Send mail to all watchers" -msgstr "Malkovich to Malkovich" - -#: etc/initialdata:117 -msgid "Send mail to all watchers as a \"comment\"" -msgstr "Malkovich to Malkovich as a \"Malkovich\"" - -#: etc/initialdata:112 -msgid "Send mail to requestors and Ccs" -msgstr "Malkovich to Malkovich and Ccs" - -#: etc/initialdata:107 -msgid "Send mail to requestors and Ccs as a comment" -msgstr "Malkovich to Malkovich and Ccs as a Malkovich" - -#: etc/initialdata:78 -msgid "Sends a message to the requestors" -msgstr "Malkovich a Malkovich to the Malkovich" - -#: etc/initialdata:125 etc/initialdata:129 -msgid "Sends mail to explicitly listed Ccs and Bccs" -msgstr "Malkovich to Malkovich Malkovich and Bccs" - -#: etc/initialdata:102 -msgid "Sends mail to the administrative Ccs" -msgstr "Malkovich to the Malkovich Malkovich" - -#: etc/initialdata:98 -msgid "Sends mail to the administrative Ccs as a comment" -msgstr "Malkovich to the Malkovich Malkovich as a Malkovich" - -#: etc/initialdata:82 etc/initialdata:86 -msgid "Sends mail to the owner" -msgstr "Malkovich to the Malkovich" - -#: lib/RT/Date.pm:419 -msgid "Sep." -msgstr "Sep." - -#: html/Approvals/Elements/PendingMyApproval:43 -msgid "Show approved requests" -msgstr "Malkovich Malkovich" - -#: html/Ticket/Create.html:143 html/Ticket/Create.html:33 -msgid "Show basics" -msgstr "Malkovich" - -#: html/Approvals/Elements/PendingMyApproval:44 -msgid "Show denied requests" -msgstr "Malkovich Malkovich" - -#: html/Ticket/Create.html:143 html/Ticket/Create.html:33 -msgid "Show details" -msgstr "Malkovich" - -#: html/Approvals/Elements/PendingMyApproval:42 -msgid "Show pending requests" -msgstr "Malkovich Malkovich" - -#: html/Approvals/Elements/PendingMyApproval:45 -msgid "Show requests awaiting other approvals" -msgstr "Malkovich Malkovich Malkovich Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Show ticket private commentary" -msgstr "Malkovich Malkovich Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Show ticket summaries" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:70 -msgid "ShowACL" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:79 -msgid "ShowScrips" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:76 -msgid "ShowTemplate" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:80 -msgid "ShowTicket" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:81 -msgid "ShowTicketComments" -msgstr "Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:84 -msgid "Sign up as a ticket Requestor or ticket or queue Cc" -msgstr "Sign up as a Malkovich Malkovich or Malkovich or Malkovich Cc" - -#: lib/RT/Queue_Overlay.pm:85 -msgid "Sign up as a ticket or queue AdminCc" -msgstr "Sign up as a Malkovich or Malkovich" - -#: html/Admin/Users/Modify.html:188 html/User/Prefs.html:145 -msgid "Signature" -msgstr "Malkovich" - -#: html/Admin/Elements/SelectSingleOrMultiple:25 -msgid "Single" -msgstr "Malkovich" - -#: html/Elements/Header:62 -msgid "Skip Menu" -msgstr "Malkovich" - -#: html/Admin/Elements/AddCustomFieldValue:27 -msgid "Sort" -msgstr "Sort" - -#: NOT FOUND IN SOURCE -msgid "Sort results by" -msgstr "Malkovich by" - -#: NOT FOUND IN SOURCE -msgid "Squelched message recipients" -msgstr "Malkovich Malkovich Malkovich" - -#: html/Admin/Elements/EditScrip:65 -msgid "Stage" -msgstr "Malkovich" - -#: html/Elements/SelectDateType:26 html/Ticket/Elements/EditDates:31 html/Ticket/Elements/ShowDates:35 -msgid "Started" -msgstr "Malkovich" - -#: html/Elements/SelectDateType:30 html/Ticket/Create.html:165 html/Ticket/Elements/EditDates:26 html/Ticket/Elements/ShowDates:31 -msgid "Starts" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:135 html/User/Prefs.html:123 -msgid "State" -msgstr "Malkovich" - -#: html/Search/Elements/PickBasics:77 html/SelfService/Elements/MyRequests:28 html/SelfService/Update.html:30 html/Ticket/Create.html:41 html/Ticket/Elements/EditBasics:31 html/Ticket/Elements/ShowBasics:30 html/Ticket/Update.html:37 lib/RT/Ticket_Overlay.pm:1276 lib/RT/Tickets_Overlay.pm:970 -msgid "Status" -msgstr "Malkovich" - -#: etc/initialdata:309 -msgid "Status Change" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:505 -#. ($self->loc($self->OldValue), $self->loc($self->NewValue)) -msgid "Status changed from %1 to %2" -msgstr "Malkovich Malkovich %1 to %2" - -#: html/Ticket/Elements/Tabs:148 -msgid "Steal" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:94 -msgid "Steal tickets" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:94 -msgid "StealTicket" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:581 -#. ($Old->Name) -msgid "Stolen from %1 " -msgstr "Malkovich %1 " - -#: html/Elements/QuickCreate:7 html/Elements/SelectAttachmentField:25 html/Search/Bulk.html:133 html/SelfService/Create.html:56 html/SelfService/Elements/MyRequests:27 html/SelfService/Update.html:31 html/Ticket/Create.html:83 html/Ticket/Elements/EditBasics:26 html/Ticket/ModifyAll.html:78 html/Ticket/Update.html:58 lib/RT/Ticket_Overlay.pm:1272 lib/RT/Tickets_Overlay.pm:1049 -msgid "Subject" -msgstr "Malkovich" - -#: docs/design_docs/string-extraction-guide.txt:89 lib/RT/StyleGuide.pod:795 lib/RT/Transaction_Overlay.pm:603 -#. ($self->Data) -msgid "Subject changed to %1" -msgstr "Malkovich to %1" - -#: html/Elements/Submit:58 -msgid "Submit" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:749 -msgid "Succeeded" -msgstr "Malkovich" - -#: lib/RT/Date.pm:394 -msgid "Sun." -msgstr "Sun." - -#: lib/RT/System.pm:53 -msgid "SuperUser" -msgstr "Malkovich" - -#: html/User/Elements/DelegateRights:76 -msgid "System" -msgstr "Malkovich" - -#: html/Admin/Elements/SelectRights:81 lib/RT/ACE_Overlay.pm:566 lib/RT/Interface/Web.pm:868 lib/RT/Interface/Web.pm:898 -msgid "System Error" -msgstr "Malkovich" - -#: lib/RT/ACE_Overlay.pm:615 -msgid "System error. Right not delegated." -msgstr "Malkovich. Malkovich Malkovich." - -#: lib/RT/ACE_Overlay.pm:145 lib/RT/ACE_Overlay.pm:222 lib/RT/ACE_Overlay.pm:305 lib/RT/ACE_Overlay.pm:897 -msgid "System error. Right not granted." -msgstr "Malkovich. Malkovich Malkovich." - -#: html/Admin/Global/GroupRights.html:34 html/Admin/Groups/GroupRights.html:36 html/Admin/Queues/GroupRights.html:35 -msgid "System groups" -msgstr "Malkovich" - -#: etc/initialdata:41 etc/initialdata:47 etc/initialdata:53 -msgid "SystemRolegroup for internal use" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/CurrentUser.pm:334 -msgid "TEST_STRING" -msgstr "TEST_MALKOVICH" - -#: html/Elements/MyRequests:27 html/Ticket/Elements/Tabs:144 -msgid "Take" -msgstr "Take" - -#: lib/RT/Queue_Overlay.pm:92 -msgid "Take tickets" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:92 -msgid "TakeTicket" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:566 -msgid "Taken" -msgstr "Malkovich" - -#: html/Admin/Elements/EditScrip:57 html/Tools/Offline.html:56 -msgid "Template" -msgstr "Malkovich" - -#: html/Admin/Global/Template.html:90 html/Admin/Queues/Template.html:89 -#. ($TemplateObj->Id()) -msgid "Template #%1" -msgstr "Malkovich #%1" - -#: html/Admin/Elements/EditTemplates:88 -msgid "Template deleted" -msgstr "Malkovich Malkovich" - -#: lib/RT/Scrip_Overlay.pm:156 -msgid "Template not found" -msgstr "Malkovich Malkovich" - -#: lib/RT/Template_Overlay.pm:348 -msgid "Template parsed" -msgstr "Malkovich" - -#: html/Admin/Elements/QueueTabs:48 html/Admin/Elements/SystemTabs:35 html/Admin/Global/index.html:44 -msgid "Templates" -msgstr "Malkovich" - -#: lib/RT/Record.pm:740 -msgid "That is already the current value" -msgstr "That is Malkovich the Malkovich" - -#: lib/RT/CustomField_Overlay.pm:248 -msgid "That is not a value for this custom field" -msgstr "That is not a Malkovich Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2086 -msgid "That is the same value" -msgstr "That is the Malkovich" - -#: lib/RT/ACE_Overlay.pm:287 lib/RT/ACE_Overlay.pm:596 -msgid "That principal already has that right" -msgstr "Malkovich Malkovich Malkovich Malkovich" - -#: lib/RT/Queue_Overlay.pm:674 -#. ($args{'Type'}) -msgid "That principal is already a %1 for this queue" -msgstr "Malkovich is Malkovich a %1 Malkovich" - -#: lib/RT/Ticket_Overlay.pm:1527 -#. ($self->loc($args{'Type'})) -msgid "That principal is already a %1 for this ticket" -msgstr "Malkovich is Malkovich a %1 Malkovich" - -#: lib/RT/Queue_Overlay.pm:773 -#. ($args{'Type'}) -msgid "That principal is not a %1 for this queue" -msgstr "That Malkovich is not a %1 Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2082 -msgid "That queue does not exist" -msgstr "Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:3152 -msgid "That ticket has unresolved dependencies" -msgstr "Malkovich Malkovich Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2956 -msgid "That user already owns that ticket" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2928 -msgid "That user does not exist" -msgstr "Malkovich Malkovich" - -#: lib/RT/User_Overlay.pm:355 -msgid "That user is already privileged" -msgstr "Malkovich is Malkovich Malkovich" - -#: lib/RT/User_Overlay.pm:376 -msgid "That user is already unprivileged" -msgstr "Malkovich is Malkovich Malkovich" - -#: lib/RT/User_Overlay.pm:368 -msgid "That user is now privileged" -msgstr "Malkovich is Malkovich" - -#: lib/RT/User_Overlay.pm:389 -msgid "That user is now unprivileged" -msgstr "Malkovich is Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:2949 -msgid "That user may not own tickets in that queue" -msgstr "Malkovich Malkovich Malkovich in Malkovich" - -#: lib/RT/Link_Overlay.pm:200 -msgid "That's not a numerical id" -msgstr "That's not a Malkovich id" - -#: html/SelfService/Display.html:31 html/Ticket/Create.html:149 html/Ticket/Elements/ShowSummary:27 -msgid "The Basics" -msgstr "The Malkovich" - -#: lib/RT/ACE_Overlay.pm:87 -msgid "The CC of a ticket" -msgstr "The CC of a Malkovich" - -#: lib/RT/ACE_Overlay.pm:88 -msgid "The administrative CC of a ticket" -msgstr "The Malkovich CC of a Malkovich" - -#: bin/rt-crontool:194 -msgid "The following command will find all active tickets in the queue 'general' and set their priority to 99 if they haven't been touched in 4 hours:" -msgstr "The Malkovich Malkovich Malkovich Malkovich Malkovich in the Malkovich 'Malkovich' and Malkovich Malkovich to 99 if they haven't Malkovich in 4 Malkovich:" - -#: NOT FOUND IN SOURCE -msgid "The following commands were not proccessed:\\n\\n" -msgstr "The Malkovich Malkovich Malkovich Malkovich:\\n\\n" - -#: lib/RT/Record.pm:743 -msgid "The new value has been set." -msgstr "The Malkovich Malkovich." - -#: lib/RT/ACE_Overlay.pm:85 -msgid "The owner of a ticket" -msgstr "The Malkovich of a Malkovich" - -#: lib/RT/ACE_Overlay.pm:86 -msgid "The requestor of a ticket" -msgstr "The Malkovich of a Malkovich" - -#: html/Admin/Elements/EditUserComments:25 -msgid "These comments aren't generally visible to the user" -msgstr "Malkovich aren't Malkovich Malkovich to the user" - -#: bin/rt-crontool:185 -msgid "This tool allows the user to run arbitrary perl modules from within RT." -msgstr "Malkovich Malkovich the user to Malkovich Malkovich Malkovich Malkovich RT." - -#: lib/RT/Transaction_Overlay.pm:226 -msgid "This transaction appears to have no content" -msgstr "Malkovich Malkovich to have no Malkovich" - -#: html/Ticket/Elements/ShowRequestor:48 -#. ($rows) -msgid "This user's %1 highest priority tickets" -msgstr "Malkovich's %1 Malkovich Malkovich" - -#: lib/RT/Date.pm:391 -msgid "Thu." -msgstr "Thu." - -#: html/Ticket/ModifyAll.html:24 html/Ticket/ModifyAll.html:28 -#. ($Ticket->Id, $Ticket->Subject) -msgid "Ticket #%1 Jumbo update: %2" -msgstr "Malkovich #%1 Malkovich: %2" - -#: html/Approvals/Elements/ShowDependency:45 -#. ($link->BaseObj->Id, $link->BaseObj->Subject) -msgid "Ticket #%1: %2" -msgstr "Malkovich #%1: %2" - -#: lib/RT/Ticket_Overlay.pm:696 lib/RT/Ticket_Overlay.pm:720 -#. ($self->Id, $QueueObj->Name) -msgid "Ticket %1 created in queue '%2'" -msgstr "Malkovich %1 Malkovich in Malkovich '%2'" - -#: NOT FOUND IN SOURCE -msgid "Ticket %1 loaded\\n" -msgstr "Malkovich %1 Malkovich\\n" - -#: html/Search/Bulk.html:216 -#. ($Ticket->Id,$_) -msgid "Ticket %1: %2" -msgstr "Malkovich %1: %2" - -#: html/Ticket/History.html:24 html/Ticket/History.html:27 -#. ($Ticket->Id, $Ticket->Subject) -msgid "Ticket History # %1 %2" -msgstr "Malkovich # %1 %2" - -#: etc/initialdata:324 -msgid "Ticket Resolved" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Ticket attachment" -msgstr "Malkovich Malkovich" - -#: lib/RT/Tickets_Overlay.pm:1228 -msgid "Ticket content" -msgstr "Malkovich" - -#: lib/RT/Tickets_Overlay.pm:1274 -msgid "Ticket content type" -msgstr "Malkovich Malkovich" - -#: lib/RT/Ticket_Overlay.pm:565 lib/RT/Ticket_Overlay.pm:579 lib/RT/Ticket_Overlay.pm:590 lib/RT/Ticket_Overlay.pm:707 -msgid "Ticket could not be created due to an internal error" -msgstr "Malkovich Malkovich be Malkovich to a Malkovich" - -#: lib/RT/Transaction_Overlay.pm:497 -msgid "Ticket created" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:502 -msgid "Ticket deleted" -msgstr "Malkovich" - -#: etc/initialdata:310 -msgid "Ticket status changed" -msgstr "Malkovich Malkovich" - -#: html/Elements/Tabs:46 -msgid "Tickets" -msgstr "Malkovich" - -#: lib/RT/Tickets_Overlay.pm:1452 -#. ($self->loc($args{'TYPE'}), ($args{'BASE'} || $args{'TICKET'})) -msgid "Tickets %1 %2" -msgstr "Malkovich %1 %2" - -#: lib/RT/Tickets_Overlay.pm:1410 -#. ($self->loc($args{'TYPE'}), ($args{'TARGET'} || $args{'TICKET'})) -msgid "Tickets %1 by %2" -msgstr "Malkovich %1 by %2" - -#: NOT FOUND IN SOURCE -msgid "Tickets from %1" -msgstr "Malkovich %1" - -#: html/Approvals/Elements/ShowDependency:26 -msgid "Tickets which depend on this approval:" -msgstr "Malkovich Malkovich on Malkovich:" - -#: html/Search/Elements/PickBasics:70 html/Ticket/Create.html:156 html/Ticket/Elements/EditBasics:47 -msgid "Time Left" -msgstr "Malkovich" - -#: html/Search/Elements/PickBasics:68 html/Ticket/Create.html:155 html/Ticket/Elements/EditBasics:43 -msgid "Time Worked" -msgstr "Malkovich" - -#: lib/RT/Tickets_Overlay.pm:1201 -msgid "Time left" -msgstr "Malkovich" - -#: html/Elements/Footer:44 -msgid "Time to display" -msgstr "Time to Malkovich" - -#: lib/RT/Tickets_Overlay.pm:1177 -msgid "Time worked" -msgstr "Malkovich" - -#: lib/RT/Ticket_Overlay.pm:1277 -msgid "TimeWorked" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "To generate a diff of this commit:" -msgstr "To Malkovich a diff of Malkovich:" - -#: NOT FOUND IN SOURCE -msgid "To generate a diff of this commit:\\n" -msgstr "To Malkovich a diff of Malkovich:\\n" - -#: lib/RT/Ticket_Overlay.pm:1280 -msgid "Told" -msgstr "Told" - -#: etc/initialdata:252 -msgid "Transaction" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:705 -#. ($self->Data) -msgid "Transaction %1 purged" -msgstr "Malkovich %1 Malkovich" - -#: lib/RT/Transaction_Overlay.pm:136 -msgid "Transaction Created" -msgstr "Malkovich Malkovich" - -#: lib/RT/Transaction_Overlay.pm:92 -msgid "Transaction->Create couldn't, as you didn't specify a ticket id" -msgstr "Malkovich->Malkovich couldn't, as you didn't Malkovich a Malkovich id" - -#: lib/RT/Transaction_Overlay.pm:760 -msgid "Transactions are immutable" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/Date.pm:389 -msgid "Tue." -msgstr "Tue." - -#: html/Admin/Elements/EditCustomField:43 html/Ticket/Elements/AddWatchers:32 html/Ticket/Elements/AddWatchers:43 html/Ticket/Elements/AddWatchers:53 lib/RT/Ticket_Overlay.pm:1278 lib/RT/Tickets_Overlay.pm:1021 -msgid "Type" -msgstr "Type" - -#: lib/RT/ScripCondition_Overlay.pm:103 -msgid "Unimplemented" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:67 -msgid "Unix login" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "UnixUsername" -msgstr "Malkovich" - -#: lib/RT/Attachment_Overlay.pm:233 lib/RT/Attachment_Overlay.pm:265 -#. ($self->ContentEncoding) -msgid "Unknown ContentEncoding %1" -msgstr "Malkovich Malkovich %1" - -#: html/Elements/SelectResultsPerPage:36 -msgid "Unlimited" -msgstr "Malkovich" - -#: etc/initialdata:32 -msgid "Unprivileged" -msgstr "Malkovich" - -#: lib/RT/Transaction_Overlay.pm:562 -msgid "Untaken" -msgstr "Malkovich" - -#: html/Search/Bulk.html:32 -msgid "Update" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Update ID" -msgstr "Malkovich ID" - -#: html/Search/Bulk.html:127 html/Ticket/ModifyAll.html:65 html/Ticket/Update.html:48 -msgid "Update Type" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Update all these tickets at once" -msgstr "Malkovich Malkovich at once" - -#: NOT FOUND IN SOURCE -msgid "Update email" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Update name" -msgstr "Malkovich" - -#: lib/RT/Action/CreateTickets.pm:655 lib/RT/Interface/Web.pm:479 -msgid "Update not recorded." -msgstr "Malkovich Malkovich." - -#: html/Search/Bulk.html:78 -msgid "Update selected tickets" -msgstr "Malkovich Malkovich" - -#: NOT FOUND IN SOURCE -msgid "Update signature" -msgstr "Malkovich Malkovich" - -#: html/Ticket/ModifyAll.html:62 -msgid "Update ticket" -msgstr "Malkovich" - -#: html/SelfService/Update.html:24 html/SelfService/Update.html:63 -#. ($Ticket->id) -msgid "Update ticket #%1" -msgstr "Malkovich #%1" - -#: html/Ticket/Update.html:121 -#. ($TicketObj->id, $TicketObj->Subject) -msgid "Update ticket #%1 (%2)" -msgstr "Malkovich #%1 (%2)" - -#: lib/RT/Action/CreateTickets.pm:653 lib/RT/Interface/Web.pm:477 -msgid "Update type was neither correspondence nor comment." -msgstr "Malkovich Malkovich Malkovich Malkovich Malkovich." - -#: html/Elements/SelectDateType:32 html/Ticket/Elements/ShowDates:51 lib/RT/Ticket_Overlay.pm:1281 -msgid "Updated" -msgstr "Malkovich" - -#: etc/initialdata:132 etc/initialdata:206 -msgid "User Defined" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "User ID" -msgstr "User ID" - -#: html/Elements/SelectUsers:25 -msgid "User Id" -msgstr "User Id" - -#: html/Admin/Elements/GroupTabs:46 html/Admin/Elements/QueueTabs:59 html/Admin/Elements/SystemTabs:46 html/Admin/Global/index.html:58 -msgid "User Rights" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:252 -#. ($msg) -msgid "User could not be created: %1" -msgstr "Malkovich be Malkovich: %1" - -#: lib/RT/User_Overlay.pm:296 -msgid "User created" -msgstr "Malkovich" - -#: html/Admin/Global/GroupRights.html:66 html/Admin/Groups/GroupRights.html:53 html/Admin/Queues/GroupRights.html:68 -msgid "User defined groups" -msgstr "Malkovich Malkovich" - -#: lib/RT/User_Overlay.pm:558 lib/RT/User_Overlay.pm:575 -msgid "User loaded" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "User view" -msgstr "Malkovich" - -#: html/Admin/Users/Modify.html:47 html/Elements/Login:51 html/Ticket/Elements/AddWatchers:34 -msgid "Username" -msgstr "Malkovich" - -#: html/Admin/Elements/SelectNewGroupMembers:25 html/Admin/Elements/Tabs:31 html/Admin/Groups/Members.html:54 html/Admin/Queues/People.html:67 html/Admin/index.html:28 html/User/Groups/Members.html:57 -msgid "Users" -msgstr "Malkovich" - -#: html/Admin/Users/index.html:64 -msgid "Users matching search criteria" -msgstr "Malkovich Malkovich Malkovich" - -#: lib/RT/Tickets_Overlay_SQL.pm:494 -msgid "Valid Query" -msgstr "Malkovich" - -#: html/Admin/Elements/EditCustomField:56 -msgid "Values" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:84 -msgid "Watch" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:85 -msgid "WatchAsAdminCc" -msgstr "Malkovich" - -#: html/Admin/Elements/QueueTabs:41 -msgid "Watchers" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "WebEncoding" -msgstr "Malkovich" - -#: lib/RT/Date.pm:390 -msgid "Wed." -msgstr "Wed." - -#: etc/initialdata:521 -msgid "When a ticket has been approved by all approvers, add correspondence to the original ticket" -msgstr "When a Malkovich Malkovich by Malkovich, Malkovich Malkovich to the Malkovich" - -#: etc/initialdata:485 -msgid "When a ticket has been approved by any approver, add correspondence to the original ticket" -msgstr "When a Malkovich Malkovich by Malkovich, Malkovich Malkovich to the Malkovich" - -#: etc/initialdata:146 -msgid "When a ticket is created" -msgstr "When a Malkovich is Malkovich" - -#: etc/initialdata:418 -msgid "When an approval ticket is created, notify the Owner and AdminCc of the item awaiting their approval" -msgstr "When a Malkovich is Malkovich, Malkovich the Malkovich and Malkovich of the Malkovich Malkovich Malkovich" - -#: etc/initialdata:151 -msgid "When anything happens" -msgstr "Malkovich Malkovich" - -#: etc/initialdata:199 -msgid "Whenever a ticket is resolved" -msgstr "Malkovich a Malkovich is Malkovich" - -#: etc/initialdata:185 -msgid "Whenever a ticket's owner changes" -msgstr "Malkovich a Malkovich's Malkovich" - -#: etc/initialdata:193 -msgid "Whenever a ticket's queue changes" -msgstr "Malkovich a Malkovich's Malkovich" - -#: etc/initialdata:170 -msgid "Whenever a ticket's status changes" -msgstr "Malkovich a Malkovich's Malkovich" - -#: etc/initialdata:207 -msgid "Whenever a user-defined condition occurs" -msgstr "Malkovich a user-Malkovich Malkovich" - -#: etc/initialdata:164 -msgid "Whenever comments come in" -msgstr "Malkovich Malkovich in" - -#: etc/initialdata:157 -msgid "Whenever correspondence comes in" -msgstr "Malkovich Malkovich Malkovich in" - -#: html/Admin/Users/Modify.html:161 html/User/Prefs.html:67 -msgid "Work" -msgstr "Work" - -#: NOT FOUND IN SOURCE -msgid "WorkPhone" -msgstr "Malkovich" - -#: html/Ticket/Elements/ShowBasics:41 html/Ticket/Update.html:42 -msgid "Worked" -msgstr "Malkovich" - -#: html/autohandler:150 -msgid "XXX CHANGEME You are not an authorized user" -msgstr "MALKOVICH Malkovich a Malkovich" - -#: lib/RT/Ticket_Overlay.pm:3059 -msgid "You already own this ticket" -msgstr "Malkovich Malkovich Malkovich" - -#: html/autohandler:142 -msgid "You are not an authorized user" -msgstr "Malkovich a Malkovich" - -#: NOT FOUND IN SOURCE -msgid "You can access it with the Download button on the right." -msgstr "Malkovich it with the Malkovich on the Malkovich." - -#: lib/RT/Ticket_Overlay.pm:2941 -msgid "You can only reassign tickets that you own or that are unowned" -msgstr "Malkovich Malkovich Malkovich Malkovich or Malkovich Malkovich" - -#: docs/design_docs/string-extraction-guide.txt:47 lib/RT/StyleGuide.pod:760 -#. ($num, $queue) -msgid "You found %1 tickets in queue %2" -msgstr "Malkovich %1 Malkovich in Malkovich %2" - -#: html/NoAuth/Logout.html:30 -msgid "You have been logged out of RT." -msgstr "Malkovich Malkovich of RT." - -#: html/SelfService/Display.html:79 -msgid "You have no permission to create tickets in that queue." -msgstr "Malkovich no Malkovich to Malkovich in that Malkovich." - -#: lib/RT/Ticket_Overlay.pm:2095 -msgid "You may not create requests in that queue." -msgstr "Malkovich Malkovich Malkovich in Malkovich." - -#: html/NoAuth/Logout.html:34 -msgid "You're welcome to login again" -msgstr "You're Malkovich to Malkovich" - -#: etc/initialdata:502 -msgid "Your request has been approved by %1. Other approvals may still be pending." -msgstr "Malkovich Malkovich Malkovich by %1. Malkovich Malkovich be Malkovich." - -#: etc/initialdata:540 -msgid "Your request has been approved." -msgstr "Malkovich Malkovich Malkovich." - -#: etc/initialdata:445 -msgid "Your request was rejected." -msgstr "Malkovich Malkovich." - -#: html/autohandler:177 -msgid "Your username or password is incorrect" -msgstr "Malkovich or Malkovich is Malkovich" - -#: html/Admin/Users/Modify.html:141 html/User/Prefs.html:127 -msgid "Zip" -msgstr "Zip" - -#: html/User/Elements/DelegateRights:58 -#. ($right->PrincipalObj->Object->SelfDescription) -msgid "as granted to %1" -msgstr "as Malkovich to %1" - -#: html/SelfService/Closed.html:27 -msgid "closed" -msgstr "Malkovich" - -#: html/Elements/SelectCustomFieldOperator:37 html/Elements/SelectMatch:33 -msgid "contains" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "content" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "content-type" -msgstr "Malkovich-type" - -#: html/Admin/Queues/Modify.html:76 lib/RT/Date.pm:319 -msgid "days" -msgstr "days" - -#: lib/RT/Queue_Overlay.pm:64 -msgid "deleted" -msgstr "Malkovich" - -#: html/Search/Elements/PickBasics:33 -msgid "does not match" -msgstr "Malkovich" - -#: html/Elements/SelectCustomFieldOperator:37 html/Elements/SelectMatch:34 -msgid "doesn't contain" -msgstr "doesn't Malkovich" - -#: html/Elements/SelectEqualityOperator:37 -msgid "equal to" -msgstr "Malkovich to" - -#: NOT FOUND IN SOURCE -msgid "filename" -msgstr "Malkovich" - -#: html/Elements/SelectCustomFieldOperator:37 html/Elements/SelectEqualityOperator:37 -msgid "greater than" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:196 -#. ($self->Name) -msgid "group '%1'" -msgstr "Malkovich '%1'" - -#: lib/RT/Date.pm:315 -msgid "hours" -msgstr "Malkovich" - -#: html/Elements/SelectBoolean:31 html/Elements/SelectCustomFieldOperator:37 html/Elements/SelectMatch:35 html/Search/Elements/PickBasics:49 html/Search/Elements/PickBasics:80 html/Search/Elements/PickBasics:97 html/Search/Elements/PickCFs:37 -msgid "is" -msgstr "is" - -#: html/Elements/SelectBoolean:35 html/Elements/SelectCustomFieldOperator:37 html/Elements/SelectMatch:36 html/Search/Elements/PickBasics:50 html/Search/Elements/PickBasics:81 html/Search/Elements/PickBasics:98 html/Search/Elements/PickCFs:38 -msgid "isn't" -msgstr "isn't" - -#: html/Elements/SelectCustomFieldOperator:37 html/Elements/SelectEqualityOperator:37 -msgid "less than" -msgstr "Malkovich" - -#: html/Search/Elements/PickBasics:32 -msgid "matches" -msgstr "Malkovich" - -#: lib/RT/Date.pm:311 -msgid "min" -msgstr "min" - -#: html/Ticket/Update.html:42 -msgid "minutes" -msgstr "Malkovich" - -#: NOT FOUND IN SOURCE -msgid "modifications\\n\\n" -msgstr "Malkovich\\n\\n" - -#: lib/RT/Date.pm:327 -msgid "months" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:59 -msgid "new" -msgstr "new" - -#: html/Admin/Elements/EditCustomFields:42 -msgid "no name" -msgstr "no name" - -#: html/Admin/Elements/EditScrips:42 -msgid "no value" -msgstr "no Malkovich" - -#: html/Admin/Elements/EditQueueWatchers:26 html/Ticket/Elements/EditWatchers:27 -msgid "none" -msgstr "none" - -#: html/Elements/SelectEqualityOperator:37 -msgid "not equal to" -msgstr "Malkovich to" - -#: html/SelfService/Elements/MyRequests:61 lib/RT/Queue_Overlay.pm:60 -msgid "open" -msgstr "open" - -#: lib/RT/Group_Overlay.pm:201 -#. ($self->Name, $user->Name) -msgid "personal group '%1' for user '%2'" -msgstr "Malkovich '%1' Malkovich '%2'" - -#: lib/RT/Group_Overlay.pm:209 -#. ($queue->Name, $self->Type) -msgid "queue %1 %2" -msgstr "Malkovich %1 %2" - -#: lib/RT/Queue_Overlay.pm:63 -msgid "rejected" -msgstr "Malkovich" - -#: lib/RT/Queue_Overlay.pm:62 -msgid "resolved" -msgstr "Malkovich" - -#: lib/RT/Date.pm:307 -msgid "sec" -msgstr "sec" - -#: lib/RT/Queue_Overlay.pm:61 -msgid "stalled" -msgstr "Malkovich" - -#: lib/RT/Group_Overlay.pm:204 -#. ($self->Type) -msgid "system %1" -msgstr "Malkovich %1" - -#: lib/RT/Group_Overlay.pm:215 -#. ($self->Type) -msgid "system group '%1'" -msgstr "Malkovich '%1'" - -#: html/Elements/Error:42 html/SelfService/Error.html:41 -msgid "the calling component did not specify why" -msgstr "the Malkovich Malkovich Malkovich Malkovich" - -#: NOT FOUND IN SOURCE -msgid "ticket #%1" -msgstr "Malkovich #%1" - -#: lib/RT/Group_Overlay.pm:212 -#. ($self->Instance, $self->Type) -msgid "ticket #%1 %2" -msgstr "Malkovich #%1 %2" - -#: lib/RT/Group_Overlay.pm:218 -#. ($self->Id) -msgid "undescribed group %1" -msgstr "Malkovich Malkovich %1" - -#: lib/RT/Group_Overlay.pm:193 -#. ($user->Object->Name) -msgid "user %1" -msgstr "user %1" - -#: lib/RT/Date.pm:323 -msgid "weeks" -msgstr "Malkovich" - -#: lib/RT/Date.pm:331 -msgid "years" -msgstr "Malkovich" - diff --git a/rt/lib/RT/Interface/CLI.pm b/rt/lib/RT/Interface/CLI.pm index 8c9329508..ec0e877b4 100644 --- a/rt/lib/RT/Interface/CLI.pm +++ b/rt/lib/RT/Interface/CLI.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK use strict; use RT; @@ -55,7 +33,7 @@ BEGIN { use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); # set the version for version checking - $VERSION = do { my @r = (q$Revision: 1.1.1.3 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker + $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker @ISA = qw(Exporter); diff --git a/rt/lib/RT/Interface/Email.pm b/rt/lib/RT/Interface/Email.pm index efc4c268e..7eec0502f 100755 --- a/rt/lib/RT/Interface/Email.pm +++ b/rt/lib/RT/Interface/Email.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,43 +14,27 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# CONTRIBUTION SUBMISSION POLICY: +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# (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 }}} +# END LICENSE BLOCK package RT::Interface::Email; use strict; use Mail::Address; use MIME::Entity; use RT::EmailParser; -use File::Temp; + BEGIN { use Exporter (); use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); # set the version for version checking - $VERSION = do { my @r = (q$Revision: 1.1.1.6 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker + $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # must be all one line, for MakeMaker @ISA = qw(Exporter); @@ -64,23 +42,22 @@ BEGIN { # as well as any optionally exported functions @EXPORT_OK = qw( &CreateUser - &GetMessageContent - &CheckForLoops - &CheckForSuspiciousSender - &CheckForAutoGenerated - &CheckForBounce - &MailError - &ParseCcAddressesFromHead - &ParseSenderAddressFromHead - &ParseErrorsToAddressFromHead - &ParseAddressFromHeader + &GetMessageContent + &CheckForLoops + &CheckForSuspiciousSender + &CheckForAutoGenerated + &MailError + &ParseCcAddressesFromHead + &ParseSenderAddressFromHead + &ParseErrorsToAddressFromHead + &ParseAddressFromHeader &Gateway); } =head1 NAME - RT::Interface::Email - helper functions for parsing email sent to RT + RT::Interface::CLI - helper functions for creating a commandline RT interface =head1 SYNOPSIS @@ -140,8 +117,8 @@ sub CheckForSuspiciousSender { my ($From, $junk) = ParseSenderAddressFromHead($head); - if (($From =~ /^mailer-daemon\@/i) or - ($From =~ /^postmaster\@/i)){ + if (($From =~ /^mailer-daemon/i) or + ($From =~ /^postmaster/i)){ return (1); } @@ -160,67 +137,13 @@ sub CheckForAutoGenerated { if ($Precedence =~ /^(bulk|junk)/i) { return (1); } - - # First Class mailer uses this as a clue. - my $FCJunk = $head->get("X-FC-Machinegenerated") || ""; - if ($FCJunk =~ /^true/i) { - return (1); - } - - return (0); -} - -# }}} - -# {{{ sub CheckForBounce -sub CheckForBounce { - my $head = shift; - - my $ReturnPath = $head->get("Return-path") || "" ; - return ($ReturnPath =~ /<>/); -} - -# }}} - -# {{{ IsRTAddress - -=head2 IsRTAddress ADDRESS - -Takes a single parameter, an email address. -Returns true if that address matches the $RTAddressRegexp. -Returns false, otherwise. - -=cut - -sub IsRTAddress { - my $address = shift || ''; - - # Example: the following rule would tell RT not to Cc - # "tickets@noc.example.com" - if ( defined($RT::RTAddressRegexp) && - $address =~ /$RT::RTAddressRegexp/i ) { - return(1); - } else { - return (undef); + else { + return (0); } } # }}} -# {{{ CullRTAddresses - -=head2 CullRTAddresses ARRAY - -Takes a single argument, an array of email addresses. -Returns the same array with any IsRTAddress()es weeded out. - -=cut - -sub CullRTAddresses { - return (grep { IsRTAddress($_) } @_); -} - -# }}} # {{{ sub MailError sub MailError { @@ -230,7 +153,6 @@ sub MailError { Subject => 'There has been an error', Explanation => 'Unexplained error', MIMEObj => undef, - Attach => undef, LogLevel => 'crit', @_); @@ -243,7 +165,6 @@ sub MailError { Bcc => $args{'Bcc'}, To => $args{'To'}, Subject => $args{'Subject'}, - Precedence => 'bulk', 'X-RT-Loop-Prevention' => $RT::rtname, ); @@ -254,19 +175,14 @@ sub MailError { $mimeobj->sync_headers(); $entity->add_part($mimeobj); } - - if ($args{'Attach'}) { - $entity->attach(Data => $args{'Attach'}, Type => 'message/rfc822'); - - } - + if ($RT::MailCommand eq 'sendmailpipe') { - open (MAIL, "|$RT::SendmailPath $RT::SendmailBounceArguments $RT::SendmailArguments") || return(0); + open (MAIL, "|$RT::SendmailPath $RT::SendmailArguments") || return(0); print MAIL $entity->as_string; close(MAIL); } else { - $entity->send($RT::MailCommand, $RT::MailParams); + $entity->send($RT::MailCommand, $RT::MailParams); } } @@ -278,6 +194,12 @@ sub CreateUser { my ($Username, $Address, $Name, $ErrorsTo, $entity) = @_; my $NewUser = RT::User->new($RT::SystemUser); + # This data is tainted by some Very Broken mailers. + # (Sometimes they send raw ISO 8859-1 data here. fear that. + require Encode; + $Username = Encode::encode(utf8 => $Username, Encode::FB_PERLQQ()) if defined $Username; + $Name = Encode::encode(utf8 => $Name, Encode::FB_PERLQQ()) if defined $Name; + my ($Val, $Message) = $NewUser->Create(Name => ($Username || $Address), EmailAddress => $Address, @@ -325,8 +247,7 @@ sub CreateUser { return $CurrentUser; } -# }}} - +# }}} # {{{ ParseCcAddressesFromHead =head2 ParseCcAddressesFromHead HASHREF @@ -352,10 +273,10 @@ sub ParseCcAddressesFromHead { foreach my $AddrObj (@ToObjs, @CcObjs) { my $Address = $AddrObj->address; $Address = $args{'CurrentUser'}->UserObj->CanonicalizeEmailAddress($Address); - next if ($args{'CurrentUser'}->EmailAddress =~ /^\Q$Address\E$/i); - next if ($args{'QueueObj'}->CorrespondAddress =~ /^\Q$Address\E$/i); - next if ($args{'QueueObj'}->CommentAddress =~ /^\Q$Address\E$/i); - next if (RT::EmailParser->IsRTAddress($Address)); + next if ($args{'CurrentUser'}->EmailAddress =~ /^$Address$/i); + next if ($args{'QueueObj'}->CorrespondAddress =~ /^$Address$/i); + next if ($args{'QueueObj'}->CommentAddress =~ /^$Address$/i); + next if (RT::EmailParser::IsRTAddress(undef, $Address)); push (@Addresses, $Address); } @@ -389,8 +310,7 @@ sub ParseSenderAddressFromHead { =head2 ParseErrorsToAddressFromHead Takes a MIME::Header object. Return a single value : user@host -of the From (evaluated in order of Return-path:,Errors-To:,Reply-To:, -From:, Sender) +of the From (evaluated in order of Errors-To:,Reply-To:, From:, Sender) =cut @@ -398,7 +318,7 @@ sub ParseErrorsToAddressFromHead { my $head = shift; #Figure out who's sending this message. - foreach my $header ('Return-path', 'Errors-To' , 'Reply-To', 'From', 'Sender' ) { + foreach my $header ('Errors-To' , 'Reply-To', 'From', 'Sender' ) { # If there's a header of that name my $headerobj = $head->get($header); if ($headerobj) { @@ -422,8 +342,6 @@ Takes an address from $head->get('Line') and returns a tuple: user@host, friendl sub ParseAddressFromHeader{ my $Addr = shift; - # Perl 5.8.0 breaks when doing regex matches on utf8 - Encode::_utf8_off($Addr) if $] == 5.008; my @Addresses = Mail::Address->parse($Addr); my $AddrObj = $Addresses[0]; @@ -441,234 +359,135 @@ sub ParseAddressFromHeader{ } # }}} -# {{{ sub ParseTicketId - - -sub ParseTicketId { - my $Subject = shift; - my $id; - - my $test_name = $RT::EmailSubjectTagRegex || qr/\Q$RT::rtname\E/i; - - if ( $Subject =~ s/\[$test_name\s+\#(\d+)\s*\]//i ) { - my $id = $1; - $RT::Logger->debug("Found a ticket ID. It's $id"); - return ($id); - } - else { - return (undef); - } -} - -# }}} - - -=head2 Gateway ARGSREF - -Takes parameters: - - action - queue - message +=head2 Gateway This performs all the "guts" of the mail rt-mailgate program, and is designed to be called from the web interface with a message, user object, and so on. -Can also take an optional 'ticket' parameter; this ticket id overrides -any ticket id found in the subject. - -Returns: - - An array of: - - (status code, message, optional ticket object) - - status code is a numeric value. - - for temporary failures, the status code should be -75 - - for permanent failures which are handled by RT, the status code - should be 0 - - for succces, the status code should be 1 - - - =cut sub Gateway { - my $argsref = shift; - - my %args = %$argsref; - - # Set some reasonable defaults - $args{'action'} ||= 'correspond'; - $args{'queue'} ||= '1'; + my %args = ( message => undef, + queue => 1, + action => 'correspond', + ticket => undef, + @_ ); # Validate the action - my ($status, @actions) = IsCorrectAction( $args{'action'} ); - unless ( $status ) { + unless ( $args{'action'} =~ /^(comment|correspond|action)$/ ) { # Can't safely loc this. What object do we loc around? - $RT::Logger->crit("Mail gateway called with an invalid action paramenter '".$actions[0]."' for queue '".$args{'queue'}."'"); - - return ( -75, "Invalid 'action' parameter", undef ); + return ( 0, "Invalid 'action' parameter", undef ); } my $parser = RT::EmailParser->new(); - - $parser->SmartParseMIMEEntityFromScalar( Message => $args{'message'}); - - if (!$parser->Entity()) { - MailError( - To => $RT::OwnerEmail, - Subject => "RT Bounce: Unparseable message", - Explanation => "RT couldn't process the message below", - Attach => $args{'message'} - ); - - return(0,"Failed to parse this message. Something is likely badly wrong with the message"); - } + $parser->ParseMIMEEntityFromScalar( $args{'message'} ); my $Message = $parser->Entity(); - my $head = $Message->head; + my $head = $Message->head; - my ( $CurrentUser, $AuthStat, $error ); - - # Initalize AuthStat so comparisons work correctly - $AuthStat = -9999999; + my ( $CurrentUser, $AuthStat, $status, $error ); my $ErrorsTo = ParseErrorsToAddressFromHead($head); - my $MessageId = $head->get('Message-ID') + my $MessageId = $head->get('Message-Id') || "<no-message-id-" . time . rand(2000) . "\@.$RT::Organization>"; #Pull apart the subject line my $Subject = $head->get('Subject') || ''; chomp $Subject; - $args{'ticket'} ||= ParseTicketId($Subject); + + $args{'ticket'} ||= $parser->ParseTicketId($Subject); my $SystemTicket; - my $Right = 'CreateTicket'; - if ( $args{'ticket'} ) { + if ($args{'ticket'} ) { $SystemTicket = RT::Ticket->new($RT::SystemUser); - $SystemTicket->Load( $args{'ticket'} ); - # if there's an existing ticket, this must be a reply - $Right = 'ReplyToTicket'; + $SystemTicket->Load($args{'ticket'}); } #Set up a queue object my $SystemQueueObj = RT::Queue->new($RT::SystemUser); $SystemQueueObj->Load( $args{'queue'} ); + # We can safely have no queue of we have a known-good ticket unless ( $args{'ticket'} || $SystemQueueObj->id ) { - return ( -75, "RT couldn't find the queue: " . $args{'queue'}, undef ); + MailError( + To => $RT::OwnerEmail, + Subject => "RT Bounce: $Subject", + Explanation => "RT couldn't find the queue: " . $args{'queue'}, + MIMEObj => $Message ); + return ( 0, "RT couldn't find the queue: " . $args{'queue'}, undef ); } # Authentication Level - # -1 - Get out. this user has been explicitly declined + # -1 - Get out. this user has been explicitly declined # 0 - User may not do anything (Not used at the moment) # 1 - Normal user # 2 - User is allowed to specify status updates etc. a la enhanced-mailgate - push @RT::MailPlugins, "Auth::MailFrom" unless @RT::MailPlugins; - + push @RT::MailPlugins, "Auth::MailFrom" unless @RT::MailPlugins; # Since this needs loading, no matter what - foreach (@RT::MailPlugins) { + for (@RT::MailPlugins) { my $Code; my $NewAuthStat; if ( ref($_) eq "CODE" ) { $Code = $_; } else { - $_ = "RT::Interface::Email::".$_ unless $_ =~ /^RT::Interface::Email::/; + $_ = "RT::Interface::Email::$_" unless /^RT::Interface::Email::/; eval "require $_;"; if ($@) { - $RT::Logger->crit("Couldn't load module '$_': $@"); + die ("Couldn't load module $_: $@"); next; } no strict 'refs'; if ( !defined( $Code = *{ $_ . "::GetCurrentUser" }{CODE} ) ) { - $RT::Logger->crit("No GetCurrentUser code found in $_ module"); + die ("No GetCurrentUser code found in $_ module"); next; } } - foreach my $action ( @actions ) { - - ( $CurrentUser, $NewAuthStat ) = $Code->( - Message => $Message, - RawMessageRef => \$args{'message'}, - CurrentUser => $CurrentUser, - AuthLevel => $AuthStat, - Action => $action, - Ticket => $SystemTicket, - Queue => $SystemQueueObj - ); - - - # If a module returns a "-1" then we discard the ticket, so. - $AuthStat = -1 if $NewAuthStat == -1; - - # You get the highest level of authentication you were assigned. - $AuthStat = $NewAuthStat if $NewAuthStat > $AuthStat; - - last if $AuthStat == -1; - } + ( $CurrentUser, $NewAuthStat ) = $Code->( Message => $Message, + CurrentUser => $CurrentUser, + AuthLevel => $AuthStat, + Action => $args{'action'}, + Ticket => $SystemTicket, + Queue => $SystemQueueObj ); + # You get the highest level of authentication you were assigned. last if $AuthStat == -1; + $AuthStat = $NewAuthStat if $NewAuthStat > $AuthStat; } # {{{ If authentication fails and no new user was created, get out. if ( !$CurrentUser or !$CurrentUser->Id or $AuthStat == -1 ) { # If the plugins refused to create one, they lose. - unless ( $AuthStat == -1 ) { - - # Notify the RT Admin of the failure. - # XXX Should this be configurable? - MailError( - To => $RT::OwnerEmail, - Subject => "Could not load a valid user", - Explanation => <<EOT, -RT could not load a valid user, and RT's configuration does not allow -for the creation of a new user for this email ($ErrorsTo). - -You might need to grant 'Everyone' the right '$Right' for the -queue @{[$args{'queue'}]}. - -EOT - MIMEObj => $Message, - LogLevel => 'error' - ); - - # Also notify the requestor that his request has been dropped. - MailError( - To => $ErrorsTo, - Subject => "Could not load a valid user", - Explanation => <<EOT, + MailError( + Subject => "Could not load a valid user", + Explanation => <<EOT, RT could not load a valid user, and RT's configuration does not allow for the creation of a new user for your email. +Your RT administrator needs to grant 'Everyone' the right 'CreateTicket' +for this queue. + EOT - MIMEObj => $Message, - LogLevel => 'error' - ); - } + MIMEObj => $Message, + LogLevel => 'error' ) + unless $AuthStat == -1; return ( 0, "Could not load a valid user", undef ); } # }}} # {{{ Lets check for mail loops of various sorts. - my $IsBounce = CheckForBounce($head); - my $IsAutoGenerated = CheckForAutoGenerated($head); my $IsSuspiciousSender = CheckForSuspiciousSender($head); @@ -679,7 +498,7 @@ EOT #If the message is autogenerated, we need to know, so we can not # send mail to the sender - if ( $IsBounce || $IsSuspiciousSender || $IsAutoGenerated || $IsALoop ) { + if ( $IsSuspiciousSender || $IsAutoGenerated || $IsALoop ) { $SquelchReplies = 1; $ErrorsTo = $RT::OwnerEmail; } @@ -689,11 +508,10 @@ EOT # {{{ Drop it if it's disallowed if ( $AuthStat == 0 ) { MailError( - To => $ErrorsTo, - Subject => "Permission Denied", - Explanation => "You do not have permission to communicate with RT", - MIMEObj => $Message - ); + To => $ErrorsTo, + Subject => "Permission Denied", + Explanation => "You do not have permission to communicate with RT", + MIMEObj => $Message ); } # }}} @@ -705,16 +523,14 @@ EOT #Should we mail it to RTOwner? if ($RT::LoopsToRTOwner) { - MailError( - To => $RT::OwnerEmail, - Subject => "RT Bounce: $Subject", - Explanation => "RT thinks this message may be a bounce", - MIMEObj => $Message - ); - } + MailError( To => $RT::OwnerEmail, + Subject => "RT Bounce: $Subject", + Explanation => "RT thinks this message may be a bounce", + MIMEObj => $Message ); - #Do we actually want to store it? - return ( 0, "Message Bounced", undef ) unless ($RT::StoreLoops); + #Do we actually want to store it? + return ( 0, "Message Bounced", undef ) unless ($RT::StoreLoops); + } } # }}} @@ -722,23 +538,17 @@ EOT # {{{ Squelch replies if necessary # Don't let the user stuff the RT-Squelch-Replies-To header. if ( $head->get('RT-Squelch-Replies-To') ) { - $head->add( - 'RT-Relocated-Squelch-Replies-To', - $head->get('RT-Squelch-Replies-To') - ); + $head->add( 'RT-Relocated-Squelch-Replies-To', + $head->get('RT-Squelch-Replies-To') ); $head->delete('RT-Squelch-Replies-To'); } if ($SquelchReplies) { + ## TODO: This is a hack. It should be some other way to + ## indicate that the transaction should be "silent". - # Squelch replies to the sender, and also leave a clue to - # allow us to squelch ALL outbound messages. This way we - # can punt the logic of "what to do when we get a bounce" - # to the scrip. We might want to notify nobody. Or just - # the RT Owner. Or maybe all Privileged watchers. my ( $Sender, $junk ) = ParseSenderAddressFromHead($head); $head->add( 'RT-Squelch-Replies-To', $Sender ); - $head->add( 'RT-DetectedAutoGenerated', 'true' ); } # }}} @@ -746,8 +556,7 @@ EOT my $Ticket = RT::Ticket->new($CurrentUser); # {{{ If we don't have a ticket Id, we're creating a new ticket - if ( (!$SystemTicket || !$SystemTicket->Id) && - grep /^(comment|correspond)$/, @actions ) { + if ( !$args{'ticket'} ) { # {{{ Create a new ticket @@ -755,139 +564,81 @@ EOT my @Requestors = ( $CurrentUser->id ); if ($RT::ParseNewMessageForTicketCcs) { - @Cc = ParseCcAddressesFromHead( - Head => $head, - CurrentUser => $CurrentUser, - QueueObj => $SystemQueueObj - ); + @Cc = ParseCcAddressesFromHead( Head => $head, + CurrentUser => $CurrentUser, + QueueObj => $SystemQueueObj ); } my ( $id, $Transaction, $ErrStr ) = $Ticket->Create( - Queue => $SystemQueueObj->Id, - Subject => $Subject, - Requestor => \@Requestors, - Cc => \@Cc, - MIMEObj => $Message - ); + Queue => $SystemQueueObj->Id, + Subject => $Subject, + Requestor => \@Requestors, + Cc => \@Cc, + MIMEObj => $Message ); if ( $id == 0 ) { - MailError( - To => $ErrorsTo, - Subject => "Ticket creation failed", - Explanation => $ErrStr, - MIMEObj => $Message - ); + MailError( To => $ErrorsTo, + Subject => "Ticket creation failed", + Explanation => $ErrStr, + MIMEObj => $Message ); $RT::Logger->error("Create failed: $id / $Transaction / $ErrStr "); return ( 0, "Ticket creation failed", $Ticket ); } - # strip comments&corresponds from the actions we don't need record twice - @actions = grep !/^(comment|correspond)$/, @actions; - $args{'ticket'} = $id; # }}} } - $Ticket->Load( $args{'ticket'} ); - unless ( $Ticket->Id ) { - my $message = "Could not find a ticket with id " . $args{'ticket'}; - MailError( - To => $ErrorsTo, - Subject => "Message not recorded", - Explanation => $message, - MIMEObj => $Message - ); - - return ( 0, $message ); - } - # }}} - foreach my $action( @actions ) { - # If the action is comment, add a comment. - if ( $action =~ /^(comment|correspond)$/i ) { - my ( $status, $msg ); - if ( $action =~ /^correspond$/i ) { - ( $status, $msg ) = $Ticket->Correspond( MIMEObj => $Message ); - } - else { - ( $status, $msg ) = $Ticket->Comment( MIMEObj => $Message ); - } - unless ($status) { - - #Warn the sender that we couldn't actually submit the comment. - MailError( - To => $ErrorsTo, - Subject => "Message not recorded", - Explanation => $msg, - MIMEObj => $Message - ); - return ( 0, "Message not recorded", $Ticket ); - } - } - elsif ($RT::UnsafeEmailCommands && $action =~ /^take$/i ) { - my ( $status, $msg ) = $Ticket->SetOwner( $CurrentUser->id ); - unless ($status) { - - #Warn the sender that we couldn't actually submit the comment. - MailError( - To => $ErrorsTo, - Subject => "Ticket not taken", - Explanation => $msg, - MIMEObj => $Message - ); - return ( 0, "Ticket not taken", $Ticket ); - } + + # If the action is comment, add a comment. + elsif ( $args{'action'} =~ /^(comment|correspond)$/i ) { + $Ticket->Load($args{'ticket'}); + unless ( $Ticket->Id ) { + my $message = "Could not find a ticket with id ".$args{'ticket'}; + MailError( To => $ErrorsTo, + Subject => "Message not recorded", + Explanation => $message, + MIMEObj => $Message ); + + return ( 0, $message); } - elsif ( $RT::UnsafeEmailCommands && $action =~ /^resolve$/i ) { - my ( $status, $msg ) = $Ticket->SetStatus( 'resolved' ); - unless ($status) { - #Warn the sender that we couldn't actually submit the comment. - MailError( - To => $ErrorsTo, - Subject => "Ticket not resolved", - Explanation => $msg, - MIMEObj => $Message - ); - return ( 0, "Ticket not resolved", $Ticket ); - } + + my ( $status, $msg ); + if ( $args{'action'} =~ /^correspond$/ ) { + ( $status, $msg ) = $Ticket->Correspond( MIMEObj => $Message ); } - else { - - #Return mail to the sender with an error - MailError( - To => $ErrorsTo, - Subject => "RT Configuration error", - Explanation => "'" - . $args{'action'} - . "' not a recognized action." - . " Your RT administrator has misconfigured " - . "the mail aliases which invoke RT", - MIMEObj => $Message - ); - $RT::Logger->crit( $args{'action'} . " type unknown for $MessageId" ); - return ( - -75, - "Configuration error: " - . $args{'action'} - . " not a recognized action", - $Ticket - ); - + ( $status, $msg ) = $Ticket->Comment( MIMEObj => $Message ); + } + unless ($status) { + + #Warn the sender that we couldn't actually submit the comment. + MailError( To => $ErrorsTo, + Subject => "Message not recorded", + Explanation => $msg, + MIMEObj => $Message ); + return ( 0, "Message not recorded", $Ticket ); } } - return ( 1, "Success", $Ticket ); -} + else { -sub IsCorrectAction -{ - my $action = shift; - my @actions = split /-/, $action; - foreach ( @actions ) { - return (0, $_) unless /^(?:comment|correspond|take|resolve)$/; - } - return (1, @actions); -} + #Return mail to the sender with an error + MailError( To => $ErrorsTo, + Subject => "RT Configuration error", + Explanation => "'" + . $args{'action'} + . "' not a recognized action." + . " Your RT administrator has misconfigured " + . "the mail aliases which invoke RT", + MIMEObj => $Message ); + $RT::Logger->crit( $args{'action'} . " type unknown for $MessageId" ); + return ( 0, "Configuration error: " . $args{'action'} . " not a recognized action", $Ticket ); + } + + +return ( 1, "Success", $Ticket ); +} eval "require RT::Interface::Email_Vendor"; die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email_Vendor.pm}); diff --git a/rt/lib/RT/Interface/Web.pm b/rt/lib/RT/Interface/Web.pm index 724d7e592..5097f54a4 100644 --- a/rt/lib/RT/Interface/Web.pm +++ b/rt/lib/RT/Interface/Web.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# CONTRIBUTION SUBMISSION POLICY: +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# (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 }}} +# END LICENSE BLOCK ## Portions Copyright 2000 Tobias Brox <tobix@fsck.com> ## This is a library of static subs to be used by the Mason web @@ -67,102 +45,94 @@ use strict; -# {{{ EscapeUTF8 -=head2 EscapeUTF8 SCALARREF -does a css-busting but minimalist escaping of whatever html you're passing in. +# {{{ sub NewApacheHandler -=cut +=head2 NewApacheHandler -sub EscapeUTF8 { - my $ref = shift; - return unless defined $$ref; - my $val = $$ref; - use bytes; - $val =~ s/&/&/g; - $val =~ s/</</g; - $val =~ s/>/>/g; - $val =~ s/\(/(/g; - $val =~ s/\)/)/g; - $val =~ s/"/"/g; - $val =~ s/'/'/g; - $$ref = $val; - Encode::_utf8_on($$ref); + Takes extra options to pass to HTML::Mason::ApacheHandler->new + Returns a new Mason::ApacheHandler object +=cut +sub NewApacheHandler { + require HTML::Mason::ApacheHandler; + my $ah = new HTML::Mason::ApacheHandler( + + comp_root => [ + [ local => $RT::MasonLocalComponentRoot ], + [ standard => $RT::MasonComponentRoot ] + ], + args_method => "CGI", + default_escape_flags => 'h', + allow_globals => [qw(%session)], + data_dir => "$RT::MasonDataDir", + @_ + ); + + $ah->interp->set_escape( h => \&RT::Interface::Web::EscapeUTF8 ); + + return ($ah); } # }}} -# {{{ EscapeURI +# {{{ sub NewCGIHandler -=head2 EscapeURI SCALARREF +=head2 NewCGIHandler -Escapes URI component according to RFC2396 + Returns a new Mason::CGIHandler object =cut -use Encode qw(); -sub EscapeURI { - my $ref = shift; - $$ref = Encode::encode_utf8( $$ref ); - $$ref =~ s/([^a-zA-Z0-9_.!~*'()-])/uc sprintf("%%%02X", ord($1))/eg; - Encode::_utf8_on( $$ref ); -} - -# }}} - -# {{{ WebCanonicalizeInfo +sub NewCGIHandler { + my %args = ( + @_ + ); -=head2 WebCanonicalizeInfo(); + my $handler = HTML::Mason::CGIHandler->new( + comp_root => [ + [ local => $RT::MasonLocalComponentRoot ], + [ standard => $RT::MasonComponentRoot ] + ], + data_dir => "$RT::MasonDataDir", + default_escape_flags => 'h', + allow_globals => [qw(%session)] + ); + -Different web servers set different environmental varibles. This -function must return something suitable for REMOTE_USER. By default, -just downcase $ENV{'REMOTE_USER'} + $handler->interp->set_escape( h => \&RT::Interface::Web::EscapeUTF8 ); -=cut -sub WebCanonicalizeInfo { - my $user; + return ($handler); - if ( defined $ENV{'REMOTE_USER'} ) { - $user = lc ( $ENV{'REMOTE_USER'} ) if( length($ENV{'REMOTE_USER'}) ); - } - - return $user; } - # }}} -# {{{ WebExternalAutoInfo - -=head2 WebExternalAutoInfo($user); - -Returns a hash of user attributes, used when WebExternalAuto is set. - -=cut -sub WebExternalAutoInfo { - my $user = shift; +# {{{ EscapeUTF8 - my %user_info; +=head2 EscapeUTF8 SCALARREF - $user_info{'Privileged'} = 1; +does a css-busting but minimalist escaping of whatever html you're passing in. - if ($^O !~ /^(?:riscos|MacOS|MSWin32|dos|os2)$/) { - # Populate fields with information from Unix /etc/passwd +=cut - my ($comments, $realname) = (getpwnam($user))[5, 6]; - $user_info{'Comments'} = $comments if defined $comments; - $user_info{'RealName'} = $realname if defined $realname; - } - elsif ($^O eq 'MSWin32' and eval 'use Net::AdminMisc; 1') { - # Populate fields with information from NT domain controller - } +sub EscapeUTF8 { + my $ref = shift; + my $val = $$ref; + use bytes; + $val =~ s/&/&/g; + $val =~ s/</</g; + $val =~ s/>/>/g; + $val =~ s/\(/(/g; + $val =~ s/\)/)/g; + $val =~ s/"/"/g; + $val =~ s/'/'/g; + $$ref = $val; + Encode::_utf8_on($$ref); - # and return the wad of stuff - return {%user_info}; } # }}} @@ -190,13 +160,10 @@ sub loc { UNIVERSAL::can($session{'CurrentUser'}, 'loc')){ return($session{'CurrentUser'}->loc(@_)); } - elsif ( my $u = eval { RT::CurrentUser->new($RT::SystemUser->Id) } ) { + else { + my $u = RT::CurrentUser->new($RT::SystemUser); return ($u->loc(@_)); } - else { - # pathetic case -- SystemUser is gone. - return $_[0]; - } } # }}} @@ -222,7 +189,7 @@ sub loc_fuzzy { return($session{'CurrentUser'}->loc_fuzzy($msg)); } else { - my $u = RT::CurrentUser->new($RT::SystemUser->Id); + my $u = RT::CurrentUser->new($RT::SystemUser); return ($u->loc_fuzzy($msg)); } } @@ -294,7 +261,6 @@ sub CreateTicket { } my %create_args = ( - Type => $ARGS{'Type'} || 'ticket', Queue => $ARGS{'Queue'}, Owner => $ARGS{'Owner'}, InitialPriority => $ARGS{'InitialPriority'}, @@ -311,81 +277,36 @@ sub CreateTicket { Starts => $starts->ISO, MIMEObj => $MIMEObj ); - foreach my $arg (keys %ARGS) { - my $cfid = $1; - + foreach my $arg (%ARGS) { + if ($arg =~ /^CustomField-(\d+)(.*?)$/) { next if ($arg =~ /-Magic$/); - #Object-RT::Ticket--CustomField-3-Values - if ($arg =~ /^Object-RT::Transaction--CustomField-/) { - $create_args{$arg} = $ARGS{$arg}; - } - elsif ($arg =~ /^Object-RT::Ticket--CustomField-(\d+)(.*?)$/) { - my $cfid = $1; - my $cf = RT::CustomField->new( $session{'CurrentUser'}); - $cf->Load($cfid); - - if ( $cf->Type eq 'Freeform' && ! $cf->SingleValue) { - $ARGS{$arg} =~ s/\r\n/\n/g; - $ARGS{$arg} = [split('\n', $ARGS{$arg})]; - } - - if ( $cf->Type =~ /text/i) { # Catch both Text and Wikitext - $ARGS{$arg} =~ s/\r//g; - } - - if ( $arg =~ /-Upload$/ ) { - $create_args{"CustomField-".$cfid} = _UploadedFile($arg); - } - else { - $create_args{"CustomField-".$cfid} = $ARGS{"$arg"}; - } + $create_args{"CustomField-".$1} = $ARGS{"$arg"}; } } - - - # XXX TODO This code should be about six lines. and badly needs refactoring. - - # {{{ turn new link lists into arrays, and pass in the proper arguments - my (@dependson, @dependedonby, @parents, @children, @refersto, @referredtoby); - - foreach my $luri ( split ( / /, $ARGS{"new-DependsOn"} ) ) { - $luri =~ s/\s*$//; # Strip trailing whitespace - push @dependson, $luri; - } - $create_args{'DependsOn'} = \@dependson; - - foreach my $luri ( split ( / /, $ARGS{"DependsOn-new"} ) ) { - push @dependedonby, $luri; - } - $create_args{'DependedOnBy'} = \@dependedonby; - - foreach my $luri ( split ( / /, $ARGS{"new-MemberOf"} ) ) { - $luri =~ s/\s*$//; # Strip trailing whitespace - push @parents, $luri; + my ( $id, $Trans, $ErrMsg ) = $Ticket->Create(%create_args); + unless ( $id && $Trans ) { + Abort($ErrMsg); } - $create_args{'Parents'} = \@parents; + my @linktypes = qw( DependsOn MemberOf RefersTo ); - foreach my $luri ( split ( / /, $ARGS{"MemberOf-new"} ) ) { - push @children, $luri; - } - $create_args{'Children'} = \@children; + foreach my $linktype (@linktypes) { + foreach my $luri ( split ( / /, $ARGS{"new-$linktype"} ) ) { + $luri =~ s/\s*$//; # Strip trailing whitespace + my ( $val, $msg ) = $Ticket->AddLink( + Target => $luri, + Type => $linktype + ); + push ( @Actions, $msg ) unless ($val); + } - foreach my $luri ( split ( / /, $ARGS{"new-RefersTo"} ) ) { - $luri =~ s/\s*$//; # Strip trailing whitespace - push @refersto, $luri; - } - $create_args{'RefersTo'} = \@refersto; + foreach my $luri ( split ( / /, $ARGS{"$linktype-new"} ) ) { + my ( $val, $msg ) = $Ticket->AddLink( + Base => $luri, + Type => $linktype + ); - foreach my $luri ( split ( / /, $ARGS{"RefersTo-new"} ) ) { - push @referredtoby, $luri; - } - $create_args{'ReferredToBy'} = \@referredtoby; - # }}} - - - my ( $id, $Trans, $ErrMsg ) = $Ticket->Create(%create_args); - unless ( $id && $Trans ) { - Abort($ErrMsg); + push ( @Actions, $msg ) unless ($val); + } } push ( @Actions, split("\n", $ErrMsg) ); @@ -444,10 +365,7 @@ sub ProcessUpdateMessage { ); #Make the update content have no 'weird' newlines in it - if ( $args{ARGSRef}->{'UpdateTimeWorked'} - || $args{ARGSRef}->{'UpdateContent'} - || $args{ARGSRef}->{'UpdateAttachments'} ) - { + if ( $args{ARGSRef}->{'UpdateContent'} ) { if ( $args{ARGSRef}->{'UpdateSubject'} eq $args{'TicketObj'}->Subject() ) @@ -456,76 +374,43 @@ sub ProcessUpdateMessage { } my $Message = MakeMIMEEntity( - Subject => $args{ARGSRef}->{'UpdateSubject'}, - Body => $args{ARGSRef}->{'UpdateContent'}, + Subject => $args{ARGSRef}->{'UpdateSubject'}, + Body => $args{ARGSRef}->{'UpdateContent'}, ); - $Message->head->add( 'Message-ID' => - "<rt-" - . $RT::VERSION . "-" - . $$ . "-" - . CORE::time() . "-" - . int(rand(2000)) . "." - . $args{'TicketObj'}->id . "-" - . "0" . "-" # Scrip - . "0" . "@" # Email sent - . $RT::Organization - . ">" ); - my $old_txn = RT::Transaction->new( $session{'CurrentUser'} ); - if ( $args{ARGSRef}->{'QuoteTransaction'} ) { - $old_txn->Load( $args{ARGSRef}->{'QuoteTransaction'} ); + if ($args{ARGSRef}->{'UpdateAttachments'}) { + $Message->make_multipart; + $Message->add_part($_) foreach values %{$args{ARGSRef}->{'UpdateAttachments'}}; } - else { - $old_txn = $args{TicketObj}->Transactions->First(); - } - - if ( $old_txn->Message && $old_txn->Message->First ) { - my @in_reply_to = split(/\s+/m, $old_txn->Message->First->GetHeader('In-Reply-To') || ''); - my @references = split(/\s+/m, $old_txn->Message->First->GetHeader('References') || '' ); - my @msgid = split(/\s+/m,$old_txn->Message->First->GetHeader('Message-ID') || ''); - my @rtmsgid = split(/\s+/m,$old_txn->Message->First->GetHeader('RT-Message-ID') || ''); - $Message->head->replace( 'In-Reply-To', join (' ', @rtmsgid ? @rtmsgid : @msgid)); - $Message->head->replace( 'References', join(' ', @references, @msgid, @rtmsgid)); + ## TODO: Implement public comments + if ( $args{ARGSRef}->{'UpdateType'} =~ /^(private|public)$/ ) { + my ( $Transaction, $Description ) = $args{TicketObj}->Comment( + CcMessageTo => $args{ARGSRef}->{'UpdateCc'}, + BccMessageTo => $args{ARGSRef}->{'UpdateBcc'}, + MIMEObj => $Message, + TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'} + ); + push ( @{ $args{Actions} }, $Description ); + } + elsif ( $args{ARGSRef}->{'UpdateType'} eq 'response' ) { + my ( $Transaction, $Description ) = $args{TicketObj}->Correspond( + CcMessageTo => $args{ARGSRef}->{'UpdateCc'}, + BccMessageTo => $args{ARGSRef}->{'UpdateBcc'}, + MIMEObj => $Message, + TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'} + ); + push ( @{ $args{Actions} }, $Description ); + } + else { + push ( @{ $args{'Actions'} }, + loc("Update type was neither correspondence nor comment."). + " ". + loc("Update not recorded.") + ); } - - if ( $args{ARGSRef}->{'UpdateAttachments'} ) { - $Message->make_multipart; - $Message->add_part($_) - foreach values %{ $args{ARGSRef}->{'UpdateAttachments'} }; - } - - ## TODO: Implement public comments - if ( $args{ARGSRef}->{'UpdateType'} =~ /^(private|public)$/ ) { - my ( $Transaction, $Description, $Object ) = $args{TicketObj}->Comment( - CcMessageTo => $args{ARGSRef}->{'UpdateCc'}, - BccMessageTo => $args{ARGSRef}->{'UpdateBcc'}, - MIMEObj => $Message, - TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'} - ); - push( @{ $args{Actions} }, $Description ); - $Object->UpdateCustomFields( ARGSRef => $args{ARGSRef} ) if $Object; - } - elsif ( $args{ARGSRef}->{'UpdateType'} eq 'response' ) { - my ( $Transaction, $Description, $Object ) = - $args{TicketObj}->Correspond( - CcMessageTo => $args{ARGSRef}->{'UpdateCc'}, - BccMessageTo => $args{ARGSRef}->{'UpdateBcc'}, - MIMEObj => $Message, - TimeTaken => $args{ARGSRef}->{'UpdateTimeWorked'} - ); - push( @{ $args{Actions} }, $Description ); - $Object->UpdateCustomFields( ARGSRef => $args{ARGSRef} ) if $Object; - } - else { - push( - @{ $args{'Actions'} }, - loc("Update type was neither correspondence nor comment.") . " " - . loc("Update not recorded.") - ); } } -} # }}} @@ -548,8 +433,7 @@ sub MakeMIMEEntity { Cc => undef, Body => undef, AttachmentFieldName => undef, -# map Encode::encode_utf8($_), @_, - @_, + map Encode::encode_utf8($_), @_, ); #Make the update content have no 'weird' newlines in it @@ -565,7 +449,6 @@ sub MakeMIMEEntity { Subject => $args{'Subject'} || "", From => $args{'From'}, Cc => $args{'Cc'}, - Charset => 'utf8', Data => [ $args{'Body'} ] ); } @@ -580,14 +463,7 @@ sub MakeMIMEEntity { #foreach my $filehandle (@filenames) { - my ( $fh, $temp_file ); - for ( 1 .. 10 ) { - # on NFS and NTFS, it is possible that tempfile() conflicts - # with other processes, causing a race condition. we try to - # accommodate this by pausing and retrying. - last if ($fh, $temp_file) = eval { tempfile( UNLINK => 1) }; - sleep 1; - } + my ( $fh, $temp_file ) = tempfile(); binmode $fh; #thank you, windows my ($buffer); @@ -605,7 +481,7 @@ sub MakeMIMEEntity { $Message->attach( Path => $temp_file, - Filename => Encode::decode_utf8($filename), + Filename => $filename, Type => $uploadinfo->{'Content-Type'}, ); close($fh); @@ -718,13 +594,13 @@ sub ProcessSearchQuery { # }}} # {{{ Limit requestor email - if ( $args{ARGS}->{'ValueOfWatcherRole'} ne '' ) { - $session{'tickets'}->LimitWatcher( - TYPE => $args{ARGS}->{'WatcherRole'}, - VALUE => $args{ARGS}->{'ValueOfWatcherRole'}, - OPERATOR => $args{ARGS}->{'WatcherRoleOp'}, + if ( $args{ARGS}->{'ValueOfRequestor'} ne '' ) { + my $alias = $session{'tickets'}->LimitRequestor( + VALUE => $args{ARGS}->{'ValueOfRequestor'}, + OPERATOR => $args{ARGS}->{'RequestorOp'}, ); + } # }}} @@ -869,6 +745,19 @@ sub ParseDateToISO { # }}} +# {{{ sub Config +# TODO: This might eventually read the cookies, user configuration +# information from the DB, queue configuration information from the +# DB, etc. + +sub Config { + my $args = shift; + my $key = shift; + return $args->{$key} || $RT::WebOptions{$key}; +} + +# }}} + # {{{ sub ProcessACLChanges sub ProcessACLChanges { @@ -891,13 +780,17 @@ sub ProcessACLChanges { my $obj; - if ($object_type eq 'RT::System') { - $obj = $RT::System; - } elsif ($RT::ACE::OBJECT_TYPES{$object_type}) { - $obj = $object_type->new($session{'CurrentUser'}); + if ($object_type eq 'RT::Queue') { + $obj = RT::Queue->new($session{'CurrentUser'}); + $obj->Load($object_id); + } elsif ($object_type eq 'RT::Group') { + $obj = RT::Group->new($session{'CurrentUser'}); $obj->Load($object_id); + + } elsif ($object_type eq 'RT::System') { + $obj = $RT::System; } else { - push (@results, loc("System Error"). ': '. + push (@results, loc("System Error"). loc("Rights could not be granted for [_1]", $object_type)); next; } @@ -920,13 +813,17 @@ sub ProcessACLChanges { next unless ($right); my $obj; - if ($object_type eq 'RT::System') { - $obj = $RT::System; - } elsif ($RT::ACE::OBJECT_TYPES{$object_type}) { - $obj = $object_type->new($session{'CurrentUser'}); + if ($object_type eq 'RT::Queue') { + $obj = RT::Queue->new($session{'CurrentUser'}); + $obj->Load($object_id); + } elsif ($object_type eq 'RT::Group') { + $obj = RT::Group->new($session{'CurrentUser'}); $obj->Load($object_id); + + } elsif ($object_type eq 'RT::System') { + $obj = $RT::System; } else { - push (@results, loc("System Error"). ': '. + push (@results, loc("System Error"). loc("Rights could not be revoked for [_1]", $object_type)); next; } @@ -962,12 +859,52 @@ sub UpdateRecordObject { @_ ); - my $Object = $args{'Object'}; - my @results = $Object->Update(AttributesRef => $args{'AttributesRef'}, - ARGSRef => $args{'ARGSRef'}, - AttributePrefix => $args{'AttributePrefix'} - ); + my (@results); + + my $object = $args{'Object'}; + my $attributes = $args{'AttributesRef'}; + my $ARGSRef = $args{'ARGSRef'}; + foreach my $attribute (@$attributes) { + my $value; + if ( defined $ARGSRef->{$attribute} ) { + $value = $ARGSRef->{$attribute}; + } + elsif ( + defined( $args{'AttributePrefix'} ) + && defined( + $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute } + ) + ) { + $value = $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute }; + + } else { + next; + } + $value =~ s/\r\n/\n/gs; + + if ($value ne $object->$attribute()){ + + my $method = "Set$attribute"; + my ( $code, $msg ) = $object->$method($value); + + push @results, loc($attribute) . ': ' . loc_fuzzy($msg); +=for loc + "[_1] could not be set to [_2].", # loc + "That is already the current value", # loc + "No value sent to _Set!\n", # loc + "Illegal value for [_1]", # loc + "The new value has been set.", # loc + "No column specified", # loc + "Immutable field", # loc + "Nonexistant field?", # loc + "Invalid data", # loc + "Couldn't find row", # loc + "Missing a primary key?: [_1]", # loc + "Found Object", # loc +=cut + }; + } return (@results); } @@ -1016,17 +953,6 @@ sub ProcessCustomFieldUpdates { my ( $err, $msg ) = $Object->DeleteValue($id); push ( @results, $msg ); } - - my $vals = $Object->Values(); - while (my $cfv = $vals->Next()) { - if (my $so = $ARGSRef->{ 'CustomField-' . $Object->Id . '-SortOrder' . $cfv->Id }) { - if ($cfv->SortOrder != $so) { - my ( $err, $msg ) = $cfv->SetSortOrder($so); - push ( @results, $msg ); - } - } - } - return (@results); } @@ -1059,7 +985,6 @@ sub ProcessTicketBasics { TimeEstimated TimeWorked TimeLeft - Type Status Queue ); @@ -1072,11 +997,6 @@ sub ProcessTicketBasics { } } - - # Status isn't a field that can be set to a null value. - # RT core complains if you try - delete $ARGSRef->{'Status'} unless ($ARGSRef->{'Status'}); - my @results = UpdateRecordObject( AttributesRef => \@attribs, Object => $TicketObj, @@ -1105,158 +1025,109 @@ sub ProcessTicketBasics { # }}} -sub ProcessTicketCustomFieldUpdates { - my %args = @_; - $args{'Object'} = delete $args{'TicketObj'}; - my $ARGSRef = { %{ $args{'ARGSRef'} } }; +# {{{ Sub ProcessTicketCustomFieldUpdates - # Build up a list of objects that we want to work with - my %custom_fields_to_mod; - foreach my $arg ( keys %$ARGSRef ) { - if ( $arg =~ /^Ticket-(\d+-.*)/) { - $ARGSRef->{"Object-RT::Ticket-$1"} = delete $ARGSRef->{$arg}; - } - elsif ( $arg =~ /^CustomField-(\d+-.*)/) { - $ARGSRef->{"Object-RT::Ticket--$1"} = delete $ARGSRef->{$arg}; - } - } +sub ProcessTicketCustomFieldUpdates { + my %args = ( + ARGSRef => undef, + @_ + ); - return ProcessObjectCustomFieldUpdates(%args, ARGSRef => $ARGSRef); -} + my @results; -sub ProcessObjectCustomFieldUpdates { - my %args = @_; my $ARGSRef = $args{'ARGSRef'}; - my @results; - # Build up a list of objects that we want to work with + # Build up a list of tickets that we want to work with + my %tickets_to_mod; my %custom_fields_to_mod; - foreach my $arg ( keys %$ARGSRef ) { - if ( $arg =~ /^Object-([\w:]+)-(\d*)-CustomField-(\d+)-/ ) { - # For each of those objects, find out what custom fields we want to work with. - $custom_fields_to_mod{$1}{$2 || $args{'Object'}->Id}{$3} = 1; + foreach my $arg ( keys %{$ARGSRef} ) { + if ( $arg =~ /^Ticket-(\d+)-CustomField-(\d+)-/ ) { + + # For each of those tickets, find out what custom fields we want to work with. + $custom_fields_to_mod{$1}{$2} = 1; } } - # For each of those objects - foreach my $class ( keys %custom_fields_to_mod ) { - foreach my $id ( keys %{$custom_fields_to_mod{$class}} ) { - my $Object = $args{'Object'}; - if (!$Object or ref($Object) ne $class or $Object->id != $id) { - $Object = $class->new( $session{'CurrentUser'} ); - $Object->Load($id); - } - - # For each custom field - foreach my $cf ( keys %{ $custom_fields_to_mod{$class}{$id} } ) { - my $CustomFieldObj = RT::CustomField->new($session{'CurrentUser'}); - $CustomFieldObj->LoadById($cf); - - foreach my $arg ( keys %{$ARGSRef} ) { - # Only interested in args for the current CF: - next unless ( $arg =~ /^Object-$class-(?:$id)?-CustomField-$cf-/ ); - - # since http won't pass in a form element with a null value, we need - # to fake it - if ($arg =~ /^(.*?)-Values-Magic$/ ) { - # We don't care about the magic, if there's really a values element; - next if ($ARGSRef->{$1.'-Value'} || $ARGSRef->{$1.'-Values'}) ; + # For each of those tickets + foreach my $tick ( keys %custom_fields_to_mod ) { + my $Ticket = RT::Ticket->new( $session{'CurrentUser'} ); + $Ticket->Load($tick); - # "Empty" values does not mean anything for Image and Binary fields - next if $CustomFieldObj->Type =~ /^(?:Image|Binary)$/; - - $arg = $1."-Values"; - $ARGSRef->{$1."-Values"} = undef; - - } - my @values = (); - if (ref( $ARGSRef->{$arg} ) eq 'ARRAY' ) { - @values = @{ $ARGSRef->{$arg} }; - } elsif ($CustomFieldObj->Type =~ /text/i) { # Both Text and Wikitext - @values = ($ARGSRef->{$arg}); - } else { - @values = split /\n/, $ARGSRef->{$arg}; - } - - if ( ($CustomFieldObj->Type eq 'Freeform' - && ! $CustomFieldObj->SingleValue) || - $CustomFieldObj->Type =~ /text/i) { - foreach my $val (@values) { - $val =~ s/\r//g; - } - } + # For each custom field + foreach my $cf ( keys %{ $custom_fields_to_mod{$tick} } ) { - if ( ( $arg =~ /-AddValue$/ ) || ( $arg =~ /-Value$/ ) ) { - foreach my $value (@values) { - next unless length($value); - my ( $val, $msg ) = $Object->AddCustomFieldValue( - Field => $cf, - Value => $value - ); - push ( @results, $msg ); - } - } - elsif ( $arg =~ /-Upload$/ ) { - my $value_hash = _UploadedFile($arg) or next; + my $CustomFieldObj = RT::CustomField->new($session{'CurrentUser'}); + $CustomFieldObj->LoadById($cf); - my ( $val, $msg ) = $Object->AddCustomFieldValue( - %$value_hash, + foreach my $arg ( keys %{$ARGSRef} ) { + # since http won't pass in a form element with a null value, we need + # to fake it + if ($arg =~ /^(.*?)-Values-Magic$/ ) { + # We don't care about the magic, if there's really a values element; + next if (exists $ARGSRef->{$1.'-Values'}) ; + + $arg = $1."-Values"; + $ARGSRef->{$1."-Values"} = undef; + + } + next unless ( $arg =~ /^Ticket-$tick-CustomField-$cf-/ ); + my @values = + ( ref( $ARGSRef->{$arg} ) eq 'ARRAY' ) + ? @{ $ARGSRef->{$arg} } + : ( $ARGSRef->{$arg} ); + if ( ( $arg =~ /-AddValue$/ ) || ( $arg =~ /-Value$/ ) ) { + foreach my $value (@values) { + next unless ($value); + my ( $val, $msg ) = $Ticket->AddCustomFieldValue( Field => $cf, - ); - push ( @results, $msg ); - } - elsif ( $arg =~ /-DeleteValues$/ ) { - foreach my $value (@values) { - next unless length($value); - my ( $val, $msg ) = $Object->DeleteCustomFieldValue( - Field => $cf, - Value => $value - ); - push ( @results, $msg ); - } - } - elsif ( $arg =~ /-DeleteValueIds$/ ) { - foreach my $value (@values) { - next unless length($value); - my ( $val, $msg ) = $Object->DeleteCustomFieldValue( - Field => $cf, - ValueId => $value, - ); - push ( @results, $msg ); - } - } - elsif ( $arg =~ /-Values$/ and !$CustomFieldObj->Repeated) { - my $cf_values = $Object->CustomFieldValues($cf); - - my %values_hash; - foreach my $value (@values) { - next unless length($value); - - # build up a hash of values that the new set has - $values_hash{$value} = 1; - - unless ( $cf_values->HasEntry($value) ) { - my ( $val, $msg ) = $Object->AddCustomFieldValue( - Field => $cf, - Value => $value - ); - push ( @results, $msg ); - } - - } - while ( my $cf_value = $cf_values->Next ) { - unless ( $values_hash{ $cf_value->Content } == 1 ) { - my ( $val, $msg ) = $Object->DeleteCustomFieldValue( - Field => $cf, - Value => $cf_value->Content - ); - push ( @results, $msg); - - } - } - } - elsif ( $arg =~ /-Values$/ ) { - my $cf_values = $Object->CustomFieldValues($cf); + Value => $value + ); + push ( @results, $msg ); + } + } + elsif ( $arg =~ /-DeleteValues$/ ) { + foreach my $value (@values) { + next unless ($value); + my ( $val, $msg ) = $Ticket->DeleteCustomFieldValue( + Field => $cf, + Value => $value + ); + push ( @results, $msg ); + } + } + elsif ( $arg =~ /-Values$/ and $CustomFieldObj->Type !~ /Entry/) { + my $cf_values = $Ticket->CustomFieldValues($cf); + + my %values_hash; + foreach my $value (@values) { + next unless ($value); + + # build up a hash of values that the new set has + $values_hash{$value} = 1; + + unless ( $cf_values->HasEntry($value) ) { + my ( $val, $msg ) = $Ticket->AddCustomFieldValue( + Field => $cf, + Value => $value + ); + push ( @results, $msg ); + } + + } + while ( my $cf_value = $cf_values->Next ) { + unless ( $values_hash{ $cf_value->Content } == 1 ) { + my ( $val, $msg ) = $Ticket->DeleteCustomFieldValue( + Field => $cf, + Value => $cf_value->Content + ); + push ( @results, $msg); + + } + + } + } + elsif ( $arg =~ /-Values$/ ) { + my $cf_values = $Ticket->CustomFieldValues($cf); # keep everything up to the point of difference, delete the rest my $delete_flag; @@ -1272,23 +1143,24 @@ sub ProcessObjectCustomFieldUpdates { # now add/replace extra things, if any foreach my $value (@values) { - my ( $val, $msg ) = $Object->AddCustomFieldValue( + my ( $val, $msg ) = $Ticket->AddCustomFieldValue( Field => $cf, Value => $value ); push ( @results, $msg ); } } - else { - push ( @results, loc("User asked for an unknown update type for custom field [_1] for [_2] object #[_3]", $cf->Name, $class, $Object->id ) ); - } - } - } - return (@results); - } + else { + push ( @results, "User asked for an unknown update type for custom field " . $cf->Name . " for ticket " . $Ticket->id ); + } + } + } + return (@results); } } +# }}} + # {{{ sub ProcessTicketWatchers =head2 ProcessTicketWatchers ( TicketObj => $Ticket, ARGSRef => \%ARGS ); @@ -1313,7 +1185,7 @@ sub ProcessTicketWatchers { foreach my $key ( keys %$ARGSRef ) { # {{{ Delete deletable watchers - if ( ( $key =~ /^Ticket-DeleteWatcher-Type-(.*)-Principal-(\d+)$/ ) ) { + if ( ( $key =~ /^Ticket-DelWatcher-Type-(.*)-Principal-(\d+)$/ ) ) { my ( $code, $msg ) = $Ticket->DeleteWatcher(PrincipalId => $2, Type => $1); @@ -1321,8 +1193,8 @@ sub ProcessTicketWatchers { } # Delete watchers in the simple style demanded by the bulk manipulator - elsif ( $key =~ /^Delete(Requestor|Cc|AdminCc)$/ ) { - my ( $code, $msg ) = $Ticket->DeleteWatcher( Email => $ARGSRef->{$key}, Type => $1 ); + elsif ( $key =~ /^Delete(Requestor|Cc|AdminCc)$/ ) { + my ( $code, $msg ) = $Ticket->DeleteWatcher( Type => $ARGSRef->{$key}, PrincipalId => $1 ); push @results, $msg; } @@ -1442,30 +1314,6 @@ sub ProcessTicketLinks { my $Ticket = $args{'TicketObj'}; my $ARGSRef = $args{'ARGSRef'}; - - my (@results) = ProcessRecordLinks(RecordObj => $Ticket, - ARGSRef => $ARGSRef); - - #Merge if we need to - if ( $ARGSRef->{ $Ticket->Id . "-MergeInto" } ) { - my ( $val, $msg ) = - $Ticket->MergeInto( $ARGSRef->{ $Ticket->Id . "-MergeInto" } ); - push @results, $msg; - } - - return (@results); -} - -# }}} - -sub ProcessRecordLinks { - my %args = ( RecordObj => undef, - ARGSRef => undef, - @_ ); - - my $Record = $args{'RecordObj'}; - my $ARGSRef = $args{'ARGSRef'}; - my (@results); # Delete links that are gone gone gone. @@ -1477,7 +1325,7 @@ sub ProcessRecordLinks { push @results, "Trying to delete: Base: $base Target: $target Type $type"; - my ( $val, $msg ) = $Record->DeleteLink( Base => $base, + my ( $val, $msg ) = $Ticket->DeleteLink( Base => $base, Type => $type, Target => $target ); @@ -1490,18 +1338,18 @@ sub ProcessRecordLinks { my @linktypes = qw( DependsOn MemberOf RefersTo ); foreach my $linktype (@linktypes) { - if ( $ARGSRef->{ $Record->Id . "-$linktype" } ) { - for my $luri ( split ( / /, $ARGSRef->{ $Record->Id . "-$linktype" } ) ) { + if ( $ARGSRef->{ $Ticket->Id . "-$linktype" } ) { + for my $luri ( split ( / /, $ARGSRef->{ $Ticket->Id . "-$linktype" } ) ) { $luri =~ s/\s*$//; # Strip trailing whitespace - my ( $val, $msg ) = $Record->AddLink( Target => $luri, + my ( $val, $msg ) = $Ticket->AddLink( Target => $luri, Type => $linktype ); push @results, $msg; } } - if ( $ARGSRef->{ "$linktype-" . $Record->Id } ) { + if ( $ARGSRef->{ "$linktype-" . $Ticket->Id } ) { - for my $luri ( split ( / /, $ARGSRef->{ "$linktype-" . $Record->Id } ) ) { - my ( $val, $msg ) = $Record->AddLink( Base => $luri, + for my $luri ( split ( / /, $ARGSRef->{ "$linktype-" . $Ticket->Id } ) ) { + my ( $val, $msg ) = $Ticket->AddLink( Base => $luri, Type => $linktype ); push @results, $msg; @@ -1509,36 +1357,17 @@ sub ProcessRecordLinks { } } + #Merge if we need to + if ( $ARGSRef->{ $Ticket->Id . "-MergeInto" } ) { + my ( $val, $msg ) = + $Ticket->MergeInto( $ARGSRef->{ $Ticket->Id . "-MergeInto" } ); + push @results, $msg; + } + return (@results); } - -=head2 _UploadedFile ( $arg ); - -Takes a CGI parameter name; if a file is uploaded under that name, -return a hash reference suitable for AddCustomFieldValue's use: -C<( Value => $filename, LargeContent => $content, ContentType => $type )>. - -Returns C<undef> if no files were uploaded in the C<$arg> field. - -=cut - -sub _UploadedFile { - my $arg = shift; - my $cgi_object = $m->cgi_object; - my $fh = $cgi_object->upload($arg) or return undef; - my $upload_info = $cgi_object->uploadInfo($fh); - - my $filename = "$fh"; - $filename =~ s#^.*[\\/]##; - binmode($fh); - - return { - Value => $filename, - LargeContent => do { local $/; scalar <$fh> }, - ContentType => $upload_info->{'Content-Type'}, - }; -} +# }}} eval "require RT::Interface::Web_Vendor"; die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web_Vendor.pm}); diff --git a/rt/lib/RT/Interface/Web_Vendor.pm b/rt/lib/RT/Interface/Web_Vendor.pm new file mode 100644 index 000000000..5be20e6b9 --- /dev/null +++ b/rt/lib/RT/Interface/Web_Vendor.pm @@ -0,0 +1,95 @@ +# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am> +# +# 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. + +=head1 NAME + +RT::Interface::Web_Vendor + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +Freeside vendor overlay for RT::Interface::Web. + +=begin testing + +use_ok(RT::Interface::Web_Vendor); + +=end testing + +=cut + +#package RT::Interface::Web; +#use strict; + +package HTML::Mason::Commands; +use strict; + +=head2 ProcessTicketCustomers + +=cut + +sub ProcessTicketCustomers { + my %args = ( + TicketObj => undef, + ARGSRef => undef, + @_ + ); + my @results = (); + + my $Ticket = $args{'TicketObj'}; + my $ARGSRef = $args{'ARGSRef'}; + + ### false laziness w/RT::Interface::Web::ProcessTicketLinks + # Delete links that are gone gone gone. + foreach my $arg ( keys %$ARGSRef ) { + if ( $arg =~ /DeleteLink-(.*?)-(DependsOn|MemberOf|RefersTo)-(.*)$/ ) { + my $base = $1; + my $type = $2; + my $target = $3; + + push @results, + "Trying to delete: Base: $base Target: $target Type $type"; + my ( $val, $msg ) = $Ticket->DeleteLink( Base => $base, + Type => $type, + Target => $target ); + + push @results, $msg; + + } + + } + ### + + my @delete_custnums = + map { /^Ticket-AddCustomer-(\d+)$/; $1 } + grep { /^Ticket-AddCustomer-(\d+)$/ && $ARGSRef->{$_} } + keys %$ARGSRef; + + my @custnums = map { /^Ticket-AddCustomer-(\d+)$/; $1 } + grep { /^Ticket-AddCustomer-(\d+)$/ && $ARGSRef->{$_} } + keys %$ARGSRef; + + foreach my $custnum ( @custnums ) { + my( $val, $msg ) = + $Ticket->AddLink( 'Type' => 'MemberOf', + 'Target' => "freeside://freeside/cust_main/$custnum", + ); + push @results, $msg; + } + + return @results; + +} + +1; + diff --git a/rt/lib/RT/Link.pm b/rt/lib/RT/Link.pm index cc68aa61d..962c378a8 100644 --- a/rt/lib/RT/Link.pm +++ b/rt/lib/RT/Link.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -83,7 +61,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -120,7 +98,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -129,14 +107,14 @@ Returns the current value of id. =cut -=head2 Base +=item Base Returns the current value of Base. (In the database, Base is stored as varchar(240).) -=head2 SetBase VALUE +=item SetBase VALUE Set Base to VALUE. @@ -147,14 +125,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Target +=item Target Returns the current value of Target. (In the database, Target is stored as varchar(240).) -=head2 SetTarget VALUE +=item SetTarget VALUE Set Target to VALUE. @@ -165,14 +143,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Type +=item Type Returns the current value of Type. (In the database, Type is stored as varchar(20).) -=head2 SetType VALUE +=item SetType VALUE Set Type to VALUE. @@ -183,14 +161,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 LocalTarget +=item LocalTarget Returns the current value of LocalTarget. (In the database, LocalTarget is stored as int(11).) -=head2 SetLocalTarget VALUE +=item SetLocalTarget VALUE Set LocalTarget to VALUE. @@ -201,14 +179,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 LocalBase +=item LocalBase Returns the current value of LocalBase. (In the database, LocalBase is stored as int(11).) -=head2 SetLocalBase VALUE +=item SetLocalBase VALUE Set LocalBase to VALUE. @@ -219,7 +197,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 LastUpdatedBy +=item LastUpdatedBy Returns the current value of LastUpdatedBy. (In the database, LastUpdatedBy is stored as int(11).) @@ -228,7 +206,7 @@ Returns the current value of LastUpdatedBy. =cut -=head2 LastUpdated +=item LastUpdated Returns the current value of LastUpdated. (In the database, LastUpdated is stored as datetime.) @@ -237,7 +215,7 @@ Returns the current value of LastUpdated. =cut -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -246,7 +224,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -256,29 +234,29 @@ Returns the current value of Created. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, Base => - {read => 1, write => 1, sql_type => 12, length => 240, is_blob => 0, is_numeric => 0, type => 'varchar(240)', default => ''}, + {read => 1, write => 1, type => 'varchar(240)', default => ''}, Target => - {read => 1, write => 1, sql_type => 12, length => 240, is_blob => 0, is_numeric => 0, type => 'varchar(240)', default => ''}, + {read => 1, write => 1, type => 'varchar(240)', default => ''}, Type => - {read => 1, write => 1, sql_type => 12, length => 20, is_blob => 0, is_numeric => 0, type => 'varchar(20)', default => ''}, + {read => 1, write => 1, type => 'varchar(20)', default => ''}, LocalTarget => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, LocalBase => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, LastUpdatedBy => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, LastUpdated => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, } }; @@ -310,7 +288,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Links.pm b/rt/lib/RT/Links.pm index 3626e2292..7a1773af9 100644 --- a/rt/lib/RT/Links.pm +++ b/rt/lib/RT/Links.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::Link item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Queue.pm b/rt/lib/RT/Queue.pm index 23839d4d9..b362c9f0d 100755 --- a/rt/lib/RT/Queue.pm +++ b/rt/lib/RT/Queue.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -83,7 +61,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -129,7 +107,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -138,14 +116,14 @@ Returns the current value of id. =cut -=head2 Name +=item Name Returns the current value of Name. (In the database, Name is stored as varchar(200).) -=head2 SetName VALUE +=item SetName VALUE Set Name to VALUE. @@ -156,14 +134,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Description +=item Description Returns the current value of Description. (In the database, Description is stored as varchar(255).) -=head2 SetDescription VALUE +=item SetDescription VALUE Set Description to VALUE. @@ -174,14 +152,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 CorrespondAddress +=item CorrespondAddress Returns the current value of CorrespondAddress. (In the database, CorrespondAddress is stored as varchar(120).) -=head2 SetCorrespondAddress VALUE +=item SetCorrespondAddress VALUE Set CorrespondAddress to VALUE. @@ -192,14 +170,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 CommentAddress +=item CommentAddress Returns the current value of CommentAddress. (In the database, CommentAddress is stored as varchar(120).) -=head2 SetCommentAddress VALUE +=item SetCommentAddress VALUE Set CommentAddress to VALUE. @@ -210,14 +188,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 InitialPriority +=item InitialPriority Returns the current value of InitialPriority. (In the database, InitialPriority is stored as int(11).) -=head2 SetInitialPriority VALUE +=item SetInitialPriority VALUE Set InitialPriority to VALUE. @@ -228,14 +206,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 FinalPriority +=item FinalPriority Returns the current value of FinalPriority. (In the database, FinalPriority is stored as int(11).) -=head2 SetFinalPriority VALUE +=item SetFinalPriority VALUE Set FinalPriority to VALUE. @@ -246,14 +224,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 DefaultDueIn +=item DefaultDueIn Returns the current value of DefaultDueIn. (In the database, DefaultDueIn is stored as int(11).) -=head2 SetDefaultDueIn VALUE +=item SetDefaultDueIn VALUE Set DefaultDueIn to VALUE. @@ -264,7 +242,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -273,7 +251,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -282,7 +260,7 @@ Returns the current value of Created. =cut -=head2 LastUpdatedBy +=item LastUpdatedBy Returns the current value of LastUpdatedBy. (In the database, LastUpdatedBy is stored as int(11).) @@ -291,7 +269,7 @@ Returns the current value of LastUpdatedBy. =cut -=head2 LastUpdated +=item LastUpdated Returns the current value of LastUpdated. (In the database, LastUpdated is stored as datetime.) @@ -300,14 +278,14 @@ Returns the current value of LastUpdated. =cut -=head2 Disabled +=item Disabled Returns the current value of Disabled. (In the database, Disabled is stored as smallint(6).) -=head2 SetDisabled VALUE +=item SetDisabled VALUE Set Disabled to VALUE. @@ -319,35 +297,35 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, Name => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, type => 'varchar(200)', default => ''}, Description => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, CorrespondAddress => - {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''}, + {read => 1, write => 1, type => 'varchar(120)', default => ''}, CommentAddress => - {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''}, + {read => 1, write => 1, type => 'varchar(120)', default => ''}, InitialPriority => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, FinalPriority => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, DefaultDueIn => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, LastUpdatedBy => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, LastUpdated => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, Disabled => - {read => 1, write => 1, sql_type => 5, length => 6, is_blob => 0, is_numeric => 1, type => 'smallint(6)', default => '0'}, + {read => 1, write => 1, type => 'smallint(6)', default => '0'}, } }; @@ -379,7 +357,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Queues.pm b/rt/lib/RT/Queues.pm index a7020812f..60aec9086 100755 --- a/rt/lib/RT/Queues.pm +++ b/rt/lib/RT/Queues.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::Queue item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Record.pm b/rt/lib/RT/Record.pm index 341d88bfc..6962221ea 100755 --- a/rt/lib/RT/Record.pm +++ b/rt/lib/RT/Record.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,30 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} - +# END LICENSE BLOCK =head1 NAME RT::Record - Base class for RT record objects @@ -67,12 +44,12 @@ ok (require RT::Record); package RT::Record; use RT::Date; use RT::User; -use RT::Attributes; + use RT::Base; use DBIx::SearchBuilder::Record::Cachable; use strict; -use vars qw/@ISA $_TABLE_ATTR/; +use vars qw/@ISA/; @ISA = qw(RT::Base); @@ -87,8 +64,8 @@ if ($RT::DontCacheSearchBuilderRecords ) { sub _Init { my $self = shift; - $self->_BuildTableAttributes unless ($_TABLE_ATTR->{ref($self)}); $self->CurrentUser(@_); + } # }}} @@ -108,146 +85,6 @@ sub _PrimaryKeys { # }}} -=head2 Delete - -Delete this record object from the database. - -=cut - -sub Delete { - my $self = shift; - my ($rv) = $self->SUPER::Delete; - if ($rv) { - return ($rv, $self->loc("Object deleted")); - } else { - - return(0, $self->loc("Object could not be deleted")) - } -} - -=head2 ObjectTypeStr - -Returns a string which is this object's type. The type is the class, -without the "RT::" prefix. - -=begin testing - -my $ticket = RT::Ticket->new($RT::SystemUser); -my $group = RT::Group->new($RT::SystemUser); -is($ticket->ObjectTypeStr, 'Ticket', "Ticket returns correct typestring"); -is($group->ObjectTypeStr, 'Group', "Group returns correct typestring"); - -=end testing - -=cut - -sub ObjectTypeStr { - my $self = shift; - if (ref($self) =~ /^.*::(\w+)$/) { - return $self->loc($1); - } else { - return $self->loc(ref($self)); - } -} - -=head2 Attributes - -Return this object's attributes as an RT::Attributes object - -=cut - -sub Attributes { - my $self = shift; - - unless ($self->{'attributes'}) { - $self->{'attributes'} = RT::Attributes->new($self->CurrentUser); - $self->{'attributes'}->LimitToObject($self); - } - return ($self->{'attributes'}); - -} - - -=head2 AddAttribute { Name, Description, Content } - -Adds a new attribute for this object. - -=cut - -sub AddAttribute { - my $self = shift; - my %args = ( Name => undef, - Description => undef, - Content => undef, - @_ ); - - my $attr = RT::Attribute->new( $self->CurrentUser ); - my ( $id, $msg ) = $attr->Create( - Object => $self, - Name => $args{'Name'}, - Description => $args{'Description'}, - Content => $args{'Content'} ); - - - # XXX TODO: Why won't RedoSearch work here? - $self->Attributes->_DoSearch; - - return ($id, $msg); -} - - -=head2 SetAttribute { Name, Description, Content } - -Like AddAttribute, but replaces all existing attributes with the same Name. - -=cut - -sub SetAttribute { - my $self = shift; - my %args = ( Name => undef, - Description => undef, - Content => undef, - @_ ); - - my @AttributeObjs = $self->Attributes->Named( $args{'Name'} ) - or return $self->AddAttribute( %args ); - - my $AttributeObj = pop( @AttributeObjs ); - $_->Delete foreach @AttributeObjs; - - $AttributeObj->SetDescription( $args{'Description'} ); - $AttributeObj->SetContent( $args{'Content'} ); - - $self->Attributes->RedoSearch; - return 1; -} - -=head2 DeleteAttribute NAME - -Deletes all attributes with the matching name for this object. - -=cut - -sub DeleteAttribute { - my $self = shift; - my $name = shift; - return $self->Attributes->DeleteEntry( Name => $name ); -} - -=head2 FirstAttribute NAME - -Returns the value of the first attribute with the matching name -for this object, or C<undef> if no such attributes exist. - -=cut - -sub FirstAttribute { - my $self = shift; - my $name = shift; - return ($self->Attributes->Named( $name ))[0]; -} - - # {{{ sub _Handle sub _Handle { my $self = shift; @@ -258,7 +95,7 @@ sub _Handle { # {{{ sub Create -=head2 Create PARAMHASH +=item Create PARAMHASH Takes a PARAMHASH of Column -> Value pairs. If any Column has a Validate$PARAMNAME subroutine defined and the @@ -358,9 +195,6 @@ sub LoadByCols { my $self = shift; my %hash = (@_); - # We don't want to hang onto this - delete $self->{'attributes'}; - # If this database is case sensitive we need to uncase objects for # explicit loading if ( $self->_Handle->CaseSensitive ) { @@ -377,11 +211,7 @@ sub LoadByCols { $newhash{$key} = $hash{$key}; } else { - my ($op, $val, $func); - ($key, $op, $val, $func) = $self->_Handle->_MakeClauseCaseInsensitive($key, '=', $hash{$key}); - $newhash{$key}->{operator} = $op; - $newhash{$key}->{value} = $val; - $newhash{$key}->{function} = $func; + $newhash{ "lower(" . $key . ")" } = lc( $hash{$key} ); } } @@ -483,7 +313,6 @@ sub LongSinceUpdateAsString { # }}} Datehandling # {{{ sub _Set -# sub _Set { my $self = shift; @@ -501,33 +330,12 @@ sub _Set { $args{'Value'} = 0; } - my $old_val = $self->__Value($args{'Field'}); - $self->_SetLastUpdated(); - my $ret = $self->SUPER::_Set( + $self->_SetLastUpdated(); + my ( $val, $msg ) = $self->SUPER::_Set( Field => $args{'Field'}, Value => $args{'Value'}, IsSQL => $args{'IsSQL'} ); - my ($status, $msg) = $ret->as_array(); - - # @values has two values, a status code and a message. - - # $ret is a Class::ReturnValue object. as such, in a boolean context, it's a bool - # we want to change the standard "success" message - if ($status) { - $msg = - $self->loc( - "[_1] changed from [_2] to [_3]", - $args{'Field'}, - ( $old_val ? "'$old_val'" : $self->loc("(no value)") ), - '"' . $self->__Value( $args{'Field'}) . '"' - ); - } else { - - $msg = $self->CurrentUser->loc_fuzzy($msg); - } - return wantarray ? ($status, $msg) : $ret; - } # }}} @@ -602,61 +410,10 @@ sub LastUpdatedByObj { # }}} -# {{{ sub URI - -=head2 URI - -Returns this record's URI - -=cut - -sub URI { - my $self = shift; - my $uri = RT::URI::fsck_com_rt->new($self->CurrentUser); - return($uri->URIForObject($self)); -} - -# }}} - -=head2 ValidateName NAME - -Validate the name of the record we're creating. Mostly, just make sure it's not a numeric ID, which is invalid for Name - -=cut - -sub ValidateName { - my $self = shift; - my $value = shift; - if ($value && $value=~ /^\d+$/) { - return(0); - } else { - return (1); - } -} - - - -=head2 SQLType attribute - -return the SQL type for the attribute 'attribute' as stored in _ClassAccessible - -=cut - -sub SQLType { - my $self = shift; - my $field = shift; - - return ($self->_Accessible($field, 'type')); - - -} require Encode::compat if $] < 5.007001; require Encode; - - - sub __Value { my $self = shift; my $field = shift; @@ -670,14 +427,7 @@ sub __Value { return('') if ( !defined($value) || $value eq ''); - if( $args{'decode_utf8'} ) { - # XXX: is_utf8 check should be here unless Encode bug would be fixed - # see http://rt.cpan.org/NoAuth/Bug.html?id=14559 - return Encode::decode_utf8($value) unless Encode::is_utf8($value); - } else { - # check is_utf8 here just to be shure - return Encode::encode_utf8($value) if Encode::is_utf8($value); - } + return Encode::decode_utf8($value) || $value if $args{'decode_utf8'}; return $value; } @@ -686,1189 +436,17 @@ sub __Value { sub _CacheConfig { { 'cache_p' => 1, + 'fast_update_p' => 1, 'cache_for_sec' => 30, } } +=head2 _DecodeUTF8 - -sub _BuildTableAttributes { - my $self = shift; - - my $attributes; - if ( UNIVERSAL::can( $self, '_CoreAccessible' ) ) { - $attributes = $self->_CoreAccessible(); - } elsif ( UNIVERSAL::can( $self, '_ClassAccessible' ) ) { - $attributes = $self->_ClassAccessible(); - - } - - foreach my $column (%$attributes) { - foreach my $attr ( %{ $attributes->{$column} } ) { - $_TABLE_ATTR->{ref($self)}->{$column}->{$attr} = $attributes->{$column}->{$attr}; - } - } - if ( UNIVERSAL::can( $self, '_OverlayAccessible' ) ) { - $attributes = $self->_OverlayAccessible(); - - foreach my $column (%$attributes) { - foreach my $attr ( %{ $attributes->{$column} } ) { - $_TABLE_ATTR->{ref($self)}->{$column}->{$attr} = $attributes->{$column}->{$attr}; - } - } - } - if ( UNIVERSAL::can( $self, '_VendorAccessible' ) ) { - $attributes = $self->_VendorAccessible(); - - foreach my $column (%$attributes) { - foreach my $attr ( %{ $attributes->{$column} } ) { - $_TABLE_ATTR->{ref($self)}->{$column}->{$attr} = $attributes->{$column}->{$attr}; - } - } - } - if ( UNIVERSAL::can( $self, '_LocalAccessible' ) ) { - $attributes = $self->_LocalAccessible(); - - foreach my $column (%$attributes) { - foreach my $attr ( %{ $attributes->{$column} } ) { - $_TABLE_ATTR->{ref($self)}->{$column}->{$attr} = $attributes->{$column}->{$attr}; - } - } - } - -} - - -=head2 _ClassAccessible - -Overrides the "core" _ClassAccessible using $_TABLE_ATTR. Behaves identical to the version in -DBIx::SearchBuilder::Record - -=cut - -sub _ClassAccessible { - my $self = shift; - return $_TABLE_ATTR->{ref($self)}; -} - -=head2 _Accessible COLUMN ATTRIBUTE - -returns the value of ATTRIBUTE for COLUMN - - -=cut - -sub _Accessible { - my $self = shift; - my $column = shift; - my $attribute = lc(shift); - return 0 unless defined ($_TABLE_ATTR->{ref($self)}->{$column}); - return $_TABLE_ATTR->{ref($self)}->{$column}->{$attribute} || 0; - -} - -=head2 _EncodeLOB BODY MIME_TYPE - -Takes a potentially large attachment. Returns (ContentEncoding, EncodedBody) based on system configuration and selected database + When passed a string will "decode" it int a proper UTF-8 string =cut -sub _EncodeLOB { - my $self = shift; - my $Body = shift; - my $MIMEType = shift; - - my $ContentEncoding = 'none'; - - #get the max attachment length from RT - my $MaxSize = $RT::MaxAttachmentSize; - - #if the current attachment contains nulls and the - #database doesn't support embedded nulls - - if ( $RT::AlwaysUseBase64 or - ( !$RT::Handle->BinarySafeBLOBs ) && ( $Body =~ /\x00/ ) ) { - - # set a flag telling us to mimencode the attachment - $ContentEncoding = 'base64'; - - #cut the max attchment size by 25% (for mime-encoding overhead. - $RT::Logger->debug("Max size is $MaxSize\n"); - $MaxSize = $MaxSize * 3 / 4; - # Some databases (postgres) can't handle non-utf8 data - } elsif ( !$RT::Handle->BinarySafeBLOBs - && $MIMEType !~ /text\/plain/gi - && !Encode::is_utf8( $Body, 1 ) ) { - $ContentEncoding = 'quoted-printable'; - } - - #if the attachment is larger than the maximum size - if ( ($MaxSize) and ( $MaxSize < length($Body) ) ) { - - # if we're supposed to truncate large attachments - if ($RT::TruncateLongAttachments) { - - # truncate the attachment to that length. - $Body = substr( $Body, 0, $MaxSize ); - - } - - # elsif we're supposed to drop large attachments on the floor, - elsif ($RT::DropLongAttachments) { - - # drop the attachment on the floor - $RT::Logger->info( "$self: Dropped an attachment of size " . length($Body) . "\n" . "It started: " . substr( $Body, 0, 60 ) . "\n" ); - return ("none", "Large attachment dropped" ); - } - } - - # if we need to mimencode the attachment - if ( $ContentEncoding eq 'base64' ) { - - # base64 encode the attachment - Encode::_utf8_off($Body); - $Body = MIME::Base64::encode_base64($Body); - - } elsif ($ContentEncoding eq 'quoted-printable') { - Encode::_utf8_off($Body); - $Body = MIME::QuotedPrint::encode($Body); - } - - - return ($ContentEncoding, $Body); - -} - -sub _DecodeLOB { - my $self = shift; - my $ContentType = shift; - my $ContentEncoding = shift; - my $Content = shift; - - if ( $ContentEncoding eq 'base64' ) { - $Content = MIME::Base64::decode_base64($Content); - } - elsif ( $ContentEncoding eq 'quoted-printable' ) { - $Content = MIME::QuotedPrint::decode($Content); - } - elsif ( $ContentEncoding && $ContentEncoding ne 'none' ) { - return ( $self->loc( "Unknown ContentEncoding [_1]", $ContentEncoding ) ); - } - if ( $ContentType eq 'text/plain' ) { - $Content = Encode::decode_utf8($Content) unless Encode::is_utf8($Content); - } - return ($Content); -} - -# {{{ LINKDIRMAP -# A helper table for links mapping to make it easier -# to build and parse links between tickets - -use vars '%LINKDIRMAP'; - -%LINKDIRMAP = ( - MemberOf => { Base => 'MemberOf', - Target => 'HasMember', }, - RefersTo => { Base => 'RefersTo', - Target => 'ReferredToBy', }, - DependsOn => { Base => 'DependsOn', - Target => 'DependedOnBy', }, - MergedInto => { Base => 'MergedInto', - Target => 'MergedInto', }, - -); - -sub Update { - my $self = shift; - - my %args = ( - ARGSRef => undef, - AttributesRef => undef, - AttributePrefix => undef, - @_ - ); - - my $attributes = $args{'AttributesRef'}; - my $ARGSRef = $args{'ARGSRef'}; - my @results; - - foreach my $attribute (@$attributes) { - my $value; - if ( defined $ARGSRef->{$attribute} ) { - $value = $ARGSRef->{$attribute}; - } - elsif ( - defined( $args{'AttributePrefix'} ) - && defined( - $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute } - ) - ) { - $value = $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute }; - - } - else { - next; - } - - $value =~ s/\r\n/\n/gs; - - - # If Queue is 'General', we want to resolve the queue name for - # the object. - - # This is in an eval block because $object might not exist. - # and might not have a Name method. But "can" won't find autoloaded - # items. If it fails, we don't care - eval { - my $object = $attribute . "Obj"; - next if ($self->$object->Name eq $value); - }; - next if ( $value eq $self->$attribute() ); - my $method = "Set$attribute"; - my ( $code, $msg ) = $self->$method($value); - my ($prefix) = ref($self) =~ /RT::(\w+)/; - - # Default to $id, but use name if we can get it. - my $label = $self->id; - $label = $self->Name if (UNIVERSAL::can($self,'Name')); - push @results, $self->loc( "$prefix [_1]", $label ) . ': '. $msg; - -=for loc - - "[_1] could not be set to [_2].", # loc - "That is already the current value", # loc - "No value sent to _Set!\n", # loc - "Illegal value for [_1]", # loc - "The new value has been set.", # loc - "No column specified", # loc - "Immutable field", # loc - "Nonexistant field?", # loc - "Invalid data", # loc - "Couldn't find row", # loc - "Missing a primary key?: [_1]", # loc - "Found Object", # loc - -=cut - - } - - return @results; -} - -# {{{ Routines dealing with Links - -# {{{ Link Collections - -# {{{ sub Members - -=head2 Members - - This returns an RT::Links object which references all the tickets -which are 'MembersOf' this ticket - -=cut - -sub Members { - my $self = shift; - return ( $self->_Links( 'Target', 'MemberOf' ) ); -} - -# }}} - -# {{{ sub MemberOf - -=head2 MemberOf - - This returns an RT::Links object which references all the tickets that this -ticket is a 'MemberOf' - -=cut - -sub MemberOf { - my $self = shift; - return ( $self->_Links( 'Base', 'MemberOf' ) ); -} - -# }}} - -# {{{ RefersTo - -=head2 RefersTo - - This returns an RT::Links object which shows all references for which this ticket is a base - -=cut - -sub RefersTo { - my $self = shift; - return ( $self->_Links( 'Base', 'RefersTo' ) ); -} - -# }}} - -# {{{ ReferredToBy - -=head2 ReferredToBy - - This returns an RT::Links object which shows all references for which this ticket is a target - -=cut - -sub ReferredToBy { - my $self = shift; - return ( $self->_Links( 'Target', 'RefersTo' ) ); -} - -# }}} - -# {{{ DependedOnBy - -=head2 DependedOnBy - - This returns an RT::Links object which references all the tickets that depend on this one - -=cut - -sub DependedOnBy { - my $self = shift; - return ( $self->_Links( 'Target', 'DependsOn' ) ); -} - -# }}} - - - -=head2 HasUnresolvedDependencies - - Takes a paramhash of Type (default to '__any'). Returns true if -$self->UnresolvedDependencies returns an object with one or more members -of that type. Returns false otherwise - - -=begin testing - -my $t1 = RT::Ticket->new($RT::SystemUser); -my ($id, $trans, $msg) = $t1->Create(Subject => 'DepTest1', Queue => 'general'); -ok($id, "Created dep test 1 - $msg"); - -my $t2 = RT::Ticket->new($RT::SystemUser); -my ($id2, $trans, $msg2) = $t2->Create(Subject => 'DepTest2', Queue => 'general'); -ok($id2, "Created dep test 2 - $msg2"); -my $t3 = RT::Ticket->new($RT::SystemUser); -my ($id3, $trans, $msg3) = $t3->Create(Subject => 'DepTest3', Queue => 'general', Type => 'approval'); -ok($id3, "Created dep test 3 - $msg3"); -my ($addid, $addmsg); -ok (($addid, $addmsg) =$t1->AddLink( Type => 'DependsOn', Target => $t2->id)); -ok ($addid, $addmsg); -ok (($addid, $addmsg) =$t1->AddLink( Type => 'DependsOn', Target => $t3->id)); - -ok ($addid, $addmsg); -my $link = RT::Link->new($RT::SystemUser); -my ($rv, $msg) = $link->Load($addid); -ok ($rv, $msg); -ok ($link->LocalTarget == $t3->id, "Link LocalTarget is correct"); -ok ($link->LocalBase == $t1->id, "Link LocalBase is correct"); - -ok ($t1->HasUnresolvedDependencies, "Ticket ".$t1->Id." has unresolved deps"); -ok (!$t1->HasUnresolvedDependencies( Type => 'blah' ), "Ticket ".$t1->Id." has no unresolved blahs"); -ok ($t1->HasUnresolvedDependencies( Type => 'approval' ), "Ticket ".$t1->Id." has unresolved approvals"); -ok (!$t2->HasUnresolvedDependencies, "Ticket ".$t2->Id." has no unresolved deps"); -; - -my ($rid, $rmsg)= $t1->Resolve(); -ok(!$rid, $rmsg); -my ($rid2, $rmsg2) = $t2->Resolve(); -ok ($rid2, $rmsg2); -($rid, $rmsg)= $t1->Resolve(); -ok(!$rid, $rmsg); -my ($rid3,$rmsg3) = $t3->Resolve; -ok ($rid3,$rmsg3); -($rid, $rmsg)= $t1->Resolve(); -ok($rid, $rmsg); - - -=end testing - -=cut - -sub HasUnresolvedDependencies { - my $self = shift; - my %args = ( - Type => undef, - @_ - ); - - my $deps = $self->UnresolvedDependencies; - - if ($args{Type}) { - $deps->Limit( FIELD => 'Type', - OPERATOR => '=', - VALUE => $args{Type}); - } - else { - $deps->IgnoreType; - } - - if ($deps->Count > 0) { - return 1; - } - else { - return (undef); - } -} - - -# {{{ UnresolvedDependencies - -=head2 UnresolvedDependencies - -Returns an RT::Tickets object of tickets which this ticket depends on -and which have a status of new, open or stalled. (That list comes from -RT::Queue->ActiveStatusArray - -=cut - - -sub UnresolvedDependencies { - my $self = shift; - my $deps = RT::Tickets->new($self->CurrentUser); - - my @live_statuses = RT::Queue->ActiveStatusArray(); - foreach my $status (@live_statuses) { - $deps->LimitStatus(VALUE => $status); - } - $deps->LimitDependedOnBy($self->Id); - - return($deps); - -} - -# }}} - -# {{{ AllDependedOnBy - -=head2 AllDependedOnBy - -Returns an array of RT::Ticket objects which (directly or indirectly) -depends on this ticket; takes an optional 'Type' argument in the param -hash, which will limit returned tickets to that type, as well as cause -tickets with that type to serve as 'leaf' nodes that stops the recursive -dependency search. - -=cut - -sub AllDependedOnBy { - my $self = shift; - my $dep = $self->DependedOnBy; - my %args = ( - Type => undef, - _found => {}, - _top => 1, - @_ - ); - - while (my $link = $dep->Next()) { - next unless ($link->BaseURI->IsLocal()); - next if $args{_found}{$link->BaseObj->Id}; - - if (!$args{Type}) { - $args{_found}{$link->BaseObj->Id} = $link->BaseObj; - $link->BaseObj->AllDependedOnBy( %args, _top => 0 ); - } - elsif ($link->BaseObj->Type eq $args{Type}) { - $args{_found}{$link->BaseObj->Id} = $link->BaseObj; - } - else { - $link->BaseObj->AllDependedOnBy( %args, _top => 0 ); - } - } - - if ($args{_top}) { - return map { $args{_found}{$_} } sort keys %{$args{_found}}; - } - else { - return 1; - } -} - -# }}} - -# {{{ DependsOn - -=head2 DependsOn - - This returns an RT::Links object which references all the tickets that this ticket depends on - -=cut - -sub DependsOn { - my $self = shift; - return ( $self->_Links( 'Base', 'DependsOn' ) ); -} - -# }}} - - - - -# {{{ sub _Links - -=head2 Links DIRECTION TYPE - -return links to/from this object. - -=cut - -*Links = \&_Links; - -sub _Links { - my $self = shift; - - #TODO: Field isn't the right thing here. but I ahave no idea what mnemonic --- - #tobias meant by $f - my $field = shift; - my $type = shift || ""; - - unless ( $self->{"$field$type"} ) { - $self->{"$field$type"} = new RT::Links( $self->CurrentUser ); - # at least to myself - $self->{"$field$type"}->Limit( FIELD => $field, - VALUE => $self->URI, - ENTRYAGGREGATOR => 'OR' ); - $self->{"$field$type"}->Limit( FIELD => 'Type', - VALUE => $type ) - if ($type); - } - return ( $self->{"$field$type"} ); -} - -# }}} - -# }}} - -# {{{ sub _AddLink - -=head2 _AddLink - -Takes a paramhash of Type and one of Base or Target. Adds that link to this ticket. - - -=cut - - -sub _AddLink { - my $self = shift; - my %args = ( Target => '', - Base => '', - Type => '', - Silent => undef, - @_ ); - - - # Remote_link is the URI of the object that is not this ticket - my $remote_link; - my $direction; - - if ( $args{'Base'} and $args{'Target'} ) { - $RT::Logger->debug( "$self tried to create a link. both base and target were specified\n" ); - return ( 0, $self->loc("Can't specifiy both base and target") ); - } - elsif ( $args{'Base'} ) { - $args{'Target'} = $self->URI(); - my $class = ref($self); - $remote_link = $args{'Base'}; - $direction = 'Target'; - } - elsif ( $args{'Target'} ) { - $args{'Base'} = $self->URI(); - my $class = ref($self); - $remote_link = $args{'Target'}; - $direction = 'Base'; - } - else { - return ( 0, $self->loc('Either base or target must be specified') ); - } - - # {{{ Check if the link already exists - we don't want duplicates - use RT::Link; - my $old_link = RT::Link->new( $self->CurrentUser ); - $old_link->LoadByParams( Base => $args{'Base'}, - Type => $args{'Type'}, - Target => $args{'Target'} ); - if ( $old_link->Id ) { - $RT::Logger->debug("$self Somebody tried to duplicate a link"); - return ( $old_link->id, $self->loc("Link already exists") ); - } - - # }}} - - - # Storing the link in the DB. - my $link = RT::Link->new( $self->CurrentUser ); - my ($linkid, $linkmsg) = $link->Create( Target => $args{Target}, - Base => $args{Base}, - Type => $args{Type} ); - - unless ($linkid) { - $RT::Logger->error("Link could not be created: ".$linkmsg); - return ( 0, $self->loc("Link could not be created") ); - } - - my $TransString = - "Record $args{'Base'} $args{Type} record $args{'Target'}."; - - return ( $linkid, $self->loc( "Link created ([_1])", $TransString ) ); -} - -# }}} - -# {{{ sub _DeleteLink - -=head2 _DeleteLink - -Delete a link. takes a paramhash of Base, Target and Type. -Either Base or Target must be null. The null value will -be replaced with this ticket\'s id - -=cut - -sub _DeleteLink { - my $self = shift; - my %args = ( - Base => undef, - Target => undef, - Type => undef, - @_ - ); - - #we want one of base and target. we don't care which - #but we only want _one_ - - my $direction; - my $remote_link; - - if ( $args{'Base'} and $args{'Target'} ) { - $RT::Logger->debug("$self ->_DeleteLink. got both Base and Target\n"); - return ( 0, $self->loc("Can't specifiy both base and target") ); - } - elsif ( $args{'Base'} ) { - $args{'Target'} = $self->URI(); - $remote_link = $args{'Base'}; - $direction = 'Target'; - } - elsif ( $args{'Target'} ) { - $args{'Base'} = $self->URI(); - $remote_link = $args{'Target'}; - $direction='Base'; - } - else { - $RT::Logger->debug("$self: Base or Target must be specified\n"); - return ( 0, $self->loc('Either base or target must be specified') ); - } - - my $link = new RT::Link( $self->CurrentUser ); - $RT::Logger->debug( "Trying to load link: " . $args{'Base'} . " " . $args{'Type'} . " " . $args{'Target'} . "\n" ); - - - $link->LoadByParams( Base=> $args{'Base'}, Type=> $args{'Type'}, Target=> $args{'Target'} ); - #it's a real link. - if ( $link->id ) { - - my $linkid = $link->id; - $link->Delete(); - - my $TransString = "Record $args{'Base'} no longer $args{Type} record $args{'Target'}."; - return ( 1, $self->loc("Link deleted ([_1])", $TransString)); - } - - #if it's not a link we can find - else { - $RT::Logger->debug("Couldn't find that link\n"); - return ( 0, $self->loc("Link not found") ); - } -} - -# }}} - -# }}} - -# {{{ Routines dealing with transactions - -# {{{ sub _NewTransaction - -=head2 _NewTransaction PARAMHASH - -Private function to create a new RT::Transaction object for this ticket update - -=cut - -sub _NewTransaction { - my $self = shift; - my %args = ( - TimeTaken => undef, - Type => undef, - OldValue => undef, - NewValue => undef, - OldReference => undef, - NewReference => undef, - ReferenceType => undef, - Data => undef, - Field => undef, - MIMEObj => undef, - ActivateScrips => 1, - CommitScrips => 1, - @_ - ); - - my $old_ref = $args{'OldReference'}; - my $new_ref = $args{'NewReference'}; - my $ref_type = $args{'ReferenceType'}; - if ($old_ref or $new_ref) { - $ref_type ||= ref($old_ref) || ref($new_ref); - if (!$ref_type) { - $RT::Logger->error("Reference type not specified for transaction"); - return; - } - $old_ref = $old_ref->Id if ref($old_ref); - $new_ref = $new_ref->Id if ref($new_ref); - } - - require RT::Transaction; - my $trans = new RT::Transaction( $self->CurrentUser ); - my ( $transaction, $msg ) = $trans->Create( - ObjectId => $self->Id, - ObjectType => ref($self), - TimeTaken => $args{'TimeTaken'}, - Type => $args{'Type'}, - Data => $args{'Data'}, - Field => $args{'Field'}, - NewValue => $args{'NewValue'}, - OldValue => $args{'OldValue'}, - NewReference => $new_ref, - OldReference => $old_ref, - ReferenceType => $ref_type, - MIMEObj => $args{'MIMEObj'}, - ActivateScrips => $args{'ActivateScrips'}, - CommitScrips => $args{'CommitScrips'}, - ); - - # Rationalize the object since we may have done things to it during the caching. - $self->Load($self->Id); - - $RT::Logger->warning($msg) unless $transaction; - - $self->_SetLastUpdated; - - if ( defined $args{'TimeTaken'} ) { - $self->_UpdateTimeTaken( $args{'TimeTaken'} ); - } - if ( $RT::UseTransactionBatch and $transaction ) { - push @{$self->{_TransactionBatch}}, $trans; - } - return ( $transaction, $msg, $trans ); -} - -# }}} - -# {{{ sub Transactions - -=head2 Transactions - - Returns an RT::Transactions object of all transactions on this record object - -=cut - -sub Transactions { - my $self = shift; - - use RT::Transactions; - my $transactions = RT::Transactions->new( $self->CurrentUser ); - - #If the user has no rights, return an empty object - $transactions->Limit( - FIELD => 'ObjectId', - VALUE => $self->id, - ); - $transactions->Limit( - FIELD => 'ObjectType', - VALUE => ref($self), - ); - - return ($transactions); -} - -# }}} -# }}} -# -# {{{ Routines dealing with custom fields - -sub CustomFields { - my $self = shift; - my $cfs = RT::CustomFields->new( $self->CurrentUser ); - - # XXX handle multiple types properly - $cfs->LimitToLookupType( $self->CustomFieldLookupType ); - $cfs->LimitToGlobalOrObjectId( - $self->_LookupId( $self->CustomFieldLookupType ) ); - - return $cfs; -} - -# TODO: This _only_ works for RT::Class classes. it doesn't work, for example, for RT::FM classes. - -sub _LookupId { - my $self = shift; - my $lookup = shift; - my @classes = ($lookup =~ /RT::(\w+)-/g); - - my $object = $self; - foreach my $class (reverse @classes) { - my $method = "${class}Obj"; - $object = $object->$method; - } - - return $object->Id; -} - - -=head2 CustomFieldLookupType - -Returns the path RT uses to figure out which custom fields apply to this object. - -=cut - -sub CustomFieldLookupType { - my $self = shift; - return ref($self); -} - -#TODO Deprecated API. Destroy in 3.6 -sub _LookupTypes { - my $self = shift; - $RT::Logger->warning("_LookupTypes call is deprecated at (". join(":",caller)."). Replace with CustomFieldLookupType"); - - return($self->CustomFieldLookupType); - -} - -# {{{ AddCustomFieldValue - -=head2 AddCustomFieldValue { Field => FIELD, Value => VALUE } - -VALUE should be a string. -FIELD can be a CustomField object OR a CustomField ID. - - -Adds VALUE as a value of CustomField FIELD. If this is a single-value custom field, -deletes the old value. -If VALUE is not a valid value for the custom field, returns -(0, 'Error message' ) otherwise, returns (1, 'Success Message') - -=cut - -sub AddCustomFieldValue { - my $self = shift; - $self->_AddCustomFieldValue(@_); -} - -sub _AddCustomFieldValue { - my $self = shift; - my %args = ( - Field => undef, - Value => undef, - RecordTransaction => 1, - @_ - ); - - my $cf = $self->LoadCustomFieldByIdentifier($args{'Field'}); - - unless ( $cf->Id ) { - return ( 0, $self->loc( "Custom field [_1] not found", $args{'Field'} ) ); - } - - my $OCFs = $self->CustomFields; - $OCFs->Limit( FIELD => 'id', VALUE => $cf->Id ); - unless ( $OCFs->Count ) { - return ( - 0, - $self->loc( - "Custom field [_1] does not apply to this object", - $args{'Field'} - ) - ); - } - # Load up a ObjectCustomFieldValues object for this custom field and this ticket - my $values = $cf->ValuesForObject($self); - - unless ( $cf->ValidateValue( $args{'Value'} ) ) { - return ( 0, $self->loc("Invalid value for custom field") ); - } - - # If the custom field only accepts a certain # of values, delete the existing - # value and record a "changed from foo to bar" transaction - unless ( $cf->UnlimitedValues) { - - # We need to whack any old values here. In most cases, the custom field should - # only have one value to delete. In the pathalogical case, this custom field - # used to be a multiple and we have many values to whack.... - my $cf_values = $values->Count; - - if ( $cf_values > $cf->MaxValues ) { - my $i = 0; #We want to delete all but the max we can currently have , so we can then - # execute the same code to "change" the value from old to new - while ( my $value = $values->Next ) { - $i++; - if ( $i < $cf_values ) { - my ( $val, $msg ) = $cf->DeleteValueForObject( - Object => $self, - Content => $value->Content - ); - unless ($val) { - return ( 0, $msg ); - } - my ( $TransactionId, $Msg, $TransactionObj ) = - $self->_NewTransaction( - Type => 'CustomField', - Field => $cf->Id, - OldReference => $value, - ); - } - } - } - - my ( $old_value, $old_content ); - if ( $old_value = $cf->ValuesForObject($self)->First ) { - $old_content = $old_value->Content(); - return (1) if( $old_content eq $args{'Value'} && $old_value->LargeContent eq $args{'LargeContent'});; - } - - my ( $new_value_id, $value_msg ) = $cf->AddValueForObject( - Object => $self, - Content => $args{'Value'}, - LargeContent => $args{'LargeContent'}, - ContentType => $args{'ContentType'}, - ); - - unless ($new_value_id) { - return ( 0, $self->loc( "Could not add new custom field value. [_1] ",, $value_msg)); - } - - my $new_value = RT::ObjectCustomFieldValue->new( $self->CurrentUser ); - $new_value->Load($new_value_id); - - # now that adding the new value was successful, delete the old one - if ($old_value) { - my ( $val, $msg ) = $old_value->Delete(); - unless ($val) { - return ( 0, $msg ); - } - } - - if ( $args{'RecordTransaction'} ) { - my ( $TransactionId, $Msg, $TransactionObj ) = - $self->_NewTransaction( - Type => 'CustomField', - Field => $cf->Id, - OldReference => $old_value, - NewReference => $new_value, - ); - } - - if ( $old_value eq '' ) { - return ( 1, $self->loc( "[_1] [_2] added", $cf->Name, $new_value->Content )); - } - elsif ( $new_value->Content eq '' ) { - return ( 1, - $self->loc( "[_1] [_2] deleted", $cf->Name, $old_value->Content ) ); - } - else { - return ( 1, $self->loc( "[_1] [_2] changed to [_3]", $cf->Name, $old_content, $new_value->Content)); - } - - } - - # otherwise, just add a new value and record "new value added" - else { - my ($new_value_id) = $cf->AddValueForObject( - Object => $self, - Content => $args{'Value'}, - LargeContent => $args{'LargeContent'}, - ContentType => $args{'ContentType'}, - ); - - unless ($new_value_id) { - return ( 0, $self->loc("Could not add new custom field value. ") ); - } - if ( $args{'RecordTransaction'} ) { - my ( $TransactionId, $Msg, $TransactionObj ) = - $self->_NewTransaction( - Type => 'CustomField', - Field => $cf->Id, - NewReference => $new_value_id, - ReferenceType => 'RT::ObjectCustomFieldValue', - ); - unless ($TransactionId) { - return ( 0, - $self->loc( "Couldn't create a transaction: [_1]", $Msg ) ); - } - } - return ( 1, $self->loc( "[_1] added as a value for [_2]", $args{'Value'}, $cf->Name)); - } - -} - -# }}} - -# {{{ DeleteCustomFieldValue - -=head2 DeleteCustomFieldValue { Field => FIELD, Value => VALUE } - -Deletes VALUE as a value of CustomField FIELD. - -VALUE can be a string, a CustomFieldValue or a ObjectCustomFieldValue. - -If VALUE is not a valid value for the custom field, returns -(0, 'Error message' ) otherwise, returns (1, 'Success Message') - -=cut - -sub DeleteCustomFieldValue { - my $self = shift; - my %args = ( - Field => undef, - Value => undef, - ValueId => undef, - @_ - ); - - my $cf = $self->LoadCustomFieldByIdentifier($args{'Field'}); - - unless ( $cf->Id ) { - return ( 0, $self->loc( "Custom field [_1] not found", $args{'Field'} ) ); - } - my ( $val, $msg ) = $cf->DeleteValueForObject( - Object => $self, - Id => $args{'ValueId'}, - Content => $args{'Value'}, - ); - unless ($val) { - return ( 0, $msg ); - } - my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction( - Type => 'CustomField', - Field => $cf->Id, - OldReference => $val, - ReferenceType => 'RT::ObjectCustomFieldValue', - ); - unless ($TransactionId) { - return ( 0, $self->loc( "Couldn't create a transaction: [_1]", $Msg ) ); - } - - return ( - $TransactionId, - $self->loc( - "[_1] is no longer a value for custom field [_2]", - $TransactionObj->OldValue, $cf->Name - ) - ); -} - -# }}} - -# {{{ FirstCustomFieldValue - -=head2 FirstCustomFieldValue FIELD - -Return the content of the first value of CustomField FIELD for this ticket -Takes a field id or name - -=cut - -sub FirstCustomFieldValue { - my $self = shift; - my $field = shift; - my $values = $self->CustomFieldValues($field); - if ($values->First) { - return $values->First->Content; - } else { - return undef; - } - -} - - - -# {{{ CustomFieldValues - -=head2 CustomFieldValues FIELD - -Return a ObjectCustomFieldValues object of all values of the CustomField whose -id or Name is FIELD for this record. - -Returns an RT::ObjectCustomFieldValues object - -=cut - -sub CustomFieldValues { - my $self = shift; - my $field = shift; - - if ($field) { - my $cf = $self->LoadCustomFieldByIdentifier($field); - - # we were asked to search on a custom field we couldn't fine - unless ( $cf->id ) { - return RT::ObjectCustomFieldValues->new( $self->CurrentUser ); - } - return ( $cf->ValuesForObject($self) ); - } - - # we're not limiting to a specific custom field; - my $ocfs = RT::ObjectCustomFieldValues->new( $self->CurrentUser ); - $ocfs->LimitToObject($self); - return $ocfs; - -} - -=head2 CustomField IDENTIFER - -Find the custom field has id or name IDENTIFIER for this object. - -If no valid field is found, returns an empty RT::CustomField object. - -=cut - -sub LoadCustomFieldByIdentifier { - my $self = shift; - my $field = shift; - - my $cf = RT::CustomField->new($self->CurrentUser); - - if ( UNIVERSAL::isa( $field, "RT::CustomField" ) ) { - $cf->LoadById( $field->id ); - } - elsif ($field =~ /^\d+$/) { - $cf = RT::CustomField->new($self->CurrentUser); - $cf->Load($field); - } else { - - my $cfs = $self->CustomFields($self->CurrentUser); - $cfs->Limit(FIELD => 'Name', VALUE => $field); - $cf = $cfs->First || RT::CustomField->new($self->CurrentUser); - } - return $cf; -} - - -# }}} - -# }}} - -# }}} - -sub BasicColumns { -} - eval "require RT::Record_Vendor"; die $@ if ($@ && $@ !~ qr{^Can't locate RT/Record_Vendor.pm}); eval "require RT::Record_Local"; diff --git a/rt/lib/RT/Scrip.pm b/rt/lib/RT/Scrip.pm index 85fe6a820..a69dde04e 100755 --- a/rt/lib/RT/Scrip.pm +++ b/rt/lib/RT/Scrip.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -87,7 +65,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -142,7 +120,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -151,14 +129,14 @@ Returns the current value of id. =cut -=head2 Description +=item Description Returns the current value of Description. (In the database, Description is stored as varchar(255).) -=head2 SetDescription VALUE +=item SetDescription VALUE Set Description to VALUE. @@ -169,14 +147,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ScripCondition +=item ScripCondition Returns the current value of ScripCondition. (In the database, ScripCondition is stored as int(11).) -=head2 SetScripCondition VALUE +=item SetScripCondition VALUE Set ScripCondition to VALUE. @@ -187,7 +165,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ScripConditionObj +=item ScripConditionObj Returns the ScripCondition Object which has the id returned by ScripCondition @@ -201,14 +179,14 @@ sub ScripConditionObj { return($ScripCondition); } -=head2 ScripAction +=item ScripAction Returns the current value of ScripAction. (In the database, ScripAction is stored as int(11).) -=head2 SetScripAction VALUE +=item SetScripAction VALUE Set ScripAction to VALUE. @@ -219,7 +197,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ScripActionObj +=item ScripActionObj Returns the ScripAction Object which has the id returned by ScripAction @@ -233,14 +211,14 @@ sub ScripActionObj { return($ScripAction); } -=head2 ConditionRules +=item ConditionRules Returns the current value of ConditionRules. (In the database, ConditionRules is stored as text.) -=head2 SetConditionRules VALUE +=item SetConditionRules VALUE Set ConditionRules to VALUE. @@ -251,14 +229,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ActionRules +=item ActionRules Returns the current value of ActionRules. (In the database, ActionRules is stored as text.) -=head2 SetActionRules VALUE +=item SetActionRules VALUE Set ActionRules to VALUE. @@ -269,14 +247,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 CustomIsApplicableCode +=item CustomIsApplicableCode Returns the current value of CustomIsApplicableCode. (In the database, CustomIsApplicableCode is stored as text.) -=head2 SetCustomIsApplicableCode VALUE +=item SetCustomIsApplicableCode VALUE Set CustomIsApplicableCode to VALUE. @@ -287,14 +265,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 CustomPrepareCode +=item CustomPrepareCode Returns the current value of CustomPrepareCode. (In the database, CustomPrepareCode is stored as text.) -=head2 SetCustomPrepareCode VALUE +=item SetCustomPrepareCode VALUE Set CustomPrepareCode to VALUE. @@ -305,14 +283,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 CustomCommitCode +=item CustomCommitCode Returns the current value of CustomCommitCode. (In the database, CustomCommitCode is stored as text.) -=head2 SetCustomCommitCode VALUE +=item SetCustomCommitCode VALUE Set CustomCommitCode to VALUE. @@ -323,14 +301,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Stage +=item Stage Returns the current value of Stage. (In the database, Stage is stored as varchar(32).) -=head2 SetStage VALUE +=item SetStage VALUE Set Stage to VALUE. @@ -341,14 +319,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Queue +=item Queue Returns the current value of Queue. (In the database, Queue is stored as int(11).) -=head2 SetQueue VALUE +=item SetQueue VALUE Set Queue to VALUE. @@ -359,7 +337,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 QueueObj +=item QueueObj Returns the Queue Object which has the id returned by Queue @@ -373,14 +351,14 @@ sub QueueObj { return($Queue); } -=head2 Template +=item Template Returns the current value of Template. (In the database, Template is stored as int(11).) -=head2 SetTemplate VALUE +=item SetTemplate VALUE Set Template to VALUE. @@ -391,7 +369,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 TemplateObj +=item TemplateObj Returns the Template Object which has the id returned by Template @@ -405,7 +383,7 @@ sub TemplateObj { return($Template); } -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -414,7 +392,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -423,7 +401,7 @@ Returns the current value of Created. =cut -=head2 LastUpdatedBy +=item LastUpdatedBy Returns the current value of LastUpdatedBy. (In the database, LastUpdatedBy is stored as int(11).) @@ -432,7 +410,7 @@ Returns the current value of LastUpdatedBy. =cut -=head2 LastUpdated +=item LastUpdated Returns the current value of LastUpdated. (In the database, LastUpdated is stored as datetime.) @@ -442,41 +420,41 @@ Returns the current value of LastUpdated. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, Description => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, ScripCondition => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, ScripAction => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, ConditionRules => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + {read => 1, write => 1, type => 'text', default => ''}, ActionRules => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + {read => 1, write => 1, type => 'text', default => ''}, CustomIsApplicableCode => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + {read => 1, write => 1, type => 'text', default => ''}, CustomPrepareCode => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + {read => 1, write => 1, type => 'text', default => ''}, CustomCommitCode => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + {read => 1, write => 1, type => 'text', default => ''}, Stage => - {read => 1, write => 1, sql_type => 12, length => 32, is_blob => 0, is_numeric => 0, type => 'varchar(32)', default => ''}, + {read => 1, write => 1, type => 'varchar(32)', default => ''}, Queue => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Template => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, LastUpdatedBy => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, LastUpdated => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, } }; @@ -508,7 +486,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/ScripAction.pm b/rt/lib/RT/ScripAction.pm index 075162f80..26824df5d 100755 --- a/rt/lib/RT/ScripAction.pm +++ b/rt/lib/RT/ScripAction.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -83,7 +61,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -117,7 +95,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -126,14 +104,14 @@ Returns the current value of id. =cut -=head2 Name +=item Name Returns the current value of Name. (In the database, Name is stored as varchar(200).) -=head2 SetName VALUE +=item SetName VALUE Set Name to VALUE. @@ -144,14 +122,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Description +=item Description Returns the current value of Description. (In the database, Description is stored as varchar(255).) -=head2 SetDescription VALUE +=item SetDescription VALUE Set Description to VALUE. @@ -162,14 +140,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ExecModule +=item ExecModule Returns the current value of ExecModule. (In the database, ExecModule is stored as varchar(60).) -=head2 SetExecModule VALUE +=item SetExecModule VALUE Set ExecModule to VALUE. @@ -180,14 +158,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Argument +=item Argument Returns the current value of Argument. (In the database, Argument is stored as varchar(255).) -=head2 SetArgument VALUE +=item SetArgument VALUE Set Argument to VALUE. @@ -198,7 +176,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -207,7 +185,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -216,7 +194,7 @@ Returns the current value of Created. =cut -=head2 LastUpdatedBy +=item LastUpdatedBy Returns the current value of LastUpdatedBy. (In the database, LastUpdatedBy is stored as int(11).) @@ -225,7 +203,7 @@ Returns the current value of LastUpdatedBy. =cut -=head2 LastUpdated +=item LastUpdated Returns the current value of LastUpdated. (In the database, LastUpdated is stored as datetime.) @@ -235,27 +213,27 @@ Returns the current value of LastUpdated. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, Name => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, type => 'varchar(200)', default => ''}, Description => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, ExecModule => - {read => 1, write => 1, sql_type => 12, length => 60, is_blob => 0, is_numeric => 0, type => 'varchar(60)', default => ''}, + {read => 1, write => 1, type => 'varchar(60)', default => ''}, Argument => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, LastUpdatedBy => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, LastUpdated => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, } }; @@ -287,7 +265,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/ScripActions.pm b/rt/lib/RT/ScripActions.pm index c34e52ff5..614ff374f 100755 --- a/rt/lib/RT/ScripActions.pm +++ b/rt/lib/RT/ScripActions.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::ScripAction item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/ScripCondition.pm b/rt/lib/RT/ScripCondition.pm index bf2c56093..fe0aa2d5a 100755 --- a/rt/lib/RT/ScripCondition.pm +++ b/rt/lib/RT/ScripCondition.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -83,7 +61,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -120,7 +98,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -129,14 +107,14 @@ Returns the current value of id. =cut -=head2 Name +=item Name Returns the current value of Name. (In the database, Name is stored as varchar(200).) -=head2 SetName VALUE +=item SetName VALUE Set Name to VALUE. @@ -147,14 +125,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Description +=item Description Returns the current value of Description. (In the database, Description is stored as varchar(255).) -=head2 SetDescription VALUE +=item SetDescription VALUE Set Description to VALUE. @@ -165,14 +143,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ExecModule +=item ExecModule Returns the current value of ExecModule. (In the database, ExecModule is stored as varchar(60).) -=head2 SetExecModule VALUE +=item SetExecModule VALUE Set ExecModule to VALUE. @@ -183,14 +161,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Argument +=item Argument Returns the current value of Argument. (In the database, Argument is stored as varchar(255).) -=head2 SetArgument VALUE +=item SetArgument VALUE Set Argument to VALUE. @@ -201,14 +179,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ApplicableTransTypes +=item ApplicableTransTypes Returns the current value of ApplicableTransTypes. (In the database, ApplicableTransTypes is stored as varchar(60).) -=head2 SetApplicableTransTypes VALUE +=item SetApplicableTransTypes VALUE Set ApplicableTransTypes to VALUE. @@ -219,7 +197,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -228,7 +206,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -237,7 +215,7 @@ Returns the current value of Created. =cut -=head2 LastUpdatedBy +=item LastUpdatedBy Returns the current value of LastUpdatedBy. (In the database, LastUpdatedBy is stored as int(11).) @@ -246,7 +224,7 @@ Returns the current value of LastUpdatedBy. =cut -=head2 LastUpdated +=item LastUpdated Returns the current value of LastUpdated. (In the database, LastUpdated is stored as datetime.) @@ -256,29 +234,29 @@ Returns the current value of LastUpdated. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, Name => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, type => 'varchar(200)', default => ''}, Description => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, ExecModule => - {read => 1, write => 1, sql_type => 12, length => 60, is_blob => 0, is_numeric => 0, type => 'varchar(60)', default => ''}, + {read => 1, write => 1, type => 'varchar(60)', default => ''}, Argument => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, ApplicableTransTypes => - {read => 1, write => 1, sql_type => 12, length => 60, is_blob => 0, is_numeric => 0, type => 'varchar(60)', default => ''}, + {read => 1, write => 1, type => 'varchar(60)', default => ''}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, LastUpdatedBy => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, LastUpdated => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, } }; @@ -310,7 +288,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/ScripConditions.pm b/rt/lib/RT/ScripConditions.pm index 99bde7dfd..34f788d9c 100755 --- a/rt/lib/RT/ScripConditions.pm +++ b/rt/lib/RT/ScripConditions.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::ScripCondition item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Scrips.pm b/rt/lib/RT/Scrips.pm index 9605a64f7..a39443136 100755 --- a/rt/lib/RT/Scrips.pm +++ b/rt/lib/RT/Scrips.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::Scrip item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Template.pm b/rt/lib/RT/Template.pm index 4f7aacb2c..f73ea3ed6 100755 --- a/rt/lib/RT/Template.pm +++ b/rt/lib/RT/Template.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -84,7 +62,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -127,7 +105,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -136,14 +114,14 @@ Returns the current value of id. =cut -=head2 Queue +=item Queue Returns the current value of Queue. (In the database, Queue is stored as int(11).) -=head2 SetQueue VALUE +=item SetQueue VALUE Set Queue to VALUE. @@ -154,7 +132,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 QueueObj +=item QueueObj Returns the Queue Object which has the id returned by Queue @@ -168,14 +146,14 @@ sub QueueObj { return($Queue); } -=head2 Name +=item Name Returns the current value of Name. (In the database, Name is stored as varchar(200).) -=head2 SetName VALUE +=item SetName VALUE Set Name to VALUE. @@ -186,14 +164,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Description +=item Description Returns the current value of Description. (In the database, Description is stored as varchar(255).) -=head2 SetDescription VALUE +=item SetDescription VALUE Set Description to VALUE. @@ -204,14 +182,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Type +=item Type Returns the current value of Type. (In the database, Type is stored as varchar(16).) -=head2 SetType VALUE +=item SetType VALUE Set Type to VALUE. @@ -222,14 +200,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Language +=item Language Returns the current value of Language. (In the database, Language is stored as varchar(16).) -=head2 SetLanguage VALUE +=item SetLanguage VALUE Set Language to VALUE. @@ -240,14 +218,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 TranslationOf +=item TranslationOf Returns the current value of TranslationOf. (In the database, TranslationOf is stored as int(11).) -=head2 SetTranslationOf VALUE +=item SetTranslationOf VALUE Set TranslationOf to VALUE. @@ -258,14 +236,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Content +=item Content Returns the current value of Content. (In the database, Content is stored as blob.) -=head2 SetContent VALUE +=item SetContent VALUE Set Content to VALUE. @@ -276,7 +254,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 LastUpdated +=item LastUpdated Returns the current value of LastUpdated. (In the database, LastUpdated is stored as datetime.) @@ -285,7 +263,7 @@ Returns the current value of LastUpdated. =cut -=head2 LastUpdatedBy +=item LastUpdatedBy Returns the current value of LastUpdatedBy. (In the database, LastUpdatedBy is stored as int(11).) @@ -294,7 +272,7 @@ Returns the current value of LastUpdatedBy. =cut -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -303,7 +281,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -313,33 +291,33 @@ Returns the current value of Created. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, Queue => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Name => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, type => 'varchar(200)', default => ''}, Description => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, Type => - {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, type => 'varchar(16)', default => ''}, Language => - {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, type => 'varchar(16)', default => ''}, TranslationOf => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Content => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''}, + {read => 1, write => 1, type => 'blob', default => ''}, LastUpdated => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, LastUpdatedBy => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, } }; @@ -371,7 +349,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Templates.pm b/rt/lib/RT/Templates.pm index 6271b973f..37db84086 100755 --- a/rt/lib/RT/Templates.pm +++ b/rt/lib/RT/Templates.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::Template item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Ticket.pm b/rt/lib/RT/Ticket.pm index 905ae8fc6..2f075a20c 100755 --- a/rt/lib/RT/Ticket.pm +++ b/rt/lib/RT/Ticket.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -84,7 +62,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -166,7 +144,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -175,14 +153,14 @@ Returns the current value of id. =cut -=head2 EffectiveId +=item EffectiveId Returns the current value of EffectiveId. (In the database, EffectiveId is stored as int(11).) -=head2 SetEffectiveId VALUE +=item SetEffectiveId VALUE Set EffectiveId to VALUE. @@ -193,14 +171,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Queue +=item Queue Returns the current value of Queue. (In the database, Queue is stored as int(11).) -=head2 SetQueue VALUE +=item SetQueue VALUE Set Queue to VALUE. @@ -211,7 +189,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 QueueObj +=item QueueObj Returns the Queue Object which has the id returned by Queue @@ -225,14 +203,14 @@ sub QueueObj { return($Queue); } -=head2 Type +=item Type Returns the current value of Type. (In the database, Type is stored as varchar(16).) -=head2 SetType VALUE +=item SetType VALUE Set Type to VALUE. @@ -243,14 +221,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 IssueStatement +=item IssueStatement Returns the current value of IssueStatement. (In the database, IssueStatement is stored as int(11).) -=head2 SetIssueStatement VALUE +=item SetIssueStatement VALUE Set IssueStatement to VALUE. @@ -261,14 +239,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Resolution +=item Resolution Returns the current value of Resolution. (In the database, Resolution is stored as int(11).) -=head2 SetResolution VALUE +=item SetResolution VALUE Set Resolution to VALUE. @@ -279,14 +257,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Owner +=item Owner Returns the current value of Owner. (In the database, Owner is stored as int(11).) -=head2 SetOwner VALUE +=item SetOwner VALUE Set Owner to VALUE. @@ -297,14 +275,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Subject +=item Subject Returns the current value of Subject. (In the database, Subject is stored as varchar(200).) -=head2 SetSubject VALUE +=item SetSubject VALUE Set Subject to VALUE. @@ -315,14 +293,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 InitialPriority +=item InitialPriority Returns the current value of InitialPriority. (In the database, InitialPriority is stored as int(11).) -=head2 SetInitialPriority VALUE +=item SetInitialPriority VALUE Set InitialPriority to VALUE. @@ -333,14 +311,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 FinalPriority +=item FinalPriority Returns the current value of FinalPriority. (In the database, FinalPriority is stored as int(11).) -=head2 SetFinalPriority VALUE +=item SetFinalPriority VALUE Set FinalPriority to VALUE. @@ -351,14 +329,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Priority +=item Priority Returns the current value of Priority. (In the database, Priority is stored as int(11).) -=head2 SetPriority VALUE +=item SetPriority VALUE Set Priority to VALUE. @@ -369,14 +347,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 TimeEstimated +=item TimeEstimated Returns the current value of TimeEstimated. (In the database, TimeEstimated is stored as int(11).) -=head2 SetTimeEstimated VALUE +=item SetTimeEstimated VALUE Set TimeEstimated to VALUE. @@ -387,14 +365,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 TimeWorked +=item TimeWorked Returns the current value of TimeWorked. (In the database, TimeWorked is stored as int(11).) -=head2 SetTimeWorked VALUE +=item SetTimeWorked VALUE Set TimeWorked to VALUE. @@ -405,14 +383,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Status +=item Status Returns the current value of Status. (In the database, Status is stored as varchar(10).) -=head2 SetStatus VALUE +=item SetStatus VALUE Set Status to VALUE. @@ -423,14 +401,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 TimeLeft +=item TimeLeft Returns the current value of TimeLeft. (In the database, TimeLeft is stored as int(11).) -=head2 SetTimeLeft VALUE +=item SetTimeLeft VALUE Set TimeLeft to VALUE. @@ -441,14 +419,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Told +=item Told Returns the current value of Told. (In the database, Told is stored as datetime.) -=head2 SetTold VALUE +=item SetTold VALUE Set Told to VALUE. @@ -459,14 +437,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Starts +=item Starts Returns the current value of Starts. (In the database, Starts is stored as datetime.) -=head2 SetStarts VALUE +=item SetStarts VALUE Set Starts to VALUE. @@ -477,14 +455,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Started +=item Started Returns the current value of Started. (In the database, Started is stored as datetime.) -=head2 SetStarted VALUE +=item SetStarted VALUE Set Started to VALUE. @@ -495,14 +473,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Due +=item Due Returns the current value of Due. (In the database, Due is stored as datetime.) -=head2 SetDue VALUE +=item SetDue VALUE Set Due to VALUE. @@ -513,14 +491,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Resolved +=item Resolved Returns the current value of Resolved. (In the database, Resolved is stored as datetime.) -=head2 SetResolved VALUE +=item SetResolved VALUE Set Resolved to VALUE. @@ -531,7 +509,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 LastUpdatedBy +=item LastUpdatedBy Returns the current value of LastUpdatedBy. (In the database, LastUpdatedBy is stored as int(11).) @@ -540,7 +518,7 @@ Returns the current value of LastUpdatedBy. =cut -=head2 LastUpdated +=item LastUpdated Returns the current value of LastUpdated. (In the database, LastUpdated is stored as datetime.) @@ -549,7 +527,7 @@ Returns the current value of LastUpdated. =cut -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -558,7 +536,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -567,14 +545,14 @@ Returns the current value of Created. =cut -=head2 Disabled +=item Disabled Returns the current value of Disabled. (In the database, Disabled is stored as smallint(6).) -=head2 SetDisabled VALUE +=item SetDisabled VALUE Set Disabled to VALUE. @@ -586,59 +564,59 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, EffectiveId => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Queue => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Type => - {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, type => 'varchar(16)', default => ''}, IssueStatement => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Resolution => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Owner => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Subject => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => '[no subject]'}, + {read => 1, write => 1, type => 'varchar(200)', default => '[no subject]'}, InitialPriority => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, FinalPriority => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Priority => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, TimeEstimated => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, TimeWorked => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Status => - {read => 1, write => 1, sql_type => 12, length => 10, is_blob => 0, is_numeric => 0, type => 'varchar(10)', default => ''}, + {read => 1, write => 1, type => 'varchar(10)', default => ''}, TimeLeft => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Told => - {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, write => 1, type => 'datetime', default => ''}, Starts => - {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, write => 1, type => 'datetime', default => ''}, Started => - {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, write => 1, type => 'datetime', default => ''}, Due => - {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, write => 1, type => 'datetime', default => ''}, Resolved => - {read => 1, write => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, write => 1, type => 'datetime', default => ''}, LastUpdatedBy => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, LastUpdated => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, Disabled => - {read => 1, write => 1, sql_type => 5, length => 6, is_blob => 0, is_numeric => 1, type => 'smallint(6)', default => '0'}, + {read => 1, write => 1, type => 'smallint(6)', default => '0'}, } }; @@ -670,7 +648,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/TicketCustomFieldValue.pm b/rt/lib/RT/TicketCustomFieldValue.pm deleted file mode 100644 index 717647266..000000000 --- a/rt/lib/RT/TicketCustomFieldValue.pm +++ /dev/null @@ -1,308 +0,0 @@ -# {{{ BEGIN BPS TAGGED BLOCK -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC -# <jesse@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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 -# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) -# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. -# -# !! DO NOT EDIT THIS FILE !! -# - -use strict; - - -=head1 NAME - -RT::TicketCustomFieldValue - - -=head1 SYNOPSIS - -=head1 DESCRIPTION - -=head1 METHODS - -=cut - -package RT::TicketCustomFieldValue; -use RT::Record; -use RT::CustomField; -use RT::Ticket; - - -use vars qw( @ISA ); -@ISA= qw( RT::Record ); - -sub _Init { - my $self = shift; - - $self->Table('TicketCustomFieldValues'); - $self->SUPER::_Init(@_); -} - - - - - -=head2 Create PARAMHASH - -Create takes a hash of values and creates a row in the database: - - int(11) 'Ticket'. - int(11) 'CustomField'. - varchar(255) 'Content'. - -=cut - - - - -sub Create { - my $self = shift; - my %args = ( - Ticket => '0', - CustomField => '0', - Content => '', - - @_); - $self->SUPER::Create( - Ticket => $args{'Ticket'}, - CustomField => $args{'CustomField'}, - Content => $args{'Content'}, -); - -} - - - -=head2 id - -Returns the current value of id. -(In the database, id is stored as int(11).) - - -=cut - - -=head2 Ticket - -Returns the current value of Ticket. -(In the database, Ticket is stored as int(11).) - - - -=head2 SetTicket VALUE - - -Set Ticket to VALUE. -Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, Ticket will be stored as a int(11).) - - -=cut - - -=head2 TicketObj - -Returns the Ticket Object which has the id returned by Ticket - - -=cut - -sub TicketObj { - my $self = shift; - my $Ticket = RT::Ticket->new($self->CurrentUser); - $Ticket->Load($self->__Value('Ticket')); - return($Ticket); -} - -=head2 CustomField - -Returns the current value of CustomField. -(In the database, CustomField is stored as int(11).) - - - -=head2 SetCustomField VALUE - - -Set CustomField to VALUE. -Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, CustomField will be stored as a int(11).) - - -=cut - - -=head2 CustomFieldObj - -Returns the CustomField Object which has the id returned by CustomField - - -=cut - -sub CustomFieldObj { - my $self = shift; - my $CustomField = RT::CustomField->new($self->CurrentUser); - $CustomField->Load($self->__Value('CustomField')); - return($CustomField); -} - -=head2 Content - -Returns the current value of Content. -(In the database, Content is stored as varchar(255).) - - - -=head2 SetContent VALUE - - -Set Content to VALUE. -Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, Content will be stored as a varchar(255).) - - -=cut - - -=head2 Creator - -Returns the current value of Creator. -(In the database, Creator is stored as int(11).) - - -=cut - - -=head2 Created - -Returns the current value of Created. -(In the database, Created is stored as datetime.) - - -=cut - - -=head2 LastUpdatedBy - -Returns the current value of LastUpdatedBy. -(In the database, LastUpdatedBy is stored as int(11).) - - -=cut - - -=head2 LastUpdated - -Returns the current value of LastUpdated. -(In the database, LastUpdated is stored as datetime.) - - -=cut - - - -sub _CoreAccessible { - { - - id => - {read => 1, type => 'int(11)', default => ''}, - Ticket => - {read => 1, write => 1, type => 'int(11)', default => '0'}, - CustomField => - {read => 1, write => 1, type => 'int(11)', default => '0'}, - Content => - {read => 1, write => 1, type => 'varchar(255)', default => ''}, - Creator => - {read => 1, auto => 1, type => 'int(11)', default => '0'}, - Created => - {read => 1, auto => 1, type => 'datetime', default => ''}, - LastUpdatedBy => - {read => 1, auto => 1, type => 'int(11)', default => '0'}, - LastUpdated => - {read => 1, auto => 1, type => 'datetime', default => ''}, - - } -}; - - - eval "require RT::TicketCustomFieldValue_Overlay"; - if ($@ && $@ !~ qr{^Can't locate RT/TicketCustomFieldValue_Overlay.pm}) { - die $@; - }; - - eval "require RT::TicketCustomFieldValue_Vendor"; - if ($@ && $@ !~ qr{^Can't locate RT/TicketCustomFieldValue_Vendor.pm}) { - die $@; - }; - - eval "require RT::TicketCustomFieldValue_Local"; - if ($@ && $@ !~ qr{^Can't locate RT/TicketCustomFieldValue_Local.pm}) { - die $@; - }; - - - - -=head1 SEE ALSO - -This class allows "overlay" methods to be placed -into the following files _Overlay is for a System overlay by the original author, -_Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customizations. - -These overlay files can contain new subs or subs to replace existing subs in this module. - -If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line - - no warnings qw(redefine); - -so that perl does not kick and scream when you redefine a subroutine or variable in your overlay. - -RT::TicketCustomFieldValue_Overlay, RT::TicketCustomFieldValue_Vendor, RT::TicketCustomFieldValue_Local - -=cut - - -1; diff --git a/rt/lib/RT/TicketCustomFieldValue_Overlay.pm b/rt/lib/RT/TicketCustomFieldValue_Overlay.pm deleted file mode 100644 index 270c5939a..000000000 --- a/rt/lib/RT/TicketCustomFieldValue_Overlay.pm +++ /dev/null @@ -1,74 +0,0 @@ -# {{{ BEGIN BPS TAGGED BLOCK -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC -# <jesse@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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 -use strict; -no warnings qw(redefine); - - - -=head2 LoadByTicketContentAndCustomField { Ticket => TICKET, CustomField => CUSTOMFIELD, Content => CONTENT } - -Loads a custom field value by Ticket, Content and which CustomField it's tied to - -=cut - - -sub LoadByTicketContentAndCustomField { - my $self = shift; - my %args = ( Ticket => undef, - CustomField => undef, - Content => undef, - @_ - ); - - - $self->LoadByCols( Content => $args{'Content'}, - CustomField => $args{'CustomField'}, - Ticket => $args{'Ticket'}); - - -} - -1; diff --git a/rt/lib/RT/TicketCustomFieldValues.pm b/rt/lib/RT/TicketCustomFieldValues.pm deleted file mode 100644 index 2174afef3..000000000 --- a/rt/lib/RT/TicketCustomFieldValues.pm +++ /dev/null @@ -1,137 +0,0 @@ -# {{{ BEGIN BPS TAGGED BLOCK -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC -# <jesse@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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 -# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) -# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. -# -# !! DO NOT EDIT THIS FILE !! -# - -use strict; - - -=head1 NAME - - RT::TicketCustomFieldValues -- Class Description - -=head1 SYNOPSIS - - use RT::TicketCustomFieldValues - -=head1 DESCRIPTION - - -=head1 METHODS - -=cut - -package RT::TicketCustomFieldValues; - -use RT::SearchBuilder; -use RT::TicketCustomFieldValue; - -use vars qw( @ISA ); -@ISA= qw(RT::SearchBuilder); - - -sub _Init { - my $self = shift; - $self->{'table'} = 'TicketCustomFieldValues'; - $self->{'primary_key'} = 'id'; - - - return ( $self->SUPER::_Init(@_) ); -} - - -=head2 NewItem - -Returns an empty new RT::TicketCustomFieldValue item - -=cut - -sub NewItem { - my $self = shift; - return(RT::TicketCustomFieldValue->new($self->CurrentUser)); -} - - eval "require RT::TicketCustomFieldValues_Overlay"; - if ($@ && $@ !~ qr{^Can't locate RT/TicketCustomFieldValues_Overlay.pm}) { - die $@; - }; - - eval "require RT::TicketCustomFieldValues_Vendor"; - if ($@ && $@ !~ qr{^Can't locate RT/TicketCustomFieldValues_Vendor.pm}) { - die $@; - }; - - eval "require RT::TicketCustomFieldValues_Local"; - if ($@ && $@ !~ qr{^Can't locate RT/TicketCustomFieldValues_Local.pm}) { - die $@; - }; - - - - -=head1 SEE ALSO - -This class allows "overlay" methods to be placed -into the following files _Overlay is for a System overlay by the original author, -_Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customizations. - -These overlay files can contain new subs or subs to replace existing subs in this module. - -If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line - - no warnings qw(redefine); - -so that perl does not kick and scream when you redefine a subroutine or variable in your overlay. - -RT::TicketCustomFieldValues_Overlay, RT::TicketCustomFieldValues_Vendor, RT::TicketCustomFieldValues_Local - -=cut - - -1; diff --git a/rt/lib/RT/TicketCustomFieldValues_Overlay.pm b/rt/lib/RT/TicketCustomFieldValues_Overlay.pm deleted file mode 100644 index 8cbaca574..000000000 --- a/rt/lib/RT/TicketCustomFieldValues_Overlay.pm +++ /dev/null @@ -1,108 +0,0 @@ -# {{{ BEGIN BPS TAGGED BLOCK -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC -# <jesse@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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 -use strict; -no warnings qw(redefine); - -# {{{ sub LimitToCustomField - -=head2 LimitToCustomField FIELD - -Limits the returned set to values for the custom field with Id FIELD - -=cut - -sub LimitToCustomField { - my $self = shift; - my $cf = shift; - return ($self->Limit( FIELD => 'CustomField', - VALUE => $cf, - OPERATOR => '=')); - -} - -# }}} - -# {{{ sub LimitToTicket - -=head2 LimitToTicket TICKETID - -Limits the returned set to values for the ticket with Id TICKETID - -=cut - -sub LimitToTicket { - my $self = shift; - my $ticket = shift; - return ($self->Limit( FIELD => 'Ticket', - VALUE => $ticket, - OPERATOR => '=')); - -} - -# }}} - - -=sub HasEntry VALUE - -Returns true if this CustomFieldValues collection has an entry with content that eq VALUE - -=cut - - -sub HasEntry { - my $self = shift; - my $value = shift; - - #TODO: this could cache and optimize a fair bit. - foreach my $item (@{$self->ItemsArrayRef}) { - return(1) if ($item->Content eq $value); - } - return undef; - -} - -1; - diff --git a/rt/lib/RT/Tickets.pm b/rt/lib/RT/Tickets.pm index 0f880e11f..b6b349144 100755 --- a/rt/lib/RT/Tickets.pm +++ b/rt/lib/RT/Tickets.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::Ticket item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Transaction.pm b/rt/lib/RT/Transaction.pm index cca2281bc..ca491a6c7 100755 --- a/rt/lib/RT/Transaction.pm +++ b/rt/lib/RT/Transaction.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -67,6 +45,7 @@ RT::Transaction package RT::Transaction; use RT::Record; +use RT::Ticket; use vars qw( @ISA ); @@ -83,21 +62,18 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: - varchar(64) 'ObjectType'. - int(11) 'ObjectId'. + int(11) 'EffectiveTicket'. + int(11) 'Ticket'. int(11) 'TimeTaken'. varchar(20) 'Type'. varchar(40) 'Field'. varchar(255) 'OldValue'. varchar(255) 'NewValue'. - varchar(255) 'ReferenceType'. - int(11) 'OldReference'. - int(11) 'NewReference'. - varchar(255) 'Data'. + varchar(100) 'Data'. =cut @@ -107,30 +83,24 @@ Create takes a hash of values and creates a row in the database: sub Create { my $self = shift; my %args = ( - ObjectType => '', - ObjectId => '0', + EffectiveTicket => '0', + Ticket => '0', TimeTaken => '0', Type => '', Field => '', OldValue => '', NewValue => '', - ReferenceType => '', - OldReference => '', - NewReference => '', Data => '', @_); $self->SUPER::Create( - ObjectType => $args{'ObjectType'}, - ObjectId => $args{'ObjectId'}, + EffectiveTicket => $args{'EffectiveTicket'}, + Ticket => $args{'Ticket'}, TimeTaken => $args{'TimeTaken'}, Type => $args{'Type'}, Field => $args{'Field'}, OldValue => $args{'OldValue'}, NewValue => $args{'NewValue'}, - ReferenceType => $args{'ReferenceType'}, - OldReference => $args{'OldReference'}, - NewReference => $args{'NewReference'}, Data => $args{'Data'}, ); @@ -138,7 +108,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -147,50 +117,64 @@ Returns the current value of id. =cut -=head2 ObjectType +=item EffectiveTicket -Returns the current value of ObjectType. -(In the database, ObjectType is stored as varchar(64).) +Returns the current value of EffectiveTicket. +(In the database, EffectiveTicket is stored as int(11).) -=head2 SetObjectType VALUE +=item SetEffectiveTicket VALUE -Set ObjectType to VALUE. +Set EffectiveTicket to VALUE. Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, ObjectType will be stored as a varchar(64).) +(In the database, EffectiveTicket will be stored as a int(11).) =cut -=head2 ObjectId +=item Ticket -Returns the current value of ObjectId. -(In the database, ObjectId is stored as int(11).) +Returns the current value of Ticket. +(In the database, Ticket is stored as int(11).) -=head2 SetObjectId VALUE +=item SetTicket VALUE -Set ObjectId to VALUE. +Set Ticket to VALUE. Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, ObjectId will be stored as a int(11).) +(In the database, Ticket will be stored as a int(11).) + + +=cut + + +=item TicketObj + +Returns the Ticket Object which has the id returned by Ticket =cut +sub TicketObj { + my $self = shift; + my $Ticket = RT::Ticket->new($self->CurrentUser); + $Ticket->Load($self->__Value('Ticket')); + return($Ticket); +} -=head2 TimeTaken +=item TimeTaken Returns the current value of TimeTaken. (In the database, TimeTaken is stored as int(11).) -=head2 SetTimeTaken VALUE +=item SetTimeTaken VALUE Set TimeTaken to VALUE. @@ -201,14 +185,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Type +=item Type Returns the current value of Type. (In the database, Type is stored as varchar(20).) -=head2 SetType VALUE +=item SetType VALUE Set Type to VALUE. @@ -219,14 +203,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Field +=item Field Returns the current value of Field. (In the database, Field is stored as varchar(40).) -=head2 SetField VALUE +=item SetField VALUE Set Field to VALUE. @@ -237,14 +221,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 OldValue +=item OldValue Returns the current value of OldValue. (In the database, OldValue is stored as varchar(255).) -=head2 SetOldValue VALUE +=item SetOldValue VALUE Set OldValue to VALUE. @@ -255,14 +239,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 NewValue +=item NewValue Returns the current value of NewValue. (In the database, NewValue is stored as varchar(255).) -=head2 SetNewValue VALUE +=item SetNewValue VALUE Set NewValue to VALUE. @@ -273,79 +257,25 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ReferenceType - -Returns the current value of ReferenceType. -(In the database, ReferenceType is stored as varchar(255).) - - - -=head2 SetReferenceType VALUE - - -Set ReferenceType to VALUE. -Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, ReferenceType will be stored as a varchar(255).) - - -=cut - - -=head2 OldReference - -Returns the current value of OldReference. -(In the database, OldReference is stored as int(11).) - - - -=head2 SetOldReference VALUE - - -Set OldReference to VALUE. -Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, OldReference will be stored as a int(11).) - - -=cut - - -=head2 NewReference - -Returns the current value of NewReference. -(In the database, NewReference is stored as int(11).) - - - -=head2 SetNewReference VALUE - - -Set NewReference to VALUE. -Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, NewReference will be stored as a int(11).) - - -=cut - - -=head2 Data +=item Data Returns the current value of Data. -(In the database, Data is stored as varchar(255).) +(In the database, Data is stored as varchar(100).) -=head2 SetData VALUE +=item SetData VALUE Set Data to VALUE. Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, Data will be stored as a varchar(255).) +(In the database, Data will be stored as a varchar(100).) =cut -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -354,7 +284,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -364,37 +294,31 @@ Returns the current value of Created. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, - ObjectType => - {read => 1, write => 1, sql_type => 12, length => 64, is_blob => 0, is_numeric => 0, type => 'varchar(64)', default => ''}, - ObjectId => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, type => 'int(11)', default => ''}, + EffectiveTicket => + {read => 1, write => 1, type => 'int(11)', default => '0'}, + Ticket => + {read => 1, write => 1, type => 'int(11)', default => '0'}, TimeTaken => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, write => 1, type => 'int(11)', default => '0'}, Type => - {read => 1, write => 1, sql_type => 12, length => 20, is_blob => 0, is_numeric => 0, type => 'varchar(20)', default => ''}, + {read => 1, write => 1, type => 'varchar(20)', default => ''}, Field => - {read => 1, write => 1, sql_type => 12, length => 40, is_blob => 0, is_numeric => 0, type => 'varchar(40)', default => ''}, + {read => 1, write => 1, type => 'varchar(40)', default => ''}, OldValue => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, NewValue => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, - ReferenceType => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, - OldReference => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, - NewReference => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, write => 1, type => 'varchar(255)', default => ''}, Data => - {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''}, + {read => 1, write => 1, type => 'varchar(100)', default => ''}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, } }; @@ -426,7 +350,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Transactions.pm b/rt/lib/RT/Transactions.pm index 351b14c4e..23a475ac6 100755 --- a/rt/lib/RT/Transactions.pm +++ b/rt/lib/RT/Transactions.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::Transaction item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/URI/freeside.pm b/rt/lib/RT/URI/freeside.pm new file mode 100644 index 000000000..ff1d38d21 --- /dev/null +++ b/rt/lib/RT/URI/freeside.pm @@ -0,0 +1,285 @@ +# BEGIN LICENSE BLOCK +# +# Copyright (c) 2004 Kristian Hoffmann <khoff@fire2wire.com> +# Based on the original RT::URI::base and RT::URI::fsck_com_rt. +# +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# +# (Except where explictly superceded by other copyright notices) +# +# 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. +# +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. +# +# +# END LICENSE BLOCK +package RT::URI::freeside; + +use RT::URI::base; +use strict; +use vars qw(@ISA $IntegrationType $URL); +@ISA = qw/RT::URI::base/; + + +=head1 NAME + +RT::URI::freeside + +=head1 DESCRIPTION + +URI handler for freeside URIs. See http://www.sisd.com/freeside/ for +more information on freeside. + + +=head1 Public subroutines + +=over 4 + +=item FreesideGetConfig CONFKEY + +Subroutine that returns the freeside's configuration value(s) for CONFKEY +as a scalar or list. + +=cut + +sub FreesideGetConfig { return undef; } + + +=item FreesideURL + +Returns the URL for freeside's web interface. + +=cut + +sub FreesideURL { return $URL; } + + +=item FreesideVersion + +Returns a string describing the freeside version being used. + +=cut + +sub FreesideVersion { return undef; } + + +=item smart_search + +A wrapper for the FS::cust_main::smart_search subroutine. + +=cut + +sub smart_search { return undef; } + + +=item small_custview + +A wrapper for the FS::CGI::small_custview subroutine. + +=cut + +sub small_custview { return 'Freeside integration error!</A>'; } + + +=back + +=head1 Private methods + +=over 4 + +=item _FreesideGetRecord + +Method returns a hashref of the freeside record referenced in the URI. +Must be called after ParseURI. + +=cut + +sub _FreesideGetRecord { return undef; } + + +=item _FreesideURIPrefix + +Method that returns the URI prefix for freeside URIs. + +=cut + +sub _FreesideURIPrefix { + + my $self = shift; + return($self->Scheme . '://freeside'); + +} + +=item _FreesideURILabel + +Method that returns a short string describing the customer referenced +in the URI. + +=cut + +sub _FreesideURILabel { + + my $self = shift; + + $RT::Logger->debug("Called _FreesideURILabel()"); + + return unless (exists($self->{'fstable'}) and + exists($self->{'fspkey'})); + + my $label; + my ($table, $pkey) = ($self->{'fstable'}, $self->{'fspkey'}); + + if ($table ne 'cust_main') { + warn "FS::${table} not currently supported"; + return; + } + + my $rec = $self->_FreesideGetRecord(); + + if (ref($rec) eq 'HASH' and $table eq 'cust_main') { + my $name = $rec->{'last'} . ', ' . $rec->{'first'}; + $name = $rec->{'company'} . " ($name)" if $rec->{'company'}; + $label = "$pkey: $name"; + } else { + $label = "$pkey: $table"; + } + + if ($label and !$@) { + return($label); + } else { + return; + } + +} + +=item _FreesideURILabelLong + +Method that returns a longer string describing the customer referenced +in the URI. + +=cut + +sub _FreesideURILabelLong { + + my $self = shift; + + return $self->_FreesideURILabel(); + +} + +=back + +=head1 Public methods + +=over 4 + +=cut + +sub ParseURI { + my $self = shift; + my $uri = shift; + my ($table, $pkey); + + my $uriprefix = $self->_FreesideURIPrefix; + if ($uri =~ /^$uriprefix\/(\w+)\/(\d+)$/) { + $table = $1; + $pkey = $2; + $self->{'scheme'} = $self->Scheme; + } else { + return(undef); + } + + $self->{'uri'} = "${uriprefix}/${table}/${pkey}"; + $self->{'fstable'} = $table; + $self->{'fspkey'} = $pkey; + + + my $url = $self->FreesideURL(); + + if ($url ne '') { + $self->{'href'} = "${url}/view/${table}.cgi?${pkey}"; + } else { + $self->{'href'} = $self->{'uri'}; + } + + $self->{'uri'}; + +} + +sub Scheme { + my $self = shift; + return('freeside'); + +} + +sub HREF { + my $self = shift; + return($self->{'href'} || $self->{'uri'}); +} + +sub IsLocal { + my $self = shift; + return undef; +} + +=item AsString + +Return a "pretty" string representing the URI object. + +This is meant to be used like this: + + % $re = $uri->Resolver; + <A HREF="<% $re->HREF %>"><% $re->AsString %></A> + +=cut + +sub AsString { + my $self = shift; + my $prettystring; + if ($prettystring = $self->_FreesideURILabel) { + return $prettystring; + } else { + return $self->URI; + } +} + +=item AsStringLong + +Return a longer (HTML) string representing the URI object. + +=cut + +sub AsStringLong { + my $self = shift; + my $prettystring; + if ($prettystring = $self->_FreesideURILabelLong || $self->_FreesideURILabel){ + return $prettystring; + } else { + return $self->URI; + } +} + +$IntegrationType ||= 'Internal'; +eval "require RT::URI::freeside::${RT::URI::freeside::IntegrationType}"; +warn $@ if $@; +if ($@ && + $@ !~ qr(^Can't locate RT/URI/freeside/${RT::URI::freeside::IntegrationType}.pm)) { + die $@; +}; + +=back + +=cut + +1; diff --git a/rt/lib/RT/URI/freeside/Internal.pm b/rt/lib/RT/URI/freeside/Internal.pm new file mode 100644 index 000000000..9ca06306d --- /dev/null +++ b/rt/lib/RT/URI/freeside/Internal.pm @@ -0,0 +1,138 @@ +# BEGIN LICENSE BLOCK +# +# Copyright (c) 2004 Kristian Hoffmann <khoff@fire2wire.com> +# Based on the original RT::URI::base and RT::URI::fsck_com_rt. +# +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# +# (Except where explictly superceded by other copyright notices) +# +# 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. +# +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. +# +# +# END LICENSE BLOCK +# +use strict; +no warnings qw(redefine); + +#use vars qw($conf); + +use FS; +use FS::UID qw(dbh); +use FS::CGI qw(popurl small_custview); +use FS::Conf; +use FS::Record qw(qsearchs qsearch dbdef); +use FS::cust_main; +use FS::cust_svc; + +=head1 NAME + +RT::URI::freeside::Internal + +=head1 DESCRIPTION + +Overlay for the RT::URI::freeside URI handler implementing the Internal integration type. + +See L<RT::URI::freeside> for public/private interface documentation. + +=cut + + + +sub _FreesideGetRecord { + + my $self = shift; + my ($table, $pkey) = ($self->{'fstable'}, $self->{'fspkey'}); + + $RT::Logger->debug("Called _FreesideGetRecord()"); + + #eval "use FS::$table;"; + + my $dbdef = dbdef; + unless ($dbdef) { + $RT::Logger->error("Using Internal freeside integration type, ". + "but it doesn't look like we're running under ". + "freeside's Mason handler."); + return; + } + + my $pkeyfield = $dbdef->table($table)->primary_key; + unless ($pkeyfield) { + $RT::Logger->error("No primary key for freeside table '$table'"); + return; + } + + my $fsrec = qsearchs($table, { $pkeyfield => $pkey }); + unless ($fsrec) { + $RT::Logger->error("Record with '$pkeyfield' == '$pkey' does " . + "not exist in table $table"); + return; + } + + return { $fsrec->hash, '_object' => $fsrec }; + +} + +sub FreesideVersion { + + return $FS::VERSION; + +} + +sub FreesideGetConfig { + + #$conf = new FS::Conf unless ref($conf); + my $conf = new FS::Conf; + + return scalar($conf->config(@_)); + +} + +sub smart_search { #Subroutine + + return map { { $_->hash } } &FS::cust_main::smart_search(@_); + +} + +sub small_custview { + + return &FS::CGI::small_custview(@_); + +} + +sub _FreesideURILabelLong { + + my $self = shift; + + my $table = $self->{'fstable'}; + + if ( $table eq 'cust_main' ) { + + my $rec = $self->_FreesideGetRecord(); + return small_custview( $rec->{'_object'}, + scalar(FS::Conf->new->config('countrydefault')), + 1 #nobalance + ); + + } else { + + return $self->_FreesideURILabel(); + + } + +} + +1; diff --git a/rt/lib/RT/URI/freeside/XMLRPC.pm b/rt/lib/RT/URI/freeside/XMLRPC.pm new file mode 100644 index 000000000..a8a731fcd --- /dev/null +++ b/rt/lib/RT/URI/freeside/XMLRPC.pm @@ -0,0 +1,122 @@ +# BEGIN LICENSE BLOCK +# +# Copyright (c) 2004 Kristian Hoffmann <khoff@fire2wire.com> +# Based on the original RT::URI::base and RT::URI::fsck_com_rt. +# +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# +# (Except where explictly superceded by other copyright notices) +# +# 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. +# +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. +# +# +# END LICENSE BLOCK + +use strict; +no warnings qw(redefine); + +use vars qw($XMLRPC_URL $_FS_VERSION); + +use Frontier::Client; + +=head1 NAME + +RT::URI::freeside::XMLRPC + +=head1 DESCRIPTION + +Overlay for the RT::URI::freeside URI handler implementing the XMLRPC integration type. + +See L<RT::URI::freeside> for public/private interface documentation. + +=cut + + +sub _XMLRPCRequest { #Subroutine + + my $method = shift; + my @args = @_; + + my $result; + eval { + my $server = new Frontier::Client ( url => $XMLRPC_URL ); + $result = $server->call($method, @args); + }; + + if (not $@ and ref($result) eq 'ARRAY') { + return (scalar(@$result) == 1) ? @$result[0] : @$result; + } else { + $RT::Logger->debug("Freeside XMLRPC: " . $result || $@); + return (); + } + +} + +sub _FreesideGetRecord { + + my $self = shift; + my ($table, $pkey) = ($self->{'fstable'}, $self->{'fspkey'}); + my $record; + + $RT::Logger->debug("Called XMLRPC::_FreesideGetRecord()"); + + #FIXME: Need a better way to get primary keys. + # Maybe create a method for it and cache them like version? + my %table_pkeys = ( + cust_main => 'custnum', + ); + + my $method = 'Record.qsearchs'; + my @args = ($table, { $table_pkeys{$table} => $pkey }); + my ($record) = &_XMLRPCRequest($method, @args); + + return $record; + +} + + +sub FreesideGetConfig { + + return _XMLRPCRequest('Conf.config', @_); + +} + + +sub FreesideVersion { + + return $_FS_VERSION if ($_FS_VERSION =~ /^\d+\.\d+\.\d+/); + + $RT::Logger->debug("Requesting freeside version..."); + ($_FS_VERSION) = &_XMLRPCRequest('version'); + $RT::Logger->debug("Cached freeside version: ${_FS_VERSION}"); + + return $_FS_VERSION; + +} + +sub smart_search { #Subroutine + + return _XMLRPCRequest('cust_main.smart_search', @_); + +} + +sub small_custview { + + return _XMLRPCRequest('CGI.small_custview', @_); + +} + +1; diff --git a/rt/lib/RT/User.pm b/rt/lib/RT/User.pm index 18edfd476..cbc10f5b4 100755 --- a/rt/lib/RT/User.pm +++ b/rt/lib/RT/User.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -83,7 +61,7 @@ sub _Init { -=head2 Create PARAMHASH +=item Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -192,7 +170,7 @@ sub Create { -=head2 id +=item id Returns the current value of id. (In the database, id is stored as int(11).) @@ -201,14 +179,14 @@ Returns the current value of id. =cut -=head2 Name +=item Name Returns the current value of Name. (In the database, Name is stored as varchar(200).) -=head2 SetName VALUE +=item SetName VALUE Set Name to VALUE. @@ -219,14 +197,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Password +=item Password Returns the current value of Password. (In the database, Password is stored as varchar(40).) -=head2 SetPassword VALUE +=item SetPassword VALUE Set Password to VALUE. @@ -237,14 +215,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Comments +=item Comments Returns the current value of Comments. (In the database, Comments is stored as blob.) -=head2 SetComments VALUE +=item SetComments VALUE Set Comments to VALUE. @@ -255,14 +233,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Signature +=item Signature Returns the current value of Signature. (In the database, Signature is stored as blob.) -=head2 SetSignature VALUE +=item SetSignature VALUE Set Signature to VALUE. @@ -273,14 +251,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 EmailAddress +=item EmailAddress Returns the current value of EmailAddress. (In the database, EmailAddress is stored as varchar(120).) -=head2 SetEmailAddress VALUE +=item SetEmailAddress VALUE Set EmailAddress to VALUE. @@ -291,14 +269,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 FreeformContactInfo +=item FreeformContactInfo Returns the current value of FreeformContactInfo. (In the database, FreeformContactInfo is stored as blob.) -=head2 SetFreeformContactInfo VALUE +=item SetFreeformContactInfo VALUE Set FreeformContactInfo to VALUE. @@ -309,14 +287,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Organization +=item Organization Returns the current value of Organization. (In the database, Organization is stored as varchar(200).) -=head2 SetOrganization VALUE +=item SetOrganization VALUE Set Organization to VALUE. @@ -327,14 +305,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 RealName +=item RealName Returns the current value of RealName. (In the database, RealName is stored as varchar(120).) -=head2 SetRealName VALUE +=item SetRealName VALUE Set RealName to VALUE. @@ -345,14 +323,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 NickName +=item NickName Returns the current value of NickName. (In the database, NickName is stored as varchar(16).) -=head2 SetNickName VALUE +=item SetNickName VALUE Set NickName to VALUE. @@ -363,14 +341,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Lang +=item Lang Returns the current value of Lang. (In the database, Lang is stored as varchar(16).) -=head2 SetLang VALUE +=item SetLang VALUE Set Lang to VALUE. @@ -381,14 +359,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 EmailEncoding +=item EmailEncoding Returns the current value of EmailEncoding. (In the database, EmailEncoding is stored as varchar(16).) -=head2 SetEmailEncoding VALUE +=item SetEmailEncoding VALUE Set EmailEncoding to VALUE. @@ -399,14 +377,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 WebEncoding +=item WebEncoding Returns the current value of WebEncoding. (In the database, WebEncoding is stored as varchar(16).) -=head2 SetWebEncoding VALUE +=item SetWebEncoding VALUE Set WebEncoding to VALUE. @@ -417,14 +395,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ExternalContactInfoId +=item ExternalContactInfoId Returns the current value of ExternalContactInfoId. (In the database, ExternalContactInfoId is stored as varchar(100).) -=head2 SetExternalContactInfoId VALUE +=item SetExternalContactInfoId VALUE Set ExternalContactInfoId to VALUE. @@ -435,14 +413,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ContactInfoSystem +=item ContactInfoSystem Returns the current value of ContactInfoSystem. (In the database, ContactInfoSystem is stored as varchar(30).) -=head2 SetContactInfoSystem VALUE +=item SetContactInfoSystem VALUE Set ContactInfoSystem to VALUE. @@ -453,14 +431,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 ExternalAuthId +=item ExternalAuthId Returns the current value of ExternalAuthId. (In the database, ExternalAuthId is stored as varchar(100).) -=head2 SetExternalAuthId VALUE +=item SetExternalAuthId VALUE Set ExternalAuthId to VALUE. @@ -471,14 +449,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 AuthSystem +=item AuthSystem Returns the current value of AuthSystem. (In the database, AuthSystem is stored as varchar(30).) -=head2 SetAuthSystem VALUE +=item SetAuthSystem VALUE Set AuthSystem to VALUE. @@ -489,14 +467,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Gecos +=item Gecos Returns the current value of Gecos. (In the database, Gecos is stored as varchar(16).) -=head2 SetGecos VALUE +=item SetGecos VALUE Set Gecos to VALUE. @@ -507,14 +485,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 HomePhone +=item HomePhone Returns the current value of HomePhone. (In the database, HomePhone is stored as varchar(30).) -=head2 SetHomePhone VALUE +=item SetHomePhone VALUE Set HomePhone to VALUE. @@ -525,14 +503,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 WorkPhone +=item WorkPhone Returns the current value of WorkPhone. (In the database, WorkPhone is stored as varchar(30).) -=head2 SetWorkPhone VALUE +=item SetWorkPhone VALUE Set WorkPhone to VALUE. @@ -543,14 +521,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 MobilePhone +=item MobilePhone Returns the current value of MobilePhone. (In the database, MobilePhone is stored as varchar(30).) -=head2 SetMobilePhone VALUE +=item SetMobilePhone VALUE Set MobilePhone to VALUE. @@ -561,14 +539,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 PagerPhone +=item PagerPhone Returns the current value of PagerPhone. (In the database, PagerPhone is stored as varchar(30).) -=head2 SetPagerPhone VALUE +=item SetPagerPhone VALUE Set PagerPhone to VALUE. @@ -579,14 +557,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Address1 +=item Address1 Returns the current value of Address1. (In the database, Address1 is stored as varchar(200).) -=head2 SetAddress1 VALUE +=item SetAddress1 VALUE Set Address1 to VALUE. @@ -597,14 +575,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Address2 +=item Address2 Returns the current value of Address2. (In the database, Address2 is stored as varchar(200).) -=head2 SetAddress2 VALUE +=item SetAddress2 VALUE Set Address2 to VALUE. @@ -615,14 +593,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 City +=item City Returns the current value of City. (In the database, City is stored as varchar(100).) -=head2 SetCity VALUE +=item SetCity VALUE Set City to VALUE. @@ -633,14 +611,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 State +=item State Returns the current value of State. (In the database, State is stored as varchar(100).) -=head2 SetState VALUE +=item SetState VALUE Set State to VALUE. @@ -651,14 +629,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Zip +=item Zip Returns the current value of Zip. (In the database, Zip is stored as varchar(16).) -=head2 SetZip VALUE +=item SetZip VALUE Set Zip to VALUE. @@ -669,14 +647,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Country +=item Country Returns the current value of Country. (In the database, Country is stored as varchar(50).) -=head2 SetCountry VALUE +=item SetCountry VALUE Set Country to VALUE. @@ -687,14 +665,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Timezone +=item Timezone Returns the current value of Timezone. (In the database, Timezone is stored as varchar(50).) -=head2 SetTimezone VALUE +=item SetTimezone VALUE Set Timezone to VALUE. @@ -705,14 +683,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 PGPKey +=item PGPKey Returns the current value of PGPKey. (In the database, PGPKey is stored as text.) -=head2 SetPGPKey VALUE +=item SetPGPKey VALUE Set PGPKey to VALUE. @@ -723,7 +701,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Creator +=item Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -732,7 +710,7 @@ Returns the current value of Creator. =cut -=head2 Created +=item Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -741,7 +719,7 @@ Returns the current value of Created. =cut -=head2 LastUpdatedBy +=item LastUpdatedBy Returns the current value of LastUpdatedBy. (In the database, LastUpdatedBy is stored as int(11).) @@ -750,7 +728,7 @@ Returns the current value of LastUpdatedBy. =cut -=head2 LastUpdated +=item LastUpdated Returns the current value of LastUpdated. (In the database, LastUpdated is stored as datetime.) @@ -760,77 +738,77 @@ Returns the current value of LastUpdated. -sub _CoreAccessible { +sub _ClassAccessible { { id => - {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, + {read => 1, type => 'int(11)', default => ''}, Name => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, type => 'varchar(200)', default => ''}, Password => - {read => 1, write => 1, sql_type => 12, length => 40, is_blob => 0, is_numeric => 0, type => 'varchar(40)', default => ''}, + {read => 1, write => 1, type => 'varchar(40)', default => ''}, Comments => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''}, + {read => 1, write => 1, type => 'blob', default => ''}, Signature => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''}, + {read => 1, write => 1, type => 'blob', default => ''}, EmailAddress => - {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''}, + {read => 1, write => 1, type => 'varchar(120)', default => ''}, FreeformContactInfo => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''}, + {read => 1, write => 1, type => 'blob', default => ''}, Organization => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, type => 'varchar(200)', default => ''}, RealName => - {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''}, + {read => 1, write => 1, type => 'varchar(120)', default => ''}, NickName => - {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, type => 'varchar(16)', default => ''}, Lang => - {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, type => 'varchar(16)', default => ''}, EmailEncoding => - {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, type => 'varchar(16)', default => ''}, WebEncoding => - {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, type => 'varchar(16)', default => ''}, ExternalContactInfoId => - {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''}, + {read => 1, write => 1, type => 'varchar(100)', default => ''}, ContactInfoSystem => - {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, type => 'varchar(30)', default => ''}, ExternalAuthId => - {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''}, + {read => 1, write => 1, type => 'varchar(100)', default => ''}, AuthSystem => - {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, type => 'varchar(30)', default => ''}, Gecos => - {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, type => 'varchar(16)', default => ''}, HomePhone => - {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, type => 'varchar(30)', default => ''}, WorkPhone => - {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, type => 'varchar(30)', default => ''}, MobilePhone => - {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, type => 'varchar(30)', default => ''}, PagerPhone => - {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, type => 'varchar(30)', default => ''}, Address1 => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, type => 'varchar(200)', default => ''}, Address2 => - {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, type => 'varchar(200)', default => ''}, City => - {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''}, + {read => 1, write => 1, type => 'varchar(100)', default => ''}, State => - {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''}, + {read => 1, write => 1, type => 'varchar(100)', default => ''}, Zip => - {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, type => 'varchar(16)', default => ''}, Country => - {read => 1, write => 1, sql_type => 12, length => 50, is_blob => 0, is_numeric => 0, type => 'varchar(50)', default => ''}, + {read => 1, write => 1, type => 'varchar(50)', default => ''}, Timezone => - {read => 1, write => 1, sql_type => 12, length => 50, is_blob => 0, is_numeric => 0, type => 'varchar(50)', default => ''}, + {read => 1, write => 1, type => 'varchar(50)', default => ''}, PGPKey => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + {read => 1, write => 1, type => 'text', default => ''}, Creator => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, LastUpdatedBy => - {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, type => 'int(11)', default => '0'}, LastUpdated => - {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, + {read => 1, auto => 1, type => 'datetime', default => ''}, } }; @@ -862,7 +840,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/RT/Users.pm b/rt/lib/RT/Users.pm index abe471f18..d58f69653 100755 --- a/rt/lib/RT/Users.pm +++ b/rt/lib/RT/Users.pm @@ -1,14 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# BEGIN LICENSE BLOCK # -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC -# <jesse@bestpractical.com> +# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> # -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: +# (Except where explictly superceded by other copyright notices) # # 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 @@ -20,29 +14,13 @@ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# -# 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.) +# Unless otherwise specified, all modifications, corrections or +# extensions to this work which alter its source code become the +# property of Best Practical Solutions, LLC when submitted for +# inclusion in the work. # -# 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 }}} +# END LICENSE BLOCK # Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -86,7 +64,7 @@ sub _Init { } -=head2 NewItem +=item NewItem Returns an empty new RT::User item @@ -123,7 +101,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -Each of these files should begin with the line +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line no warnings qw(redefine); diff --git a/rt/lib/t/00smoke.t.in b/rt/lib/t/00smoke.t.in deleted file mode 100644 index 288dd4aae..000000000 --- a/rt/lib/t/00smoke.t.in +++ /dev/null @@ -1,14 +0,0 @@ -#!@PERL@ - -use Test::More qw(no_plan); - -use lib "@RT_LIB_PATH@"; -use RT; -ok(RT::LoadConfig); -ok(RT::Init, "Basic initialization and DB connectivity"); - -use File::Find; -File::Find::find({wanted => \&wanted}, 'lib/'); -sub wanted { /^*\.pm\z/s && ok(require $_, "Requiring '$_'"); } - - diff --git a/rt/lib/t/01harness.t.in b/rt/lib/t/01harness.t.in deleted file mode 100644 index d132330c2..000000000 --- a/rt/lib/t/01harness.t.in +++ /dev/null @@ -1,12 +0,0 @@ -#!@PERL@ - -use Test::More qw(no_plan); - -use lib "@RT_LIB_PATH@"; -use RT; -ok(RT::LoadConfig); -ok(RT::Init, "Basic initialization and DB connectivity"); - -my $test = shift @ARGV; -require $test; - diff --git a/rt/lib/t/02regression.t.in b/rt/lib/t/02regression.t.in deleted file mode 100644 index c2e3277a9..000000000 --- a/rt/lib/t/02regression.t.in +++ /dev/null @@ -1,47 +0,0 @@ -#!@PERL@ - -use Test::More qw(no_plan); - -use lib "@RT_LIB_PATH@"; -use RT; -ok(RT::LoadConfig); -ok(RT::Init, "Basic initialization and DB connectivity"); - -# Create a new queue -use_ok(RT::Queue); -my $q = RT::Queue->new($RT::SystemUser); - -$q->Load('regression'); -if ($q->id != 0) { - die "Regression tests not starting with a clean DB. Bailing"; -} - -my ($id, $msg) = $q->Create( Name => 'Regression', - Description => 'A regression test queue', - CorrespondAddress => 'correspond@a', - CommentAddress => 'comment@a'); - -isnt($id, 0, "Queue was created sucessfully - $msg"); - -my $q2 = RT::Queue->new($RT::SystemUser); - -ok($q2->Load($id)); -is($q2->id, $id, "Sucessfully loaded the queue again"); -is($q2->Name, 'Regression'); -is($q2->Description, 'A regression test queue'); -is($q2->CorrespondAddress, 'correspond@a'); -is($q2->CommentAddress, 'comment@a'); - - -use File::Find; -File::Find::find({wanted => \&wanted_autogen, - preprocess => sub {return sort @_}}, 'lib/t/autogen'); -sub wanted_autogen { /^autogen.*\.t\z/s && require $_; } - -File::Find::find({wanted => \&wanted_regression, - preprocess => sub {return sort @_}}, 'lib/t/regression'); -sub wanted_regression { /^*\.t\z/s && require $_; } - -require "@RT_LIB_PATH@/t/03web.pl"; -require "@RT_LIB_PATH@/t/04_send_email.pl"; -require "@RT_LIB_PATH@/t/05cronsupport.pl"; diff --git a/rt/lib/t/03web.pl.in b/rt/lib/t/03web.pl.in deleted file mode 100644 index 25c26e711..000000000 --- a/rt/lib/t/03web.pl.in +++ /dev/null @@ -1,170 +0,0 @@ -#!@PERL@ - -use strict; -use WWW::Mechanize; -use HTTP::Request::Common; -use HTTP::Cookies; -use LWP; -use Encode; - -my $cookie_jar = HTTP::Cookies->new; -my $agent = WWW::Mechanize->new(); - -# give the agent a place to stash the cookies - -$agent->cookie_jar($cookie_jar); - - -# get the top page -my $url = "http://localhost".$RT::WebPath."/"; -$agent->get($url); - -is ($agent->{'status'}, 200, "Loaded a page"); - - -# {{{ test a login - -# follow the link marked "Login" - -ok($agent->{form}->find_input('user')); - -ok($agent->{form}->find_input('pass')); -ok ($agent->{'content'} =~ /username:/i); -$agent->field( 'user' => 'root' ); -$agent->field( 'pass' => 'password' ); -# the field isn't named, so we have to click link 0 -$agent->click(0); -is($agent->{'status'}, 200, "Fetched the page ok"); -ok( $agent->{'content'} =~ /Logout/i, "Found a logout link"); - - - -$agent->get($url."Ticket/Create.html?Queue=1"); -is ($agent->{'status'}, 200, "Loaded Create.html"); -$agent->form(3); -# Start with a string containing characters in latin1 -my $string = "I18N Web Testing æøå"; -Encode::from_to($string, 'iso-8859-1', 'utf8'); -$agent->field('Subject' => "Foo"); -$agent->field('Content' => $string); -ok($agent->submit(), "Created new ticket with $string"); - -ok( $agent->{'content'} =~ qr{$string} , "Found the content"); - -$agent->get($url."Ticket/Create.html?Queue=1"); -is ($agent->{'status'}, 200, "Loaded Create.html"); -$agent->form(3); -# Start with a string containing characters in latin1 -my $string = "I18N Web Testing æøå"; -Encode::from_to($string, 'iso-8859-1', 'utf8'); -$agent->field('Subject' => $string); -$agent->field('Content' => "BAR"); -ok($agent->submit(), "Created new ticket with $string"); - -ok( $agent->{'content'} =~ qr{$string} , "Found the content"); - - - -# }}} - -# {{{ Query Builder tests - -my $response = $agent->get($url."Search/Build.html"); -ok( $response->is_success, "Fetched " . $url."Search/Build.html" ); - -# Parsing TicketSQL -# -# Adding items - -# set the first value -ok($agent->form_name('BuildQuery')); -$agent->field("AttachmentField", "Subject"); -$agent->field("AttachmentOp", "LIKE"); -$agent->field("ValueOfAttachment", "aaa"); -$agent->submit(); - -# set the next value -ok($agent->form_name('BuildQuery')); -$agent->field("AttachmentField", "Subject"); -$agent->field("AttachmentOp", "LIKE"); -$agent->field("ValueOfAttachment", "bbb"); -$agent->submit(); - -ok($agent->form_name('BuildQuery')); - -# get the query -my $query = $agent->current_form->find_input("Query")->value; -# strip whitespace from ends -$query =~ s/^\s*//g; -$query =~ s/\s*$//g; - -# collapse other whitespace -$query =~ s/\s+/ /g; - -is ($query, "Subject LIKE 'aaa' AND Subject LIKE 'bbb'"); - -# - new items go one level down -# - add items at currently selected level -# - if nothing is selected, add at end, one level down -# -# move left -# - error if nothing selected -# - same item should be selected after move -# - can't move left if you're at the top level -# -# move right -# - error if nothing selected -# - same item should be selected after move -# - can always move right (no max depth...should there be?) -# -# move up -# - error if nothing selected -# - same item should be selected after move -# - can't move up if you're first in the list -# -# move down -# - error if nothing selected -# - same item should be selected after move -# - can't move down if you're last in the list -# -# toggle -# - error if nothing selected -# - change all aggregators in the grouping -# - don't change any others -# -# delete -# - error if nothing selected -# - delete currently selected item -# - delete all children of a grouping -# - if delete leaves a node with no children, delete that, too -# - what should be selected? -# -# Clear -# - clears entire query -# - clears it from the session, too - -# }}} - -use File::Find; -find ( \&wanted , 'html/'); - -sub wanted { - -f && /\.html$/ && $_ !~ /Logout.html$/ && test_get($File::Find::name); -} - -sub test_get { - my $file = shift; - - - $file =~ s#^html/##; - ok ($agent->get("$url/$file", "GET $url/$file")); - is ($agent->{'status'}, 200, "Loaded $file"); -# ok( $agent->{'content'} =~ /Logout/i, "Found a logout link on $file "); - ok( $agent->{'content'} !~ /Not logged in/i, "Still logged in for $file"); - ok( $agent->{'content'} !~ /System error/i, "Didn't get a Mason compilation error on $file"); - -} - -# }}} - -1; diff --git a/rt/lib/t/04_send_email.pl.in b/rt/lib/t/04_send_email.pl.in deleted file mode 100644 index 39ab0d271..000000000 --- a/rt/lib/t/04_send_email.pl.in +++ /dev/null @@ -1,506 +0,0 @@ -#!@PERL@ -w - -use strict; -use RT::EmailParser; -use RT::Tickets; -use RT::Action::SendEmail; - -my @_outgoing_messages; -my @scrips_fired; - -#We're not testing acls here. -my $everyone = RT::Group->new($RT::SystemUser); -$everyone->LoadSystemInternalGroup('Everyone'); -$everyone->PrincipalObj->GrantRight(Right =>'SuperUser'); - - -is (__PACKAGE__, 'main', "We're operating in the main package"); - - -{ -no warnings qw/redefine/; -sub RT::Action::SendEmail::SendMessage { - my $self = shift; - my $MIME = shift; - - main::_fired_scrip($self->ScripObj); - main::ok(ref($MIME) eq 'MIME::Entity', "hey, look. it's a mime entity"); -} - -} - -# instrument SendEmail to pass us what it's about to send. -# create a regular ticket - -my $parser = RT::EmailParser->new(); - - -# Let's test to make sure a multipart/report is processed correctly -my $content = `cat @RT_LIB_PATH@/t/data/multipart-report` || die "couldn't find new content"; -# be as much like the mail gateway as possible. -use RT::Interface::Email; - -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -ok ($tick->Transactions->First->Content =~ /The original message was received/, "It's the bounce"); - - -# make sure it fires scrips. -is ($#scrips_fired, 1, "Fired 2 scrips on ticket creation"); - -undef @scrips_fired; - - - - -$parser->ParseMIMEEntityFromScalar('From: root@localhost -To: rt@example.com -Subject: This is a test of new ticket creation as an unknown user - -Blah! -Foob!'); - - -use Data::Dumper; - -my $ticket = RT::Ticket->new($RT::SystemUser); -my ($id, $tid, $msg ) = $ticket->Create(Requestor => ['root@localhost'], Queue => 'general', Subject => 'I18NTest', MIMEObj => $parser->Entity); -ok ($id,$msg); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); -ok ($tick->Subject eq 'I18NTest', "failed to create the new ticket from an unprivileged account"); - -# make sure it fires scrips. -is ($#scrips_fired, 1, "Fired 2 scrips on ticket creation"); -# make sure it sends an autoreply -# make sure it sends a notification to adminccs - - -# we need to swap out SendMessage to test the new things we care about; -&utf8_redef_sendmessage; - -# create an iso 8859-1 ticket -@scrips_fired = (); - -my $content = `cat @RT_LIB_PATH@/t/data/new-ticket-from-iso-8859-1` || die "couldn't find new content"; - - - -$parser->ParseMIMEEntityFromScalar($content); - - -# be as much like the mail gateway as possible. -use RT::Interface::Email; - -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -ok ($tick->Transactions->First->Content =~ /H\x{e5}vard/, "It's signed by havard. yay"); - - -# make sure it fires scrips. -is ($#scrips_fired, 1, "Fired 2 scrips on ticket creation"); -# make sure it sends an autoreply - - -# make sure it sends a notification to adminccs - -# If we correspond, does it do the right thing to the outbound messages? - -$parser->ParseMIMEEntityFromScalar($content); -my ($id, $msg) = $tick->Comment(MIMEObj => $parser->Entity); -ok ($id, $msg); - -$parser->ParseMIMEEntityFromScalar($content); -($id, $msg) = $tick->Correspond(MIMEObj => $parser->Entity); -ok ($id, $msg); - - - - - -# we need to swap out SendMessage to test the new things we care about; -&iso8859_redef_sendmessage; -$RT::EmailOutputEncoding = 'iso-8859-1'; -# create an iso 8859-1 ticket -@scrips_fired = (); - -my $content = `cat @RT_LIB_PATH@/t/data/new-ticket-from-iso-8859-1` || die "couldn't find new content"; -# be as much like the mail gateway as possible. -use RT::Interface::Email; - -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -ok ($tick->Transactions->First->Content =~ /H\x{e5}vard/, "It's signed by havard. yay"); - - -# make sure it fires scrips. -is ($#scrips_fired, 1, "Fired 2 scrips on ticket creation"); -# make sure it sends an autoreply - - -# make sure it sends a notification to adminccs - - -# If we correspond, does it do the right thing to the outbound messages? - -$parser->ParseMIMEEntityFromScalar($content); -my ($id, $msg) = $tick->Comment(MIMEObj => $parser->Entity); -ok ($id, $msg); - -$parser->ParseMIMEEntityFromScalar($content); -($id, $msg) = $tick->Correspond(MIMEObj => $parser->Entity); -ok ($id, $msg); - - -sub _fired_scrip { - my $scrip = shift; - push @scrips_fired, $scrip; -} - -sub utf8_redef_sendmessage { - no warnings qw/redefine/; - eval ' - sub RT::Action::SendEmail::SendMessage { - my $self = shift; - my $MIME = shift; - - my $scrip = $self->ScripObj->id; - ok(1, $self->ScripObj->ConditionObj->Name . " ".$self->ScripObj->ActionObj->Name); - main::_fired_scrip($self->ScripObj); - $MIME->make_singlepart; - main::ok( ref($MIME) eq \'MIME::Entity\', - "hey, look. it\'s a mime entity" ); - main::ok( ref( $MIME->head ) eq \'MIME::Head\', - "its mime header is a mime header. yay" ); - main::ok( $MIME->head->get(\'Content-Type\') =~ /utf-8/, - "Its content type is utf-8" ); - my $message_as_string = $MIME->bodyhandle->as_string(); - use Encode; - $message_as_string = Encode::decode_utf8($message_as_string); - main::ok( - $message_as_string =~ /H\x{e5}vard/, -"The message\'s content contains havard\'s name. this will fail if it\'s not utf8 out"); - - }'; -} - -sub iso8859_redef_sendmessage { - no warnings qw/redefine/; - eval ' - sub RT::Action::SendEmail::SendMessage { - my $self = shift; - my $MIME = shift; - - my $scrip = $self->ScripObj->id; - ok(1, $self->ScripObj->ConditionObj->Name . " ".$self->ScripObj->ActionObj->Name); - main::_fired_scrip($self->ScripObj); - $MIME->make_singlepart; - main::ok( ref($MIME) eq \'MIME::Entity\', - "hey, look. it\'s a mime entity" ); - main::ok( ref( $MIME->head ) eq \'MIME::Head\', - "its mime header is a mime header. yay" ); - main::ok( $MIME->head->get(\'Content-Type\') =~ /iso-8859-1/, - "Its content type is iso-8859-1 - " . $MIME->head->get("Content-Type") ); - my $message_as_string = $MIME->bodyhandle->as_string(); - use Encode; - $message_as_string = Encode::decode("iso-8859-1",$message_as_string); - main::ok( - $message_as_string =~ /H\x{e5}vard/, "The message\'s content contains havard\'s name. this will fail if it\'s not utf8 out"); - - }'; -} - -# {{{ test a multipart alternative containing a text-html part with an umlaut - -my $content = `cat @RT_LIB_PATH@/t/data/multipart-alternative-with-umlaut` || die "couldn't find new content"; - -$parser->ParseMIMEEntityFromScalar($content); - - -# be as much like the mail gateway as possible. -¨auts_redef_sendmessage; - -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -ok ($tick->Transactions->First->Content =~ /causes Error/, "We recorded the content right as text-plain"); -is ($tick->Transactions->First->Attachments->Count , 3 , "Has three attachments, presumably a text-plain, a text-html and a multipart alternative"); - -sub umlauts_redef_sendmessage { - no warnings qw/redefine/; - eval 'sub RT::Action::SendEmail::SendMessage { }'; -} - -# }}} - -# {{{ test a text-html message with an umlaut - -my $content = `cat @RT_LIB_PATH@/t/data/text-html-with-umlaut` || die "couldn't find new content"; - -$parser->ParseMIMEEntityFromScalar($content); - - -# be as much like the mail gateway as possible. -&text_html_umlauts_redef_sendmessage; - -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -ok ($tick->Transactions->First->Attachments->First->Content =~ /causes Error/, "We recorded the content as containing 'causes error'"); -ok ($tick->Transactions->First->Attachments->First->ContentType =~ /text\/html/, "We recorded the content as text/html"); -ok ($tick->Transactions->First->Attachments->Count ==1 , "Has one attachment, presumably a text-html and a multipart alternative"); - -sub text_html_umlauts_redef_sendmessage { - no warnings qw/redefine/; - eval 'sub RT::Action::SendEmail::SendMessage { - my $self = shift; - my $MIME = shift; - use Data::Dumper; - return (1) unless ($self->ScripObj->ScripActionObj->Name eq "Notify AdminCcs" ); - ok (is $MIME->parts, 2, "generated correspondence mime entityis composed of three parts"); - is ($MIME->head->mime_type , "multipart/mixed", "The first part is a multipart mixed". $MIME->head->mime_type); - is ($MIME->parts(0)->head->mime_type , "text/plain", "The second part is a plain"); - is ($MIME->parts(1)->head->mime_type , "text/html", "The third part is an html "); - }'; -} - -# }}} - -# {{{ test a text-html message with russian characters - -my $content = `cat @RT_LIB_PATH@/t/data/text-html-in-russian` || die "couldn't find new content"; - -$parser->ParseMIMEEntityFromScalar($content); - - -# be as much like the mail gateway as possible. -&text_html_russian_redef_sendmessage; - -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -ok ($tick->Transactions->First->Attachments->First->ContentType =~ /text\/html/, "We recorded the content right as text-html"); -ok ($tick->Transactions->First->Attachments->Count ==1 , "Has one attachment, presumably a text-html and a multipart alternative"); - -sub text_html_russian_redef_sendmessage { - no warnings qw/redefine/; - eval 'sub RT::Action::SendEmail::SendMessage { - my $self = shift; - my $MIME = shift; - use Data::Dumper; - return (1) unless ($self->ScripObj->ScripActionObj->Name eq "Notify AdminCcs" ); - ok (is $MIME->parts, 2, "generated correspondence mime entityis composed of three parts"); - is ($MIME->head->mime_type , "multipart/mixed", "The first part is a multipart mixed". $MIME->head->mime_type); - is ($MIME->parts(0)->head->mime_type , "text/plain", "The second part is a plain"); - is ($MIME->parts(1)->head->mime_type , "text/html", "The third part is an html "); - my $content_1251; - $content_1251 = $MIME->parts(1)->bodyhandle->as_string(); - ok ($content_1251 =~ qr{Ó÷eáíûé Öeíòp "ÊÀÄÐÛ ÄÅËÎÂÎÃÎ ÌÈÐÀ" ïpèãëaøaeò ía òpeíèíã:}, -"Content matches drugim in codepage 1251" ); - }'; -} - -# }}} - -# {{{ test a message containing a russian subject and NO content type - -unshift (@RT::EmailInputEncodings, 'koi8-r'); -$RT::EmailOutputEncoding = 'koi8-r'; -my $content = `cat @RT_LIB_PATH@/t/data/russian-subject-no-content-type` || die "couldn't find new content"; - -$parser->ParseMIMEEntityFromScalar($content); - - -# be as much like the mail gateway as possible. -&text_plain_russian_redef_sendmessage; -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -ok ($tick->Transactions->First->Attachments->First->ContentType =~ /text\/plain/, "We recorded the content type right"); -ok ($tick->Transactions->First->Attachments->Count ==1 , "Has one attachment, presumably a text-plain"); -is ($tick->Subject, "\x{442}\x{435}\x{441}\x{442} \x{442}\x{435}\x{441}\x{442}", "Recorded the subject right"); -sub text_plain_russian_redef_sendmessage { - no warnings qw/redefine/; - eval 'sub RT::Action::SendEmail::SendMessage { - my $self = shift; - my $MIME = shift; - return (1) unless ($self->ScripObj->ScripActionObj->Name eq "Notify AdminCcs" ); - is ($MIME->head->mime_type , "text/plain", "The only part is text/plain "); - my $subject = $MIME->head->get("subject"); - chomp($subject); - #is( $subject , /^=\?KOI8-R\?B\?W2V4YW1wbGUuY39tICM3XSDUxdPUINTF09Q=\?=/ , "The $subject is encoded correctly"); - }; - '; -} - -shift @RT::EmailInputEncodings; -$RT::EmailOutputEncoding = 'utf-8'; -# }}} - - -# {{{ test a message containing a nested RFC 822 message - -my $content = `cat @RT_LIB_PATH@/t/data/nested-rfc-822` || die "couldn't find new content"; -ok ($content, "Loaded nested-rfc-822 to test"); - -$parser->ParseMIMEEntityFromScalar($content); - - -# be as much like the mail gateway as possible. -&text_plain_nested_redef_sendmessage; -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); -is ($tick->Subject, "[Jonas Liljegren] Re: [Para] Niv\x{e5}er?"); -ok ($tick->Transactions->First->Attachments->First->ContentType =~ /multipart\/mixed/, "We recorded the content type right"); -is ($tick->Transactions->First->Attachments->Count , 5 , "Has one attachment, presumably a text-plain and a message RFC 822 and another plain"); -sub text_plain_nested_redef_sendmessage { - no warnings qw/redefine/; - eval 'sub RT::Action::SendEmail::SendMessage { - my $self = shift; - my $MIME = shift; - return (1) unless ($self->ScripObj->ScripActionObj->Name eq "Notify AdminCcs" ); - is ($MIME->head->mime_type , "multipart/mixed", "It is a mixed multipart"); - my $subject = $MIME->head->get("subject"); - $subject = MIME::Base64::decode_base64( $subject); - chomp($subject); - # TODO, why does this test fail - #ok($subject =~ qr{Niv\x{e5}er}, "The subject matches the word - $subject"); - 1; - }'; -} - -# }}} - - -# {{{ test a multipart alternative containing a uuencoded mesage generated by lotus notes - -my $content = `cat @RT_LIB_PATH@/t/data/notes-uuencoded` || die "couldn't find new content"; - -$parser->ParseMIMEEntityFromScalar($content); - - -# be as much like the mail gateway as possible. -¬es_redef_sendmessage; - -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -ok ($tick->Transactions->First->Content =~ /from Lotus Notes/, "We recorded the content right"); -is ($tick->Transactions->First->Attachments->Count , 3 , "Has three attachments"); - -sub notes_redef_sendmessage { - no warnings qw/redefine/; - eval 'sub RT::Action::SendEmail::SendMessage { }'; -} - -# }}} - -# {{{ test a multipart that crashes the file-based mime-parser works - -my $content = `cat @RT_LIB_PATH@/t/data/crashes-file-based-parser` || die "couldn't find new content"; - -$parser->ParseMIMEEntityFromScalar($content); - - -# be as much like the mail gateway as possible. -&crashes_redef_sendmessage; - -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -ok ($tick->Transactions->First->Content =~ /FYI/, "We recorded the content right"); -is ($tick->Transactions->First->Attachments->Count , 5 , "Has three attachments"); - -sub crashes_redef_sendmessage { - no warnings qw/redefine/; - eval 'sub RT::Action::SendEmail::SendMessage { }'; -} - - - -# }}} - -# {{{ test a multi-line RT-Send-CC header - -my $content = `cat @RT_LIB_PATH@/t/data/rt-send-cc` || die "couldn't find new content"; - -$parser->ParseMIMEEntityFromScalar($content); - - - -my %args = (message => $content, queue => 1, action => 'correspond'); - RT::Interface::Email::Gateway(\%args); -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); - -my $cc = $tick->Transactions->First->Attachments->First->GetHeader('RT-Send-Cc'); -ok ($cc =~ /test1/, "Found test 1"); -ok ($cc =~ /test2/, "Found test 2"); -ok ($cc =~ /test3/, "Found test 3"); -ok ($cc =~ /test4/, "Found test 4"); -ok ($cc =~ /test5/, "Found test 5"); - -# }}} - -# Don't taint the environment -$everyone->PrincipalObj->RevokeRight(Right =>'SuperUser'); -1; diff --git a/rt/lib/t/05cronsupport.pl.in b/rt/lib/t/05cronsupport.pl.in deleted file mode 100644 index a6b3d7451..000000000 --- a/rt/lib/t/05cronsupport.pl.in +++ /dev/null @@ -1,84 +0,0 @@ -#!@PERL@ -w - -use strict; - -### Set up some testing data. Test the testing data because why not? - -# Create a user with rights, a queue, and some tickets. -my $user_obj = RT::User->new($RT::SystemUser); -my ($ret, $msg) = $user_obj->LoadOrCreateByEmail('tara@example.com'); -ok($ret, 'record test user creation'); -$user_obj->SetName('tara'); -$user_obj->PrincipalObj->GrantRight(Right => 'SuperUser'); -my $CurrentUser = RT::CurrentUser->new('tara'); - -# Create our template, which will be used for tests of RT::Action::Record*. - -my $template_content = 'RT-Send-Cc: tla@example.com -RT-Send-Bcc: jesse@example.com - -This is a content string with no content.'; - -my $template_obj = RT::Template->new($CurrentUser); -$template_obj->Create(Queue => '0', - Name => 'recordtest', - Description => 'testing Record actions', - Content => $template_content, - ); - -# Create a queue and some tickets. - -my $queue_obj = RT::Queue->new($CurrentUser); -($ret, $msg) = $queue_obj->Create(Name => 'recordtest', Description => 'queue for Action::Record testing'); -ok($ret, 'record test queue creation'); - -my $ticket1 = RT::Ticket->new($CurrentUser); -my ($id, $tobj, $msg2) = $ticket1->Create(Queue => $queue_obj, - Requestor => ['tara@example.com'], - Subject => 'bork bork bork', - Priority => 22, - ); -ok($id, 'record test ticket creation 1'); -my $ticket2 = RT::Ticket->new($CurrentUser); -($id, $tobj, $msg2) = $ticket2->Create(Queue => $queue_obj, - Requestor => ['root@localhost'], - Subject => 'hurdy gurdy' - ); -ok($id, 'record test ticket creation 2'); - - -### OK. Have data, will travel. - -# First test the search. - -ok(require RT::Search::FromSQL, "Search::FromSQL loaded"); -my $ticketsqlstr = "Requestor.EmailAddress = '" . $CurrentUser->EmailAddress . - "' AND Priority > '20'"; -my $search = RT::Search::FromSQL->new(Argument => $ticketsqlstr, TicketsObj => RT::Tickets->new($CurrentUser), - ); -is(ref($search), 'RT::Search::FromSQL', "search created"); -ok($search->Prepare(), "fromsql search run"); -my $counter = 0; -while(my $t = $search->TicketsObj->Next() ) { - is($t->Id(), $ticket1->Id(), "fromsql search results 1"); - $counter++; -} -is ($counter, 1, "fromsql search results 2"); - -# Right. Now test the actions. - -ok(require RT::Action::RecordComment); -ok(require RT::Action::RecordCorrespondence); - -my ($comment_act, $correspond_act); -ok($comment_act = RT::Action::RecordComment->new(TicketObj => $ticket1, TemplateObj => $template_obj, CurrentUser => $CurrentUser), "RecordComment created"); -ok($correspond_act = RT::Action::RecordCorrespondence->new(TicketObj => $ticket2, TemplateObj => $template_obj, CurrentUser => $CurrentUser), "RecordCorrespondence created"); -ok($comment_act->Prepare(), "Comment prepared"); -ok($correspond_act->Prepare(), "Correspond prepared"); -ok($comment_act->Commit(), "Comment committed"); -ok($correspond_act->Commit(), "Correspondence committed"); - -# Now test for loop suppression. -my ($trans, $desc, $transaction) = $ticket2->Comment(MIMEObj => $template_obj->MIMEObj); -my $bogus_action = RT::Action::RecordComment->new(TicketObj => $ticket1, TemplateObj => $template_obj, TransactionObj => $transaction, CurrentUser => $CurrentUser); -ok(!$bogus_action->Prepare(), "Comment aborted to prevent loop"); diff --git a/rt/lib/t/regression/00placeholder b/rt/lib/t/regression/00placeholder deleted file mode 100644 index 0afc6045c..000000000 --- a/rt/lib/t/regression/00placeholder +++ /dev/null @@ -1 +0,0 @@ -1; diff --git a/rt/sbin/rt-setup-database b/rt/sbin/rt-setup-database deleted file mode 100644 index 58f882f6e..000000000 --- a/rt/sbin/rt-setup-database +++ /dev/null @@ -1,619 +0,0 @@ -#!/usr/bin/perl -w -# BEGIN LICENSE BLOCK -# -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -# -# (Except where explictly superceded by other copyright notices) -# -# 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. -# -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -# -# -# END LICENSE BLOCK - -use strict; -use vars qw($PROMPT $VERSION $Handle $Nobody $SystemUser $item); -use vars - qw(@Groups @Users @ACL @Queues @ScripActions @ScripConditions @Templates @CustomFields @Scrips); - -use lib "/opt/rt3/lib"; - -#This drags in RT's config.pm -# We do it in a begin block because RT::Handle needs to know the type to do its -# inheritance -use RT; -use Carp; -use RT::User; -use RT::CurrentUser; -use RT::Template; -use RT::ScripAction; -use RT::ACE; -use RT::Group; -use RT::User; -use RT::Queue; -use RT::ScripCondition; -use RT::CustomField; -use RT::Scrip; - -RT::LoadConfig(); -use Term::ReadKey; -use Getopt::Long; - -my %args; - -GetOptions( - \%args, - 'prompt-for-dba-password', 'force', 'debug', - 'action=s', 'dba=s', 'dba-password=s', 'datafile=s', - 'datadir=s' -); - -$| = 1; #unbuffer that output. - -require RT::Handle; -my $Handle = RT::Handle->new($RT::DatabaseType); -$Handle->BuildDSN; -my $dbh; - -if ( $args{'prompt-for-dba-password'} ) { - $args{'dba-password'} = get_dba_password(); - chomp( $args{'dba-password'} ); -} - -unless ( $args{'action'} ) { - help(); - die; -} -if ( $args{'action'} eq 'init' ) { - $dbh = DBI->connect( get_system_dsn(), $args{'dba'}, $args{'dba-password'} ) - || die "Failed to connect to " . get_system_dsn() . " as $args{'dba'}: $DBI::errstr"; - print "Now creating a database for RT.\n"; - if ($RT::DatabaseType ne 'Oracle' || - $args{'dba'} ne $RT::DatabaseUser) { - create_db(); - } else { - print "...skipped as ".$args{'dba'} ." is not " . $RT::DatabaseUser . " or we're working with Oracle.\n"; - } - - $dbh->disconnect; - $dbh = DBI->connect( $Handle->DSN, $args{'dba'}, $args{'dba-password'} ) - || die $DBI::errstr; - - print "Now populating database schema.\n"; - insert_schema(); - print "Now inserting database ACLs\n"; - insert_acl() unless ($RT::DatabaseType eq 'Oracle'); - print "Now inserting RT core system objects\n"; - insert_initial_data(); - print "Now inserting RT data\n"; - insert_data( $RT::EtcPath . "/initialdata" ); -} -elsif ( $args{'action'} eq 'drop' ) { - unless ( $dbh = - DBI->connect( get_system_dsn(), $args{'dba'}, $args{'dba-password'} ) ) - { - warn $DBI::errstr; - warn "Database doesn't appear to exist. Aborting database drop."; - exit(0); - } - drop_db(); -} -elsif ( $args{'action'} eq 'insert' ) { - insert_data( $args{'datafile'} ); -} -elsif ($args{'action'} eq 'acl') { - $dbh = DBI->connect( $Handle->DSN, $args{'dba'}, $args{'dba-password'} ) - || die "Failed to connect to " . get_system_dsn() . " as $args{'dba'}: $DBI::errstr"; - insert_acl($args{'datadir'}); -} -elsif ($args{'action'} eq 'schema') { - $dbh = DBI->connect( $Handle->DSN, $args{'dba'}, $args{'dba-password'} ) - || die "Failed to connect to " . get_system_dsn() . " as $args{'dba'}: $DBI::errstr"; - insert_schema($args{'datadir'}); -} - -else { - print STDERR '$0 called with an invalid --action parameter'; - exit(-1); -} - -# {{{ sub insert_schema -sub insert_schema { - my $base_path = (shift || $RT::EtcPath); - my (@schema); - print "Creating database schema.\n"; - - if ( -f $base_path . "/schema." . $RT::DatabaseType ) { - no warnings 'unopened'; - - open( SCHEMA, "<" . $base_path . "/schema." . $RT::DatabaseType ); - open( SCHEMA_LOCAL, "<" . $RT::LocalEtcPath . "/schema." . $RT::DatabaseType ); - - my $statement = ""; - foreach my $line (<SCHEMA>, ($_ = ';;'), <SCHEMA_LOCAL>) { - $line =~ s/\#.*//g; - $line =~ s/--.*//g; - $statement .= $line; - if ( $line =~ /;(\s*)$/ ) { - $statement =~ s/;(\s*)$//g; - push @schema, $statement; - $statement = ""; - } - } - - local $SIG{__WARN__} = sub {}; - my $is_local = 0; # local/etc/schema needs to be nonfatal. - foreach my $statement (@schema) { - if ($statement =~ /^\s*;$/) { $is_local = 1; next; } - print STDERR "SQL: $statement\n" if defined $args{'debug'}; - my $sth = $dbh->prepare($statement) or die $dbh->errstr; - unless ( $sth->execute or $is_local ) { - die "Problem with statement:\n $statement\n" . $sth->errstr; - } - } - - } - else { - die "Couldn't find schema file for " . $RT::DatabaseType . "\n"; - } - print "schema sucessfully inserted\n"; - -} - -# }}} - -# {{{ sub drop_db -sub drop_db { - return if ( $RT::DatabaseType eq 'SQLite' ); - if ( $RT::DatabaseType eq 'Oracle' ) { - print <<END; - -To delete the tables and sequences of the RT Oracle database by running - \@etc/drop.Oracle -through SQLPlus. - -END - return; - } - unless ( $args{'force'} ) { - print <<END; - -About to drop $RT::DatabaseType database $RT::DatabaseName on $RT::DatabaseHost. -WARNING: This will erase all data in $RT::DatabaseName. - -END - exit unless _yesno(); - - } - - print "Dropping $RT::DatabaseType database $RT::DatabaseName.\n"; - - $dbh->do("Drop DATABASE $RT::DatabaseName") or warn $DBI::errstr; -} - -# }}} - -# {{{ sub create_db -sub create_db { - print "Creating $RT::DatabaseType database $RT::DatabaseName.\n"; - if ( $RT::DatabaseType eq 'SQLite' ) { - return; - } - elsif ( $RT::DatabaseType eq 'Pg' ) { - $dbh->do("CREATE DATABASE $RT::DatabaseName WITH ENCODING='UNICODE'"); - if ($DBI::errstr) { - $dbh->do("CREATE DATABASE $RT::DatabaseName") || die $DBI::errstr; - } - } - elsif ($RT::DatabaseType eq 'Oracle') { - insert_acl(); - } - elsif ( $RT::DatabaseType eq 'Informix' ) { - $ENV{DB_LOCALE} = 'en_us.utf8'; - $dbh->do("CREATE DATABASE $RT::DatabaseName WITH BUFFERED LOG"); - } - else { - $dbh->do("CREATE DATABASE $RT::DatabaseName") or die $DBI::errstr; - } -} - -# }}} - -sub get_dba_password { - print -"In order to create a new database and grant RT access to that database,\n"; - print "this script needs to connect to your " - . $RT::DatabaseType - . " instance on " - . $RT::DatabaseHost . " as " - . $args{'dba'} . ".\n"; - print -"Please specify that user's database password below. If the user has no database\n"; - print "password, just press return.\n\n"; - print "Password: "; - ReadMode('noecho'); - my $password = ReadLine(0); - ReadMode('normal'); - return ($password); -} - -# {{{ sub _yesno -sub _yesno { - print "Proceed [y/N]:"; - my $x = scalar(<STDIN>); - $x =~ /^y/i; -} - -# }}} - -# {{{ insert_acls -sub insert_acl { - - my $base_path = (shift || $RT::EtcPath); - - if ( $RT::DatabaseType =~ /^oracle$/i ) { - do $base_path . "/acl.Oracle" - || die "Couldn't find ACLS for Oracle\n" . $@; - } - elsif ( $RT::DatabaseType =~ /^pg$/i ) { - do $base_path . "/acl.Pg" || die "Couldn't find ACLS for Pg\n" . $@; - } - elsif ( $RT::DatabaseType =~ /^mysql$/i ) { - do $base_path . "/acl.mysql" - || die "Couldn't find ACLS for mysql in " . $RT::EtcPath . "\n" . $@; - } - elsif ( $RT::DatabaseType =~ /^informix$/i ) { - do $base_path . "/acl.Informix" - || die "Couldn't find ACLS for Informix in " . $RT::EtcPath . "\n" . $@; - } - elsif ( $RT::DatabaseType =~ /^SQLite$/i ) { - return; - } - else { - die "Unknown RT database type"; - } - - my @acl = acl($dbh); - foreach my $statement (@acl) { - print STDERR $statement if $args{'debug'}; - my $sth = $dbh->prepare($statement) or die $dbh->errstr; - unless ( $sth->execute ) { - die "Problem with statement:\n $statement\n" . $sth->errstr; - } - } -} - -# }}} - -=head2 get_system_dsn - -Returns a dsn suitable for database creates and drops -and user creates and drops - -=cut - -sub get_system_dsn { - - my $dsn = $Handle->DSN; - - #with mysql, you want to connect sans database to funge things - if ( $RT::DatabaseType eq 'mysql' ) { - $dsn =~ s/dbname=$RT::DatabaseName//; - - # with postgres, you want to connect to database1 - } - elsif ( $RT::DatabaseType eq 'Pg' ) { - $dsn =~ s/dbname=$RT::DatabaseName/dbname=template1/; - } - elsif ( $RT::DatabaseType eq 'Informix' ) { - # with Informix, you want to connect sans database: - $dsn =~ s/Informix:$RT::DatabaseName/Informix:/; - } - return $dsn; -} - -sub insert_initial_data { - - RT::InitLogging(); - - #connect to the db, for actual RT work - require RT::Handle; - $RT::Handle = RT::Handle->new(); - $RT::Handle->Connect(); - - #Put together a current user object so we can create a User object - my $CurrentUser = new RT::CurrentUser(); - - print "Checking for existing system user ($CurrentUser)..."; - my $test_user = RT::User->new($CurrentUser); - $test_user->Load('RT_System'); - if ( $test_user->id ) { - print "found!\n\nYou appear to have a functional RT database.\n" - . "Exiting, so as not to clobber your existing data.\n"; - exit(-1); - - } - else { - print "not found. This appears to be a new installation.\n"; - } - - print "Creating system user..."; - my $RT_System = new RT::User($CurrentUser); - - my ( $val, $msg ) = $RT_System->_BootstrapCreate( - Name => 'RT_System', - RealName => 'The RT System itself', - Comments => -'Do not delete or modify this user. It is integral to RT\'s internal database structures', - Creator => '1' ); - - unless ($val) { - print "$msg\n"; - exit(1); - } - print "done.\n"; - $RT::Handle->Disconnect(); - -} - -# load some sort of data into the database - -sub insert_data { - my $datafile = shift; - - #Connect to the database and get RT::SystemUser and RT::Nobody loaded - RT::Init; - - my $CurrentUser = RT::CurrentUser->new(); - $CurrentUser->LoadByName('RT_System'); - - if ( $datafile eq $RT::EtcPath . "/initialdata" ) { - - print "Creating Superuser ACL..."; - - my $superuser_ace = RT::ACE->new($CurrentUser); - $superuser_ace->_BootstrapCreate( - PrincipalId => ACLEquivGroupId( $CurrentUser->Id ), - PrincipalType => 'Group', - RightName => 'SuperUser', - ObjectType => 'RT::System', - ObjectId => '1' ); - - } - - # Slurp in stuff to insert from the datafile. Possible things to go in here:- - # @groups, @users, @acl, @queues, @ScripActions, @ScripConditions, @templates - - require $datafile - || die "Couldn't find initial data for import\n" . $@; - - if (@Groups) { - print "Creating groups..."; - foreach $item (@Groups) { - my $new_entry = RT::Group->new($CurrentUser); - my ( $return, $msg ) = $new_entry->_Create(%$item); - print "(Error: $msg)" unless ($return); - print $return. "."; - } - print "done.\n"; - } - if (@Users) { - print "Creating users..."; - foreach $item (@Users) { - my $new_entry = new RT::User($CurrentUser); - my ( $return, $msg ) = $new_entry->Create(%$item); - print "(Error: $msg)" unless ($return); - print $return. "."; - } - print "done.\n"; - } - if (@Queues) { - print "Creating queues..."; - for $item (@Queues) { - my $new_entry = new RT::Queue($CurrentUser); - my ( $return, $msg ) = $new_entry->Create(%$item); - print "(Error: $msg)" unless ($return); - print $return. "."; - } - print "done.\n"; - } - if (@ACL) { - print "Creating ACL..."; - for my $item (@ACL) { - - my ($princ, $object); - - # Global rights or Queue rights? - if ($item->{'Queue'}) { - $object = RT::Queue->new($CurrentUser); - $object->Load( $item->{'Queue'} ); - } else { - $object = $RT::System; - } - - # Group rights or user rights? - if ($item->{'GroupDomain'}) { - $princ = RT::Group->new($CurrentUser); - if ($item->{'GroupDomain'} eq 'UserDefined') { - $princ->LoadUserDefinedGroup( $item->{'GroupId'} ); - } elsif ($item->{'GroupDomain'} eq 'SystemInternal') { - $princ->LoadSystemInternalGroup( $item->{'GroupType'} ); - } elsif ($item->{'GroupDomain'} eq 'RT::Queue-Role' && - $item->{'Queue'}) { - $princ->LoadQueueRoleGroup( Type => $item->{'GroupType'}, - Queue => $object->id); - } else { - $princ->Load( $item->{'GroupId'} ); - } - } else { - $princ = RT::User->new($CurrentUser); - $princ->Load( $item->{'UserId'} ); - } - - # Grant it - my ( $return, $msg ) = $princ->PrincipalObj->GrantRight( - Right => $item->{'Right'}, - Object => $object ); - - if ($return) { - print $return. "."; - } - else { - print $msg . "."; - - } - - } - print "done.\n"; - } - if (@CustomFields) { - print "Creating custom fields..."; - for $item (@CustomFields) { - my $new_entry = new RT::CustomField($CurrentUser); - my $values = $item->{'Values'}; - delete $item->{'Values'}; - my $q = $item->{'Queue'}; - my $q_obj = RT::Queue->new($CurrentUser); - $q_obj->Load($q); - if ( $q_obj->Id ) { - $item->{'Queue'} = $q_obj->Id; - } - elsif ( $q == 0 ) { - $item->{'Queue'} = 0; - } - else { - print "(Error: Could not find queue " . $q . ")\n" - unless ( $q_obj->Id ); - next; - } - my ( $return, $msg ) = $new_entry->Create(%$item); - - foreach my $value ( @{$values} ) { - my ( $eval, $emsg ) = $new_entry->AddValue(%$value); - print "(Error: $emsg)\n" unless ($eval); - } - - print "(Error: $msg)\n" unless ($return); - print $return. "."; - } - - print "done.\n"; - } - - if (@ScripActions) { - print "Creating ScripActions..."; - - for $item (@ScripActions) { - my $new_entry = RT::ScripAction->new($CurrentUser); - my $return = $new_entry->Create(%$item); - print $return. "."; - } - - print "done.\n"; - } - - if (@ScripConditions) { - print "Creating ScripConditions..."; - - for $item (@ScripConditions) { - my $new_entry = RT::ScripCondition->new($CurrentUser); - my $return = $new_entry->Create(%$item); - print $return. "."; - } - - print "done.\n"; - } - - if (@Templates) { - print "Creating templates..."; - - for $item (@Templates) { - my $new_entry = new RT::Template($CurrentUser); - my $return = $new_entry->Create(%$item); - print $return. "."; - } - print "done.\n"; - } - if (@Scrips) { - print "Creating scrips..."; - - for $item (@Scrips) { - my $new_entry = new RT::Scrip($CurrentUser); - my ( $return, $msg ) = $new_entry->Create(%$item); - if ($return) { - print $return. "."; - } - else { - print "(Error: $msg)\n"; - } - } - print "done.\n"; - } - $RT::Handle->Disconnect(); - -} - -=head2 ACLEquivGroupId - -Given a userid, return that user's acl equivalence group - -=cut - -sub ACLEquivGroupId { - my $username = shift; - my $user = RT::User->new($RT::SystemUser); - $user->Load($username); - my $equiv_group = RT::Group->new($RT::SystemUser); - $equiv_group->LoadACLEquivalenceGroup($user); - return ( $equiv_group->Id ); -} - -sub help { - - print <<EOF; - -$0: Set up RT's database - ---action init Initialize the database - drop Drop the database. - This will ERASE ALL YOUR DATA - insert Insert data into RT's database. - By default, will use RT's installation data. - To use a local or supplementary datafile, specify it - using the '--datafile' option below. - - acl Initialize only the database ACLs - To use a local or supplementary datafile, specify it - using the '--datadir' option below. - - schema Initialize only the database schema - To use a local or supplementary datafile, specify it - using the '--datadir' option below. - ---datafile /path/to/datafile ---datadir /path/to/ Used to specify a path to find the local - database schema and acls to be installed. - - ---dba dba's username ---dba-password dba's password ---prompt-for-dba-password Ask for the database administrator's password interactively - - -EOF - -} - -1; diff --git a/rt/sbin/rt-setup-database.in b/rt/sbin/rt-setup-database.in index c432cc97b..49feba845 100644 --- a/rt/sbin/rt-setup-database.in +++ b/rt/sbin/rt-setup-database.in @@ -130,14 +130,7 @@ if ( $args{'action'} eq 'init' ) { unless ($RT::DatabaseType eq 'SQLite') { $dbh->disconnect; - - if ($RT::DatabaseType eq "Oracle") { - $RT::DatabasePassword = $RT::DatabasePassword; #Warning avidance - $dbh = DBI->connect( $Handle->DSN, ${RT::DatabaseUser}, ${RT::DatabasePassword} ) || die $DBI::errstr; - } else { - $dbh = DBI->connect( $Handle->DSN, $args{'dba'}, $args{'dba-password'} ) || die $DBI::errstr; - } } print "Now populating database schema.\n"; insert_schema(); @@ -158,6 +151,9 @@ elsif ( $args{'action'} eq 'drop' ) { } drop_db(); } +elsif ( $args{'action'} eq 'insert_initial' ) { + insert_initial_data(); +} elsif ( $args{'action'} eq 'insert' ) { insert_data( $args{'datafile'} || ($args{'datadir'}."/content")); } @@ -650,6 +646,8 @@ $0: Set up RT's database --action init Initialize the database drop Drop the database. This will ERASE ALL YOUR DATA + insert_initial + Insert RT's core system objects insert Insert data into RT's database. By default, will use RT's installation data. To use a local or supplementary datafile, specify it diff --git a/rt/sbin/rt-test-dependencies b/rt/sbin/rt-test-dependencies deleted file mode 100644 index c1591b189..000000000 --- a/rt/sbin/rt-test-dependencies +++ /dev/null @@ -1,278 +0,0 @@ -#!/usr/bin/perl -# BEGIN LICENSE BLOCK -# -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -# -# (Except where explictly superceded by other copyright notices) -# -# 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. -# -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -# -# -# END LICENSE BLOCK - -# -# This is just a basic script that checks to make sure that all -# the modules needed by RT before you can install it. -# - -use strict; -no warnings qw(numeric redefine); -use Getopt::Long; -use CPAN; -my %args; -my %deps; -GetOptions(\%args,'install', 'with-MYSQL', 'with-POSTGRESQL|with-pg|with-pgsql', 'with-SQLITE', 'with-ORACLE', 'with-FASTCGI', 'with-SPEEDYCGI', 'with-MODPERL1', 'with-MODPERL2' ,'with-DEV'); - -if (!keys %args) { - help(); - exit(0); -} -if ($args{'with-MODPERL2'}) { - warn_modperl2(); -} - -$args{'with-MASON'} = 1; -$args{'with-CORE'} = 1; -$args{'with-DEV'} =1; -$args{'with-CLI'} =1; -$args{'with-MAILGATE'} =1; -if ($] < 5.007) { -$args{'with-I18N-COMPAT'} = 1; -} - -sub warn_modperl2 { - print <<'.'; - NOTE: mod_perl 2.0 isn't quite ready for prime_time just yet; - Best Practical Solutions strongly recommends that sites use - Apache 1.3 or FastCGI. If you MUST use mod_perl 2.0 (or 1.99), - please read the mailing list archives before asking for help. -. - sleep 5; -} - - -sub help { - - print <<'.'; - -By default, testdeps determine whether you have -installed all the perl modules RT needs to run. - - --install Install missing modules - -The following switches will tell the tool to check for specific dependencies - - --with-mysql Database interface for MySQL - --with-postgresql Database interface for PostgreSQL - --with-sqlite Database interface and driver for SQLite (unsupported) - --with-oracle Database interface for oracle (unsupported) - - --with-fastcgi Libraries needed to support the fastcgi handler - --with-speedycgi Libraries needed to support the speedycgi handler - --with-modperl1 Libraries needed to support the modperl 1 handler - --with-modperl2 Libraries needed to support the modperl 2 handler - - --with-dev Tools needed for RT development -. -} - - -sub _ { - map { /(\S+)\s*(\S*)/; $1 => ($2 ? $2 :'') } split ( /\n/, $_[0] ); -} - -$deps{'CORE'} = [ _( << '.') ]; -Digest::MD5 2.27 -DBI 1.37 -Test::Inline -Class::ReturnValue 0.40 -DBIx::SearchBuilder 0.97 -Text::Template -File::Spec 0.8 -HTML::Entities -Net::Domain -Log::Dispatch 2.0 -Locale::Maketext 1.06 -Locale::Maketext::Lexicon 0.32 -Locale::Maketext::Fuzzy -MIME::Entity 5.108 -Mail::Mailer 1.57 -Net::SMTP -Text::Wrapper -Time::ParseDate -File::Temp -Term::ReadKey -Text::Autoformat -Text::Quoted 1.3 -Scalar::Util -. - -$deps{'MASON'} = [ _( << '.') ]; -Params::Validate 0.02 -Cache::Cache -Exception::Class -HTML::Mason 1.16 -MLDBM -Errno -FreezeThaw -Digest::MD5 2.27 -CGI::Cookie 1.20 -Storable 2.08 -Apache::Session 1.53 -. - -$deps{'MAILGATE'} = [ _( << '.') ]; -HTML::TreeBuilder -HTML::FormatText -Getopt::Long -LWP::UserAgent -. - -$deps{'CLI'} = [ _( << '.') ]; -Getopt::Long 2.24 -. - -$deps{'DEV'} = [ _( << '.') ]; -Regexp::Common -Time::HiRes -Test::Inline -WWW::Mechanize -. - -$deps{'FASTCGI'} = [ _( << '.') ]; -CGI 2.92 -FCGI -CGI::Fast -. - -$deps{'SPEEDYCGI'} = [ _( << '.') ]; -CGI 2.92 -CGI::SpeedyCGI -. - - -$deps{'MODPERL1'} = [ _( << '.') ]; -CGI 2.92 -Apache::Request -Apache::DBI 0.92 -. - -$deps{'MODPERL2'} = [ _( << '.') ]; -CGI 2.92 -Apache::DBI -. - -$deps{'I18N-COMPAT'} = [ _( << '.') ]; -Text::Iconv -Encode::compat 0.04 -. - -$deps{'MYSQL'} = [ _( << '.') ]; -DBD::mysql 2.1018 -. -$deps{'ORACLE'} = [ _( << '.') ]; -DBD::Oracle -. -$deps{'POSTGRESQL'} = [ _( << '.') ]; -DBD::Pg -. - -print "perl:\n"; -print "\t5.8.0"; -eval {require 5.008}; -if ($@) { -print "...missing.\n"; - eval {require 5.006001}; - if ($@) { - print " RT is known to be non-functional on versions of perl older than 5.6.1. Please upgrade to 5.8.0 or newer"; - die; - } else { - print " RT is not supported on perl 5.6.1\n"; - } -} else { - print "...found\n"; - -} - - -foreach my $type (keys %args) { -next unless ($type =~ /^with-(.*?)$/); -my $type = $1; -print "$type dependencies:\n"; - my @deps = (@{$deps{$type}}); - while (@deps) { - my $module = shift @deps; - my $version = shift @deps; -my $ret; - $ret =test_dep($module, $version); - -if ($args{'install'} && !$ret) { - resolve_dep($module); -} -} -} -sub test_dep { - my $module = shift; - my $version = shift; - - print "\t$module $version"; - eval "use $module $version" ; - if ($@) { - my $error = $@; - $error =~ s/\n(.*)$//s; - print "...MISSING\n"; - print "\t\t$error\n" if $error =~ /this is only/; - - return undef; - } else { - print "...found\n"; -return 1; - } -} - -sub resolve_dep { - my $module = shift; - use CPAN; - CPAN::Shell->install($module); - -} - - -sub print_help { - print << "EOF"; - -$0 FLAG DBTYPE - - -$0 is a tool for RT that will tell you if you've got all -the modules RT depends on properly installed. - -Flags: (only one flag is valid for a given run) - --quiet will check to see if we've got everything we need - and will exit with a return code of (1) if we don't. - --warn will tell you what isn't properly installed - --fix will use CPANPLUS.pm or CPAN.pm to magically make everything better - -DBTYPE is one of: - oracle, pg, mysql - -EOF - - exit(0); -} |