[Rt-commit] rt branch, master, updated. rt-3.9.7-1162-g1effcc2

Alex Vandiver alexmv at bestpractical.com
Mon Jan 3 14:04:29 EST 2011


The branch, master has been updated
       via  1effcc25a1d6e02752c04e223162724cf5b01324 (commit)
       via  d1da7658cd79123d567f875260f3fd310877730b (commit)
       via  0a1338514b8fea30a9bb492a01fc58c5d305a377 (commit)
       via  fa0111eb3c3c3892e12b46963033e8d18ea12067 (commit)
       via  4e92d3f7760ec3cfbc5f6da8d1dbe4b1267de0a7 (commit)
       via  2a35c54f23f6c5c9280811471fddf1a6c62bd3ee (commit)
       via  de368655aec9eb2f16f192e1afba57e6be388134 (commit)
       via  2617f30bcbe23bf3173906e13fa092e8248b862a (commit)
       via  35c9bc2afbe9863ba4cffdd4829eff6aa849ffcd (commit)
       via  7fae35f16881c000390c589f84be569d5c55ceda (commit)
       via  f7892ec19eefc48a071465e480be8dcd4444637c (commit)
       via  514c9e1b3d058a30ce3f09319bb31a55b7392f47 (commit)
       via  bd4d927529345f7a666ff4cc0125f8c2005dc2fe (commit)
       via  0b8ff30428fd099bea992896f1af6e13f4e6b57c (commit)
       via  b3350f9a8cfa0ad44b6e6a07d06e7a3a71f6c8a9 (commit)
       via  fe8879aa2b81a85927ba66495bdbe0972b5fa60d (commit)
       via  be3cee4a76d771966371d59535fd0eece3a4dfee (commit)
       via  ba7b2d4b4420d576d3a3ba1ab39fe6b960be3b40 (commit)
       via  e697e268b084affe59c99f6e3f60d9de091bcd93 (commit)
       via  816d9e57cdd473d80b344a877d2a4195156624ff (commit)
       via  51132971e7ed3f9aac1051471e667d2c46b7859d (commit)
       via  e679291b1d40c3d35651447c1fa75588d46d062d (commit)
       via  ce5ca3131c0051c51795f3343e172646ccb047a5 (commit)
       via  d45f84cb6de9d802b0b57cbbd7cb368be2d94425 (commit)
       via  c704e523f9a1ade4d6161515e821093f20d54a20 (commit)
       via  9ab41d269a6c866310cfb6b85912027a915d8374 (commit)
       via  ee67ffd36f0eae01cb213c82666d2920c2a26e0d (commit)
       via  e1a110ee6514c21641a5abf45b38c67f8532364b (commit)
       via  81ccb8fd1be6e81ff3d681ffcf3d9ec4343261a8 (commit)
       via  1e785ed14af3ee70a72807c66fd426a77d71e5c4 (commit)
       via  6186b46f5f7f7802a0e7f7df084d95b6080b6d86 (commit)
       via  91ab4a53aaeaeee7623638f86d45fb895ddf55f9 (commit)
       via  bf2bcb0ffbbc8a447ba17afc0ae9f8a868ecee00 (commit)
       via  bfd183b9faff4b218f9d23e670d1f6d29a69b62b (commit)
       via  78d40104bc78e7895f837df5dd58b9ecdc54c619 (commit)
       via  24d4e4e4caada28e8af6ef875cd626b3c00bf1c2 (commit)
       via  beb2eb4815a678d4b0123956ed11aa7f57c6266f (commit)
       via  2ccdcb483374c3d0d99850f6cc2b162ac9ed5807 (commit)
       via  8e62e1227f7c84c7be4e1500b57c9ddc2355e450 (commit)
       via  c74f25ac404a26917be85e7a2845ace5ce4dcc0e (commit)
       via  b23fa125a12bfbf7370ed08b3982d2f228ab33f4 (commit)
       via  39da36ab206bbce94b77d87b1bad4f4238f6ebd3 (commit)
       via  cc1486bd4711c160e484a3569b748ac2533c3f10 (commit)
       via  24a1cc4a6ccc40bbd9d0348025c90a633abbd718 (commit)
       via  8804d03810a201bde96b24fbdd91d90e6b972bbd (commit)
       via  f0256a98c82d25edaf54e8c2b6441e1c2019ec49 (commit)
       via  dcfa3ecdaff584a5723cb6939716f65df848a109 (commit)
       via  4bb5118ad93b1c7606c39f5c592fc64a5ddde482 (commit)
       via  8428a61288804b5bb93fa9d355a48084f6878186 (commit)
       via  c91d36535baf1e3c987a36a2653c9d1da251b37d (commit)
       via  68b5cfc1750298da845be01333fa498aeac91e93 (commit)
       via  77209c3fde59313d6b089ceeb860fdf411fba8bb (commit)
       via  37b0b19371ec785cd772b21b1bc72e9c4d79c8df (commit)
       via  6134b351eb410c5a36ca7a55c20cd29afbfe3a33 (commit)
       via  a64d936853d87ae98a3d0d207d94e01fb5b1ab71 (commit)
       via  7ad504c443ad91261a64d9fba60d0551dce45098 (commit)
       via  d033518bb938a318782d96d1931dbcd4efb00abe (commit)
       via  f6247f0e2a38008c3885dc77ebb1bf8eeabce667 (commit)
       via  c9e6ef1e279f9d5af7336c61a0c89c9b24e3c736 (commit)
       via  6bb055aaaa380dff1dae8cce7e3acf52fb79a09d (commit)
       via  f430e36a7ff5fa983ff7d85b9e7a9e84a4f14f34 (commit)
       via  b6ee9bbeec49709ef1ffb91140f29fc34c016530 (commit)
       via  8178ac6ccdd707045fb25b7a9b07fec4f5508b41 (commit)
       via  c1525149c003a949cc50b36f639021d91bad7007 (commit)
       via  2142df6a23f70399cd5014cc5ed1aa80f3c310ef (commit)
       via  46976ee7551191c9888e7e3d99860c11156d680c (commit)
       via  7628a51c8977a89fda5860a59bff74fd08f94e80 (commit)
       via  58f9fc1a1357d592ea07c59a38b6d40ff0f7326b (commit)
       via  3a5f91569b88172942b27bff4cdd93006644f6cf (commit)
       via  4485a37d9703379007b70573eb1661a3db89bde4 (commit)
       via  5b572ed8c64f9ce240c548ef81776193d9451c41 (commit)
       via  ac4105da4e97b07f3b981306a5f440593d261a27 (commit)
       via  ecaf1a8580703c3e47235a9bd168a83af034e2f9 (commit)
       via  b03f18097b8d98e84841463053f7cfb3a08bca62 (commit)
       via  379827282fa8ff8a485704cedeb9c66222a11a89 (commit)
       via  a8130dd1a8a62926962a97d4a71826baff6bd61b (commit)
       via  0ec2fc6bfc62e62a96e59926102e15980b81d31c (commit)
       via  e9e17611cb7d024eaf6a362783899de48583cd4a (commit)
       via  e153c4c79001cfa00ae4d1287acb8384731a34ff (commit)
       via  a2693b0112098cbf1d6f53ef67e3c45bbc16f8a6 (commit)
       via  1c00409b77c049217820c6827864aa2a9ab9b06e (commit)
       via  b94d8b727caf31c6b31c35652a4465086560e209 (commit)
       via  ffce595ffb2bdfe603c71887e9bba2486cf84543 (commit)
       via  3ad9ff384197ab2b40190e32f467cd907d0c2dae (commit)
       via  3cf134e8ed7177dfdf8648ff9fa6a5204243f114 (commit)
       via  276138214cd3700560bf628a501338cc47439176 (commit)
       via  bc56f5bf5534db3a90b6c3e9bbb021d979500149 (commit)
       via  78b2af5e3c3bfa25c2b619157680c6b0d458c7d1 (commit)
       via  5559bea49258d6e08006bf7f4ac0b08feca0502b (commit)
       via  f23e5027a92f86ec21c98e3cfe78cbba0e18e569 (commit)
       via  faa35e65bc7497d2bdea76e927f6ae3d0d8936dc (commit)
       via  27b08989fd0c14d1aa30087a88487fa2668522d9 (commit)
       via  e1f84c11b62028e64184c6ea2964c12ef8ed8a97 (commit)
       via  9f3478d9fe8010a968c96ee66e83f0e1ec31c909 (commit)
       via  a5e4e3867164e0d7e38a4bbc824987a4ce981de0 (commit)
       via  78cde82a53774bfdec5c84bbeba0895e915ec269 (commit)
       via  a5b5899b4e3ea580821f0a8916ead6033a7fc141 (commit)
       via  aa26405f0de61ac2160114fe2eea1972c9e7322d (commit)
       via  1ca17a66423132b7cba61b741b7be89fb32d8e8f (commit)
       via  800fbe0813e1b583d73b6170228baf3cd4632aa5 (commit)
       via  41bcc7baf5319981676f323dc563a463c5030e6e (commit)
       via  375fd64719ef8c0f4e9a72b94ba44c5aac7b745c (commit)
       via  c04d9e903b0a8bb8b7f8f15a19de00ad2ca79cb4 (commit)
       via  b651c7177fc841e1a3dd7ee6f4c06924ac8561be (commit)
       via  b4044e8b15e8ea8830bbf7240c4b005c836e82b7 (commit)
       via  e3fd940616ee33348182b3c05d7961a1bf83517a (commit)
       via  e396fb46ea399249a3f6e848ca792d8dfd2c8761 (commit)
       via  6ed672847d837abaf0e04f83af725463c631c21b (commit)
       via  e6b03ead8284f491aa01d7976f46220e0411708f (commit)
      from  e8401860c0af8f57d92ab9102689c174f19e6399 (commit)

Summary of changes:
 README                                            |   26 +-
 UPGRADING                                         |  300 +--
 UPGRADING.rtfm                                    |   97 -
 configure.ac                                      |    1 +
 devel/factory                                     |  136 +-
 docs/UPGRADING-2.x                                |    3 +
 docs/UPGRADING-3.0                                |   18 +
 docs/UPGRADING-3.2                                |    9 +
 docs/UPGRADING-3.4                                |   13 +
 docs/UPGRADING-3.6                                |   43 +
 docs/UPGRADING-3.8                                |  159 +
 docs/UPGRADING-4.0                                |   80 +
 etc/RT_Config.pm.in                               |   34 +-
 etc/rtfm/upgrade/2.1.0/acl.Oracle                 |    4 -
 etc/rtfm/upgrade/2.1.0/acl.Pg                     |   24 -
 etc/rtfm/upgrade/2.1.0/acl.mysql                  |    4 -
 etc/rtfm/upgrade/2.1.0/content                    |    2 -
 etc/rtfm/upgrade/2.1.0/schema.Oracle              |   22 -
 etc/rtfm/upgrade/2.1.0/schema.Pg                  |   20 -
 etc/rtfm/upgrade/2.1.0/schema.mysql               |   20 -
 etc/rtfm/upgrade/2.1.30/acl.Oracle                |    4 -
 etc/rtfm/upgrade/2.1.30/acl.Pg                    |    4 -
 etc/rtfm/upgrade/2.1.30/acl.mysql                 |    4 -
 etc/rtfm/upgrade/2.1.30/content                   |    2 -
 etc/rtfm/upgrade/2.1.30/schema.Oracle             |    7 -
 etc/rtfm/upgrade/2.2.0RC2/acl.Oracle              |    4 -
 etc/rtfm/upgrade/2.2.0RC2/acl.Pg                  |    4 -
 etc/rtfm/upgrade/2.2.0RC2/acl.mysql               |    4 -
 etc/rtfm/upgrade/2.2.0RC2/content                 |    2 -
 etc/rtfm/upgrade/2.2.0RC2/schema.Oracle           |    1 -
 etc/rtfm/upgrade/2.2.0RC2/schema.Pg               |    4 -
 etc/rtfm/upgrade/2.2.0RC2/schema.mysql            |    1 -
 etc/rtfm/upgrade/migrate-2.0-to-2.1               |  292 --
 etc/rtfm/upgrade/upgrade-mysql-schema.pl          |  248 --
 etc/upgrade/3.9.8/content                         |   22 +
 etc/upgrade/upgrade-articles.in                   |  258 ++
 etc/upgrade/upgrade-mysql-schema.pl               |   25 +-
 lib/RT.pm                                         |   56 +
 lib/RT/ACE.pm                                     |  622 +++-
 lib/RT/ACE_Overlay.pm                             |  581 ----
 lib/RT/ACL.pm                                     |  268 ++-
 lib/RT/ACL_Overlay.pm                             |  313 --
 lib/RT/Action.pm                                  |    1 +
 lib/RT/Approval.pm                                |    1 +
 lib/RT/Article.pm                                 |  634 ++++-
 lib/RT/Article_Overlay.pm                         |  662 ----
 lib/RT/Articles.pm                                |  541 +++-
 lib/RT/Articles_Overlay.pm                        |  546 ---
 lib/RT/Attachment.pm                              |  811 ++++-
 lib/RT/Attachment_Overlay.pm                      |  765 ----
 lib/RT/Attachments.pm                             |  185 +-
 lib/RT/Attachments_Overlay.pm                     |  238 --
 lib/RT/Attribute.pm                               |  430 ++-
 lib/RT/Attribute_Overlay.pm                       |  436 ---
 lib/RT/Attributes.pm                              |  164 +-
 lib/RT/Attributes_Overlay.pm                      |  212 --
 lib/RT/Base.pm                                    |    1 +
 lib/RT/CachedGroupMember.pm                       |  305 ++-
 lib/RT/CachedGroupMember_Overlay.pm               |  305 --
 lib/RT/CachedGroupMembers.pm                      |  120 +-
 lib/RT/CachedGroupMembers_Overlay.pm              |  165 -
 lib/RT/Class.pm                                   |  404 ++-
 lib/RT/Class_Overlay.pm                           |  451 ---
 lib/RT/Classes.pm                                 |   57 +-
 lib/RT/Classes_Overlay.pm                         |   87 -
 lib/RT/Condition.pm                               |    1 +
 lib/RT/Config.pm                                  |   24 +-
 lib/RT/CurrentUser.pm                             |    1 +
 lib/RT/CustomField.pm                             | 1693 +++++++++-
 lib/RT/CustomFieldValue.pm                        |  149 +-
 lib/RT/CustomFieldValue_Overlay.pm                |  147 -
 lib/RT/CustomFieldValues.pm                       |   49 +-
 lib/RT/CustomFieldValues_Overlay.pm               |   73 -
 lib/RT/CustomField_Overlay.pm                     | 1696 ---------
 lib/RT/CustomFields.pm                            |  318 ++-
 lib/RT/CustomFields_Overlay.pm                    |  378 --
 lib/RT/Dashboard.pm                               |    1 +
 lib/RT/Dashboard/Mailer.pm                        |    6 +-
 lib/RT/Date.pm                                    |    1 +
 lib/RT/EmailParser.pm                             |    1 +
 lib/RT/Group.pm                                   | 1267 +++++++-
 lib/RT/GroupMember.pm                             |  374 ++-
 lib/RT/GroupMember_Overlay.pm                     |  376 --
 lib/RT/GroupMembers.pm                            |   96 +-
 lib/RT/GroupMembers_Overlay.pm                    |  143 -
 lib/RT/Group_Overlay.pm                           | 1226 -------
 lib/RT/Groups.pm                                  |  383 ++-
 lib/RT/Groups_Overlay.pm                          |  432 ---
 lib/RT/Handle.pm                                  |    1 +
 lib/RT/I18N.pm                                    |  104 +-
 lib/RT/I18N/cs.pm                                 |    3 +
 lib/RT/I18N/ru.pm                                 |    3 +
 lib/RT/Installer.pm                               |    1 +
 lib/RT/Interface/Email/Auth/MailFrom.pm           |    4 +
 lib/RT/Interface/Web.pm                           |   54 +-
 lib/RT/Interface/Web/Handler.pm                   |    1 +
 lib/RT/Lifecycle.pm                               |    1 +
 lib/RT/Link.pm                                    |  292 ++-
 lib/RT/Link_Overlay.pm                            |  282 --
 lib/RT/Links.pm                                   |  120 +-
 lib/RT/Links_Overlay.pm                           |  166 -
 lib/RT/ObjectClass.pm                             |   91 +-
 lib/RT/ObjectClass_Overlay.pm                     |   76 -
 lib/RT/ObjectClasses.pm                           |   64 +-
 lib/RT/ObjectClasses_Overlay.pm                   |   69 -
 lib/RT/ObjectCustomField.pm                       |  296 ++-
 lib/RT/ObjectCustomFieldValue.pm                  |  568 +++-
 lib/RT/ObjectCustomFieldValue_Overlay.pm          |  500 ---
 lib/RT/ObjectCustomFieldValues.pm                 |  116 +-
 lib/RT/ObjectCustomFieldValues_Overlay.pm         |  138 -
 lib/RT/ObjectCustomField_Overlay.pm               |  268 --
 lib/RT/ObjectCustomFields.pm                      |   96 +-
 lib/RT/ObjectCustomFields_Overlay.pm              |  118 -
 lib/RT/ObjectTopics.pm                            |   55 +-
 lib/RT/ObjectTopics_Overlay.pm                    |   94 -
 lib/RT/Plugin.pm                                  |    3 +-
 lib/RT/Principal.pm                               |  711 ++++-
 lib/RT/Principal_Overlay.pm                       |  730 ----
 lib/RT/Principals.pm                              |   29 +-
 lib/RT/Principals_Overlay.pm                      |   75 -
 lib/RT/Queue.pm                                   | 1270 +++++++-
 lib/RT/Queue_Overlay.pm                           | 1270 -------
 lib/RT/Queues.pm                                  |   65 +-
 lib/RT/Queues_Overlay.pm                          |  111 -
 lib/RT/Record.pm                                  |    1 +
 lib/RT/Reminders.pm                               |    5 +-
 lib/RT/Report/Tickets/Entry.pm                    |    4 +
 lib/RT/Rule.pm                                    |    1 +
 lib/RT/Ruleset.pm                                 |    1 +
 lib/RT/SQL.pm                                     |    1 +
 lib/RT/SavedSearch.pm                             |    1 +
 lib/RT/Scrip.pm                                   |  770 ++++-
 lib/RT/ScripAction.pm                             |  266 ++-
 lib/RT/ScripAction_Overlay.pm                     |  263 --
 lib/RT/ScripActions.pm                            |   52 +-
 lib/RT/ScripActions_Overlay.pm                    |  104 -
 lib/RT/ScripCondition.pm                          |  227 +-
 lib/RT/ScripCondition_Overlay.pm                  |  214 --
 lib/RT/ScripConditions.pm                         |   50 +-
 lib/RT/ScripConditions_Overlay.pm                 |  104 -
 lib/RT/Scrip_Overlay.pm                           |  670 ----
 lib/RT/Scrips.pm                                  |  322 ++-
 lib/RT/Scrips_Overlay.pm                          |  376 --
 lib/RT/Search.pm                                  |    1 +
 lib/RT/SearchBuilder.pm                           |    1 +
 lib/RT/SharedSetting.pm                           |    1 +
 lib/RT/Shredder.pm                                |    2 +-
 lib/RT/Shredder/Constants.pm                      |    3 +
 lib/RT/Squish.pm                                  |   62 +-
 lib/RT/Squish/CSS.pm                              |   71 +-
 lib/RT/Squish/JS.pm                               |   77 +-
 lib/RT/System.pm                                  |    1 +
 lib/RT/Template.pm                                |  752 ++++-
 lib/RT/Template_Overlay.pm                        |  715 ----
 lib/RT/Templates.pm                               |  104 +-
 lib/RT/Templates_Overlay.pm                       |  188 -
 lib/RT/Test.pm                                    |    1 +
 lib/RT/Ticket.pm                                  | 3857 ++++++++++++++++++++-
 lib/RT/Ticket_Overlay.pm                          | 3678 --------------------
 lib/RT/Tickets.pm                                 | 3415 ++++++++++++++++++-
 lib/RT/Tickets_Overlay.pm                         | 3452 ------------------
 lib/RT/{Tickets_Overlay_SQL.pm => Tickets_SQL.pm} |    1 +
 lib/RT/Topic.pm                                   |  214 +-
 lib/RT/Topic_Overlay.pm                           |  251 --
 lib/RT/Topics.pm                                  |   61 +-
 lib/RT/Topics_Overlay.pm                          |  100 -
 lib/RT/Transaction.pm                             | 1417 +++++++-
 lib/RT/Transaction_Overlay.pm                     | 1357 --------
 lib/RT/Transactions.pm                            |  106 +-
 lib/RT/Transactions_Overlay.pm                    |  153 -
 lib/RT/URI.pm                                     |    1 +
 lib/RT/User.pm                                    | 1655 ++++++++-
 lib/RT/User_Overlay.pm                            | 1555 ---------
 lib/RT/Users.pm                                   |  494 +++-
 lib/RT/Users_Overlay.pm                           |  547 ---
 lib/RT/Util.pm                                    |    1 +
 sbin/rt-test-dependencies.in                      |    3 +
 sbin/rt-validator.in                              |    2 +-
 share/html/Admin/Articles/Classes/Modify.html     |    7 +-
 share/html/Admin/CustomFields/Modify.html         |    9 +-
 share/html/Admin/Groups/Modify.html               |    7 +-
 share/html/Admin/Queues/Modify.html               |    9 +-
 share/html/Admin/Users/Modify.html                |    9 +-
 share/html/Articles/Article/Edit.html             |    9 +-
 share/html/Dashboards/Modify.html                 |   10 +-
 share/html/Elements/Header                        |   14 +-
 share/html/Elements/HeaderJavascript              |   18 +-
 share/html/Elements/MaybeRedirectForResults       |   67 -
 share/html/Elements/Tabs                          |    8 +-
 share/html/NoAuth/css/aileron/misc.css            |    1 -
 share/html/NoAuth/css/aileron/msie-pie.css        |    2 +-
 share/html/NoAuth/css/aileron/msie6.css           |    2 +-
 share/html/NoAuth/css/aileron/nav.css             |    6 +-
 share/html/NoAuth/css/aileron/ticket-search.css   |    1 -
 share/html/NoAuth/css/ballard/misc.css            |    1 -
 share/html/NoAuth/css/base/history-folding.css    |    1 +
 share/html/NoAuth/css/base/superfish.css          |    4 +-
 share/html/NoAuth/css/base/tablesorter.css        |    6 +-
 share/html/NoAuth/css/dhandler                    |   11 +-
 share/html/NoAuth/css/web2/misc.css               |    1 -
 share/html/NoAuth/css/web2/msie-pie.css           |    2 +-
 share/html/NoAuth/css/web2/msie6.css              |    4 +-
 share/html/NoAuth/css/web2/nav.css                |    6 +-
 share/html/NoAuth/js/dhandler                     |   10 +-
 share/html/NoAuth/js/history-folding.js           |    2 +-
 share/html/Search/Build.html                      |    2 +-
 share/html/Ticket/Display.html                    |   11 +-
 share/html/Ticket/Elements/FoldStanzaJS           |    4 +-
 share/html/Ticket/Elements/Reminders              |   26 +-
 share/html/Ticket/Elements/ShowSummary            |    2 +-
 share/html/Ticket/Reminders.html                  |    4 +-
 share/html/index.html                             |    9 +-
 share/html/m/_elements/menu                       |    3 +-
 share/po/ar.po                                    | 3041 ++++++++++-------
 share/po/bg.po                                    | 2979 ++++++++++------
 share/po/cs.po                                    | 2991 ++++++++++------
 share/po/da.po                                    | 2983 ++++++++++------
 share/po/de.po                                    | 2979 ++++++++++------
 share/po/el.po                                    | 3021 ++++++++++-------
 share/po/en.po                                    |    2 +-
 share/po/en_GB.po                                 | 1777 +++++-----
 share/po/es.po                                    | 2971 ++++++++++------
 share/po/et.po                                    | 3019 ++++++++++-------
 share/po/fi.po                                    | 2991 ++++++++++------
 share/po/fr.po                                    | 2981 ++++++++++------
 share/po/he.po                                    | 3037 ++++++++++-------
 share/po/hr.po                                    | 2971 ++++++++++-------
 share/po/hu.po                                    | 3017 ++++++++++-------
 share/po/id.po                                    | 3031 ++++++++++-------
 share/po/is.po                                    | 3013 ++++++++++-------
 share/po/it.po                                    | 2973 ++++++++++------
 share/po/ja.po                                    | 3017 ++++++++++-------
 share/po/lt.po                                    | 2985 ++++++++++------
 share/po/nb.po                                    | 2975 ++++++++++------
 share/po/nl.po                                    | 3023 ++++++++++-------
 share/po/nn.po                                    | 2975 ++++++++++------
 share/po/pl.po                                    | 2961 ++++++++++-------
 share/po/pt.po                                    | 2997 ++++++++++------
 share/po/pt_BR.po                                 | 2977 ++++++++++------
 share/po/pt_PT.po                                 | 3023 ++++++++++-------
 share/po/rt.pot                                   | 3041 ++++++++++-------
 share/po/ru.po                                    | 2977 ++++++++++------
 share/po/sv.po                                    | 3001 ++++++++++------
 share/po/tr.po                                    | 3011 ++++++++++------
 share/po/zh_CN.po                                 | 2977 ++++++++++------
 share/po/zh_TW.po                                 | 2997 ++++++++++------
 t/api/i18n_guess.t                                |   47 +
 t/api/squish.t                                    |   20 +-
 t/api/template-simple.t                           |   18 +-
 t/customfields/datetime_search.t                  |    4 +-
 t/fts/indexed_pg.t                                |    5 +
 t/i18n/caching.t                                  |    6 +-
 t/shredder/utils.pl                               |    1 -
 t/web/cf_datetime.t                               |   95 +-
 t/web/reminders.t                                 |   88 +
 t/web/squish.t                                    |   25 +-
 t/web/ticket_forward.t                            |   17 +-
 257 files changed, 83525 insertions(+), 67476 deletions(-)
 delete mode 100644 UPGRADING.rtfm
 create mode 100644 docs/UPGRADING-2.x
 create mode 100644 docs/UPGRADING-3.0
 create mode 100644 docs/UPGRADING-3.2
 create mode 100644 docs/UPGRADING-3.4
 create mode 100644 docs/UPGRADING-3.6
 create mode 100644 docs/UPGRADING-3.8
 create mode 100644 docs/UPGRADING-4.0
 delete mode 100644 etc/rtfm/upgrade/2.1.0/acl.Oracle
 delete mode 100644 etc/rtfm/upgrade/2.1.0/acl.Pg
 delete mode 100644 etc/rtfm/upgrade/2.1.0/acl.mysql
 delete mode 100644 etc/rtfm/upgrade/2.1.0/content
 delete mode 100644 etc/rtfm/upgrade/2.1.0/schema.Oracle
 delete mode 100644 etc/rtfm/upgrade/2.1.0/schema.Pg
 delete mode 100644 etc/rtfm/upgrade/2.1.0/schema.mysql
 delete mode 100644 etc/rtfm/upgrade/2.1.30/acl.Oracle
 delete mode 100644 etc/rtfm/upgrade/2.1.30/acl.Pg
 delete mode 100644 etc/rtfm/upgrade/2.1.30/acl.mysql
 delete mode 100644 etc/rtfm/upgrade/2.1.30/content
 delete mode 100644 etc/rtfm/upgrade/2.1.30/schema.Oracle
 delete mode 100644 etc/rtfm/upgrade/2.1.30/schema.Pg
 delete mode 100644 etc/rtfm/upgrade/2.1.30/schema.mysql
 delete mode 100644 etc/rtfm/upgrade/2.2.0RC2/acl.Oracle
 delete mode 100644 etc/rtfm/upgrade/2.2.0RC2/acl.Pg
 delete mode 100644 etc/rtfm/upgrade/2.2.0RC2/acl.mysql
 delete mode 100644 etc/rtfm/upgrade/2.2.0RC2/content
 delete mode 100644 etc/rtfm/upgrade/2.2.0RC2/schema.Oracle
 delete mode 100644 etc/rtfm/upgrade/2.2.0RC2/schema.Pg
 delete mode 100644 etc/rtfm/upgrade/2.2.0RC2/schema.mysql
 delete mode 100644 etc/rtfm/upgrade/migrate-2.0-to-2.1
 delete mode 100755 etc/rtfm/upgrade/upgrade-mysql-schema.pl
 create mode 100644 etc/upgrade/3.9.8/content
 create mode 100644 etc/upgrade/upgrade-articles.in
 mode change 100755 => 100644 lib/RT.pm
 mode change 100755 => 100644 lib/RT/ACE.pm
 delete mode 100755 lib/RT/ACE_Overlay.pm
 mode change 100755 => 100644 lib/RT/ACL.pm
 delete mode 100755 lib/RT/ACL_Overlay.pm
 mode change 100755 => 100644 lib/RT/Action.pm
 mode change 100755 => 100644 lib/RT/Action/AutoOpen.pm
 mode change 100755 => 100644 lib/RT/Action/Autoreply.pm
 mode change 100755 => 100644 lib/RT/Action/CreateTickets.pm
 mode change 100755 => 100644 lib/RT/Action/EscalatePriority.pm
 mode change 100755 => 100644 lib/RT/Action/LinearEscalate.pm
 mode change 100755 => 100644 lib/RT/Action/Notify.pm
 mode change 100755 => 100644 lib/RT/Action/NotifyAsComment.pm
 mode change 100755 => 100644 lib/RT/Action/ResolveMembers.pm
 mode change 100755 => 100644 lib/RT/Action/SendEmail.pm
 mode change 100755 => 100644 lib/RT/Action/SetPriority.pm
 mode change 100755 => 100644 lib/RT/Action/SetStatus.pm
 mode change 100755 => 100644 lib/RT/Action/UserDefined.pm
 delete mode 100644 lib/RT/Article_Overlay.pm
 delete mode 100644 lib/RT/Articles_Overlay.pm
 mode change 100755 => 100644 lib/RT/Attachment.pm
 delete mode 100644 lib/RT/Attachment_Overlay.pm
 mode change 100755 => 100644 lib/RT/Attachments.pm
 delete mode 100755 lib/RT/Attachments_Overlay.pm
 delete mode 100644 lib/RT/Attribute_Overlay.pm
 delete mode 100644 lib/RT/Attributes_Overlay.pm
 mode change 100755 => 100644 lib/RT/Base.pm
 mode change 100755 => 100644 lib/RT/CachedGroupMember.pm
 delete mode 100755 lib/RT/CachedGroupMember_Overlay.pm
 mode change 100755 => 100644 lib/RT/CachedGroupMembers.pm
 delete mode 100755 lib/RT/CachedGroupMembers_Overlay.pm
 delete mode 100644 lib/RT/Class_Overlay.pm
 delete mode 100644 lib/RT/Classes_Overlay.pm
 mode change 100755 => 100644 lib/RT/Condition.pm
 mode change 100755 => 100644 lib/RT/Condition/AnyTransaction.pm
 mode change 100755 => 100644 lib/RT/Condition/BeforeDue.pm
 mode change 100755 => 100644 lib/RT/Condition/Overdue.pm
 mode change 100755 => 100644 lib/RT/Condition/OwnerChange.pm
 mode change 100755 => 100644 lib/RT/Condition/PriorityExceeds.pm
 mode change 100755 => 100644 lib/RT/Condition/QueueChange.pm
 mode change 100755 => 100644 lib/RT/Condition/StatusChange.pm
 mode change 100755 => 100644 lib/RT/Condition/UserDefined.pm
 mode change 100755 => 100644 lib/RT/CurrentUser.pm
 mode change 100755 => 100644 lib/RT/CustomField.pm
 mode change 100755 => 100644 lib/RT/CustomFieldValue.pm
 delete mode 100644 lib/RT/CustomFieldValue_Overlay.pm
 mode change 100755 => 100644 lib/RT/CustomFieldValues.pm
 delete mode 100755 lib/RT/CustomFieldValues_Overlay.pm
 delete mode 100755 lib/RT/CustomField_Overlay.pm
 mode change 100755 => 100644 lib/RT/CustomFields.pm
 delete mode 100755 lib/RT/CustomFields_Overlay.pm
 mode change 100755 => 100644 lib/RT/Date.pm
 mode change 100755 => 100644 lib/RT/EmailParser.pm
 mode change 100755 => 100644 lib/RT/Group.pm
 mode change 100755 => 100644 lib/RT/GroupMember.pm
 delete mode 100755 lib/RT/GroupMember_Overlay.pm
 mode change 100755 => 100644 lib/RT/GroupMembers.pm
 delete mode 100755 lib/RT/GroupMembers_Overlay.pm
 delete mode 100755 lib/RT/Group_Overlay.pm
 mode change 100755 => 100644 lib/RT/Groups.pm
 delete mode 100755 lib/RT/Groups_Overlay.pm
 mode change 100755 => 100644 lib/RT/Handle.pm
 mode change 100755 => 100644 lib/RT/I18N.pm
 mode change 100755 => 100644 lib/RT/I18N/cs.pm
 mode change 100755 => 100644 lib/RT/I18N/i_default.pm
 mode change 100755 => 100644 lib/RT/I18N/ru.pm
 mode change 100755 => 100644 lib/RT/Interface/CLI.pm
 mode change 100755 => 100644 lib/RT/Interface/Email.pm
 mode change 100755 => 100644 lib/RT/Interface/Email/Auth/MailFrom.pm
 mode change 100755 => 100644 lib/RT/Interface/REST.pm
 mode change 100755 => 100644 lib/RT/Interface/Web.pm
 mode change 100755 => 100644 lib/RT/Interface/Web/QueryBuilder.pm
 mode change 100755 => 100644 lib/RT/Interface/Web/QueryBuilder/Tree.pm
 mode change 100755 => 100644 lib/RT/Link.pm
 delete mode 100755 lib/RT/Link_Overlay.pm
 mode change 100755 => 100644 lib/RT/Links.pm
 delete mode 100755 lib/RT/Links_Overlay.pm
 delete mode 100644 lib/RT/ObjectClass_Overlay.pm
 delete mode 100644 lib/RT/ObjectClasses_Overlay.pm
 delete mode 100644 lib/RT/ObjectCustomFieldValue_Overlay.pm
 delete mode 100644 lib/RT/ObjectCustomFieldValues_Overlay.pm
 delete mode 100644 lib/RT/ObjectCustomField_Overlay.pm
 delete mode 100644 lib/RT/ObjectCustomFields_Overlay.pm
 delete mode 100644 lib/RT/ObjectTopics_Overlay.pm
 mode change 100755 => 100644 lib/RT/Principal.pm
 delete mode 100755 lib/RT/Principal_Overlay.pm
 mode change 100755 => 100644 lib/RT/Principals.pm
 delete mode 100755 lib/RT/Principals_Overlay.pm
 mode change 100755 => 100644 lib/RT/Queue.pm
 delete mode 100755 lib/RT/Queue_Overlay.pm
 mode change 100755 => 100644 lib/RT/Queues.pm
 delete mode 100755 lib/RT/Queues_Overlay.pm
 mode change 100755 => 100644 lib/RT/Record.pm
 mode change 100755 => 100644 lib/RT/Scrip.pm
 mode change 100755 => 100644 lib/RT/ScripAction.pm
 delete mode 100755 lib/RT/ScripAction_Overlay.pm
 mode change 100755 => 100644 lib/RT/ScripActions.pm
 delete mode 100755 lib/RT/ScripActions_Overlay.pm
 mode change 100755 => 100644 lib/RT/ScripCondition.pm
 delete mode 100755 lib/RT/ScripCondition_Overlay.pm
 mode change 100755 => 100644 lib/RT/ScripConditions.pm
 delete mode 100755 lib/RT/ScripConditions_Overlay.pm
 delete mode 100755 lib/RT/Scrip_Overlay.pm
 mode change 100755 => 100644 lib/RT/Scrips.pm
 delete mode 100644 lib/RT/Scrips_Overlay.pm
 mode change 100755 => 100644 lib/RT/Search.pm
 mode change 100755 => 100644 lib/RT/Search/ActiveTicketsInQueue.pm
 mode change 100755 => 100644 lib/RT/SearchBuilder.pm
 mode change 100755 => 100644 lib/RT/StyleGuide.pod
 mode change 100755 => 100644 lib/RT/System.pm
 mode change 100755 => 100644 lib/RT/Template.pm
 delete mode 100755 lib/RT/Template_Overlay.pm
 mode change 100755 => 100644 lib/RT/Templates.pm
 delete mode 100755 lib/RT/Templates_Overlay.pm
 mode change 100755 => 100644 lib/RT/Ticket.pm
 delete mode 100755 lib/RT/Ticket_Overlay.pm
 mode change 100755 => 100644 lib/RT/Tickets.pm
 delete mode 100755 lib/RT/Tickets_Overlay.pm
 rename lib/RT/{Tickets_Overlay_SQL.pm => Tickets_SQL.pm} (99%)
 mode change 100755 => 100644
 delete mode 100644 lib/RT/Topic_Overlay.pm
 delete mode 100644 lib/RT/Topics_Overlay.pm
 mode change 100755 => 100644 lib/RT/Transaction.pm
 delete mode 100755 lib/RT/Transaction_Overlay.pm
 mode change 100755 => 100644 lib/RT/Transactions.pm
 delete mode 100755 lib/RT/Transactions_Overlay.pm
 mode change 100755 => 100644 lib/RT/URI.pm
 mode change 100755 => 100644 lib/RT/URI/base.pm
 mode change 100755 => 100644 lib/RT/URI/fsck_com_rt.pm
 mode change 100755 => 100644 lib/RT/User.pm
 delete mode 100755 lib/RT/User_Overlay.pm
 mode change 100755 => 100644 lib/RT/Users.pm
 delete mode 100755 lib/RT/Users_Overlay.pm
 delete mode 100644 share/html/Elements/MaybeRedirectForResults
 create mode 100644 t/api/i18n_guess.t
 create mode 100644 t/web/reminders.t

- Log -----------------------------------------------------------------
commit 1effcc25a1d6e02752c04e223162724cf5b01324
Merge: e840186 d1da765
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon Jan 3 13:19:44 2011 -0500

    Merge branch '4.0-trunk'
    
    Conflicts:
    	etc/rtfm/upgrade/2.1.0/schema.mysql
    	lib/RT/CustomField.pm
    	lib/RT/Links.pm
    	lib/RT/Principal.pm
    	lib/RT/Reminders.pm
    	lib/RT/Template.pm
    	lib/RT/Tickets.pm
    	lib/RT/Topic.pm
    	lib/RT/Transaction.pm

diff --cc lib/RT/CustomField.pm
index 2cb5bcb,620fb58..890da04
mode 100755,100644..100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@@ -136,6 -1573,137 +1573,137 @@@ sub ValuesForObject 
  }
  
  
+ =head2 _ForObjectType PATH FRIENDLYNAME
+ 
+ Tell RT that a certain object accepts custom fields
+ 
+ Examples:
+ 
+     'RT::Queue-RT::Ticket'                 => "Tickets",                # loc
+     'RT::Queue-RT::Ticket-RT::Transaction' => "Ticket Transactions",    # loc
+     'RT::User'                             => "Users",                  # loc
+     'RT::Group'                            => "Groups",                 # loc
+ 
+ This is a class method. 
+ 
+ =cut
+ 
+ sub _ForObjectType {
+     my $self = shift;
+     my $path = shift;
+     my $friendly_name = shift;
+ 
+     $FRIENDLY_OBJECT_TYPES{$path} = $friendly_name;
+ 
+ }
+ 
+ 
+ =head2 IncludeContentForValue [VALUE] (and SetIncludeContentForValue)
+ 
+ Gets or sets the  C<IncludeContentForValue> for this custom field. RT
+ uses this field to automatically include content into the user's browser
+ as they display records with custom fields in RT.
+ 
+ =cut
+ 
+ sub SetIncludeContentForValue {
+     shift->IncludeContentForValue(@_);
+ }
+ sub IncludeContentForValue{
+     my $self = shift;
+     $self->_URLTemplate('IncludeContentForValue', @_);
+ }
+ 
+ 
+ 
+ =head2 LinkValueTo [VALUE] (and SetLinkValueTo)
+ 
+ Gets or sets the  C<LinkValueTo> for this custom field. RT
+ uses this field to make custom field values into hyperlinks in the user's
+ browser as they display records with custom fields in RT.
+ 
+ =cut
+ 
+ 
+ sub SetLinkValueTo {
+     shift->LinkValueTo(@_);
+ }
+ 
+ sub LinkValueTo {
+     my $self = shift;
+     $self->_URLTemplate('LinkValueTo', @_);
+ 
+ }
+ 
+ 
+ =head2 _URLTemplate  NAME [VALUE]
+ 
+ With one argument, returns the _URLTemplate named C<NAME>, but only if
+ the current user has the right to see this custom field.
+ 
+ With two arguments, attemptes to set the relevant template value.
+ 
+ =cut
+ 
+ sub _URLTemplate {
+     my $self          = shift;
+     my $template_name = shift;
+     if (@_) {
+ 
+         my $value = shift;
+         unless ( $self->CurrentUserHasRight('AdminCustomField') ) {
+             return ( 0, $self->loc('Permission Denied') );
+         }
+         $self->SetAttribute( Name => $template_name, Content => $value );
+         return ( 1, $self->loc('Updated') );
+     } else {
+         unless ( $self->id && $self->CurrentUserHasRight('SeeCustomField') ) {
+             return (undef);
+         }
+ 
+         my @attr = $self->Attributes->Named($template_name);
+         my $attr = shift @attr;
+ 
+         if ($attr) { return $attr->Content }
+ 
+     }
+ }
+ 
+ sub SetBasedOn {
+     my $self = shift;
+     my $value = shift;
+ 
+     return $self->_Set( Field => 'BasedOn', Value => $value, @_ )
+         unless defined $value and length $value;
+ 
+     my $cf = RT::CustomField->new( $self->CurrentUser );
+     $cf->Load( ref $value ? $value->id : $value );
+ 
 -    return (0, "Permission denied")
++    return (0, "Permission Denied")
+         unless $cf->id && $cf->CurrentUserHasRight('SeeCustomField');
+ 
+     # XXX: Remove this restriction once we support lists and cascaded selects
+     if ( $self->RenderType =~ /List/ ) {
+         return (0, $self->loc("We can't currently render as a List when basing categories on another custom field.  Please use another render type."));
+     }
+ 
+     return $self->_Set( Field => 'BasedOn', Value => $value, @_ )
+ }
+ 
+ sub BasedOnObj {
+     my $self = shift;
+ 
+     my $obj = RT::CustomField->new( $self->CurrentUser );
+     if ( $self->BasedOn ) {
+         $obj->Load( $self->BasedOn );
+     }
+     return $obj;
+ }
+ 
+ 
+ 
+ 
+ 
  
  =head2 id
  
diff --cc lib/RT/Principal.pm
index 8e40951,510cb2b..b167922
mode 100755,100644..100644
--- a/lib/RT/Principal.pm
+++ b/lib/RT/Principal.pm
@@@ -68,27 -79,605 +79,605 @@@ Returns undef, otherwis
  
  =cut
  
- package RT::Principal;
- use base 'RT::Record';
+ sub IsGroup {
+     my $self = shift;
+     if ( defined $self->PrincipalType && 
+             $self->PrincipalType eq 'Group' ) {
+         return 1;
+     }
+     return undef;
+ }
+ 
+ 
+ 
+ =head2 IsUser 
+ 
+ Returns true if this principal is a User. 
+ Returns undef, otherwise
+ 
+ =cut
+ 
+ sub IsUser {
+     my $self = shift;
+     if ($self->PrincipalType eq 'User') {
+         return(1);
+     }
+     else {
+         return undef;
+     }
+ }
+ 
+ 
+ 
+ =head2 Object
+ 
+ Returns the user or group associated with this principal
+ 
+ =cut
+ 
+ sub Object {
+     my $self = shift;
+ 
+     unless ( $self->{'object'} ) {
+         if ( $self->IsUser ) {
+            $self->{'object'} = RT::User->new($self->CurrentUser);
+         }
+         elsif ( $self->IsGroup ) {
+             $self->{'object'}  = RT::Group->new($self->CurrentUser);
+         }
+         else { 
+             $RT::Logger->crit("Found a principal (".$self->Id.") that was neither a user nor a group");
+             return(undef);
+         }
+         $self->{'object'}->Load( $self->ObjectId() );
+     }
+     return ($self->{'object'});
+ 
+ 
+ }
+ 
+ 
+ 
+ =head2 GrantRight  { Right => RIGHTNAME, Object => undef }
+ 
+ A helper function which calls RT::ACE->Create
+ 
+ 
+ 
+    Returns a tuple of (STATUS, MESSAGE);  If the call succeeded, STATUS is true. Otherwise it's 
+    false.
+ 
+ =cut
+ 
+ sub GrantRight {
+     my $self = shift;
+     my %args = (
+         Right => undef,
+         Object => undef,
+         @_
+     );
+ 
 -    return (0, "Permission denied") if $args{'Right'} eq 'ExecuteCode'
++    return (0, "Permission Denied") if $args{'Right'} eq 'ExecuteCode'
+         and RT->Config->Get('DisallowExecuteCode');
+ 
+     #ACL check handled in ACE.pm
+     my $ace = RT::ACE->new( $self->CurrentUser );
+ 
+     my $type = $self->_GetPrincipalTypeForACL();
+ 
+     RT->System->QueueCacheNeedsUpdate(1) if $args{'Right'} eq 'SeeQueue';
+ 
+     # If it's a user, we really want to grant the right to their 
+     # user equivalence group
+     return $ace->Create(
+         RightName     => $args{'Right'},
+         Object        => $args{'Object'},
+         PrincipalType => $type,
+         PrincipalId   => $self->Id,
+     );
+ }
+ 
+ 
+ =head2 RevokeRight { Right => "RightName", Object => "object" }
+ 
+ Delete a right that a user has 
+ 
+ 
+    Returns a tuple of (STATUS, MESSAGE);  If the call succeeded, STATUS is true. Otherwise it's 
+       false.
+ 
+ 
+ =cut
+ 
+ sub RevokeRight {
+ 
+     my $self = shift;
+     my %args = (
+         Right  => undef,
+         Object => undef,
+         @_
+     );
+ 
+     #if we haven't specified any sort of right, we're talking about a global right
+     if (!defined $args{'Object'} && !defined $args{'ObjectId'} && !defined $args{'ObjectType'}) {
+         $args{'Object'} = $RT::System;
+     }
+     #ACL check handled in ACE.pm
+     my $type = $self->_GetPrincipalTypeForACL();
+ 
+     my $ace = RT::ACE->new( $self->CurrentUser );
+     my ($status, $msg) = $ace->LoadByValues(
+         RightName     => $args{'Right'},
+         Object        => $args{'Object'},
+         PrincipalType => $type,
+         PrincipalId   => $self->Id
+     );
+ 
+     if ( not $status and $msg =~ /Invalid right/ ) {
+         $RT::Logger->warn("Tried to revoke the invalid right '$args{Right}', ignoring it.");
+         return (1);
+     }
+ 
+     RT->System->QueueCacheNeedsUpdate(1) if $args{'Right'} eq 'SeeQueue';
+     return ($status, $msg) unless $status;
+     return $ace->Delete;
+ }
+ 
+ 
+ 
+ =head2 HasRight (Right => 'right' Object => undef)
+ 
+ Checks to see whether this principal has the right "Right" for the Object
+ specified. This takes the params:
+ 
+ =over 4
+ 
+ =item Right
+ 
+ name of a right
+ 
+ =item Object
+ 
+ an RT style object (->id will get its id)
+ 
+ =back
+ 
+ Returns 1 if a matching ACE was found. Returns undef if no ACE was found.
+ 
+ Use L</HasRights> to fill a fast cache, especially if you're going to
+ check many different rights with the same principal and object.
+ 
+ =cut
+ 
+ sub HasRight {
+ 
+     my $self = shift;
+     my %args = ( Right        => undef,
+                  Object       => undef,
+                  EquivObjects => undef,
+                  @_,
+                );
+ 
+     # RT's SystemUser always has all rights
+     if ( $self->id == RT->SystemUser->id ) {
+         return 1;
+     }
+ 
+     $args{'Right'} = RT::ACE->CanonicalizeRightName( $args{'Right'} );
+     unless ( $args{'Right'} ) {
+         $RT::Logger->error(
+                "Invalid right. Couldn't canonicalize right '$args{'Right'}'");
+         return undef;
+     }
+ 
+     return undef if $args{'Right'} eq 'ExecuteCode'
+         and RT->Config->Get('DisallowExecuteCode');
+ 
+     $args{'EquivObjects'} = [ @{ $args{'EquivObjects'} } ]
+         if $args{'EquivObjects'};
+ 
+     if ( $self->__Value('Disabled') ) {
+         $RT::Logger->debug(   "Disabled User #"
+                             . $self->id
+                             . " failed access check for "
+                             . $args{'Right'} );
+         return (undef);
+     }
+ 
+     if ( eval { $args{'Object'}->id } ) {
+         push @{ $args{'EquivObjects'} }, $args{'Object'};
+     } else {
+         $RT::Logger->crit("HasRight called with no valid object");
+         return (undef);
+     }
  
- sub _Init {
-   my $self = shift; 
+     {
+         my $cached = $_ACL_CACHE->fetch(
+             $self->id .';:;'. ref($args{'Object'}) .'-'. $args{'Object'}->id
+         );
+         return $cached->{'SuperUser'} || $cached->{ $args{'Right'} }
+             if $cached;
+     }
+ 
+     unshift @{ $args{'EquivObjects'} },
+         $args{'Object'}->ACLEquivalenceObjects;
+ 
+     unshift @{ $args{'EquivObjects'} }, $RT::System
+         unless $self->can('_IsOverrideGlobalACL')
+             && $self->_IsOverrideGlobalACL( $args{'Object'} );
+ 
+     # If we've cached a win or loss for this lookup say so
+ 
+ # Construct a hashkeys to cache decisions:
+ # 1) full_hashkey - key for any result and for full combination of uid, right and objects
+ # 2) short_hashkey - one key for each object to store positive results only, it applies
+ # only to direct group rights and partly to role rights
+     my $full_hashkey = join (";:;", $self->id, $args{'Right'});
+     foreach ( @{ $args{'EquivObjects'} } ) {
+         my $ref_id = $self->_ReferenceId($_);
+         $full_hashkey .= ";:;".$ref_id;
+ 
+         my $short_hashkey = join(";:;", $self->id, $args{'Right'}, $ref_id);
+         my $cached_answer = $_ACL_CACHE->fetch($short_hashkey);
+         return $cached_answer > 0 if defined $cached_answer;
+     }
+ 
+     {
+         my $cached_answer = $_ACL_CACHE->fetch($full_hashkey);
+         return $cached_answer > 0 if defined $cached_answer;
+     }
+ 
+     my ( $hitcount, $via_obj ) = $self->_HasRight(%args);
+ 
+     $_ACL_CACHE->set( $full_hashkey => $hitcount ? 1 : -1 );
+     $_ACL_CACHE->set( join(';:;',  $self->id, $args{'Right'},$via_obj) => 1 )
+         if $via_obj && $hitcount;
+ 
+     return ($hitcount);
+ }
+ 
+ =head2 HasRights
+ 
+ Returns a hash reference with all rights this principal has on an
+ object. Takes Object as a named argument.
+ 
+ Main use case of this method is the following:
+ 
+     $ticket->CurrentUser->PrincipalObj->HasRights( Object => $ticket );
+     ...
+     $ticket->CurrentUserHasRight('A');
+     ...
+     $ticket->CurrentUserHasRight('Z');
+ 
+ Results are cached and the cache is used in this and, as well, in L</HasRight>
+ method speeding it up. Don't use hash reference returned by this method
+ directly for rights checks as it's more complicated then it seems, especially
+ considering config options like 'DisallowExecuteCode'.
+ 
+ =cut
+ 
+ sub HasRights {
+     my $self = shift;
+     my %args = (
+         Object       => undef,
+         EquivObjects => undef,
+         @_
+     );
+     return {} if $self->__Value('Disabled');
+ 
+     my $object = $args{'Object'};
+     unless ( eval { $object->id } ) {
+         $RT::Logger->crit("HasRights called with no valid object");
+     }
+ 
+     my $cache_key = $self->id .';:;'. ref($object) .'-'. $object->id;
+     my $cached = $_ACL_CACHE->fetch($cache_key);
+     return $cached if $cached;
+ 
+     push @{ $args{'EquivObjects'} }, $object;
+     unshift @{ $args{'EquivObjects'} },
+         $args{'Object'}->ACLEquivalenceObjects;
+     unshift @{ $args{'EquivObjects'} }, $RT::System
+         unless $self->can('_IsOverrideGlobalACL')
+             && $self->_IsOverrideGlobalACL( $object );
+ 
+     my %res = ();
+     {
+         my $query
+             = "SELECT DISTINCT ACL.RightName "
+             . $self->_HasGroupRightQuery(
+                 EquivObjects => $args{'EquivObjects'}
+             );
+         my $rights = $RT::Handle->dbh->selectcol_arrayref($query);
+         unless ($rights) {
+             $RT::Logger->warning( $RT::Handle->dbh->errstr );
+             return ();
+         }
+         $res{$_} = 1 foreach @$rights;
+     }
+     my $roles;
+     {
+         my $query
+             = "SELECT DISTINCT Groups.Type "
+             . $self->_HasRoleRightQuery(
+                 EquivObjects => $args{'EquivObjects'}
+             );
+         $roles = $RT::Handle->dbh->selectcol_arrayref($query);
+         unless ($roles) {
+             $RT::Logger->warning( $RT::Handle->dbh->errstr );
+             return ();
+         }
+     }
+     if ( @$roles ) {
+         my $query
+             = "SELECT DISTINCT ACL.RightName "
+             . $self->_RolesWithRightQuery(
+                 EquivObjects => $args{'EquivObjects'}
+             )
+             . ' AND ('. join( ' OR ', map "PrincipalType = '$_'", @$roles ) .')'
+         ;
+         my $rights = $RT::Handle->dbh->selectcol_arrayref($query);
+         unless ($rights) {
+             $RT::Logger->warning( $RT::Handle->dbh->errstr );
+             return ();
+         }
+         $res{$_} = 1 foreach @$rights;
+     }
+ 
+     delete $res{'ExecuteCode'} if 
+         RT->Config->Get('DisallowExecuteCode');
+ 
+     $_ACL_CACHE->store( $cache_key, \%res );
+     return \%res;
+ }
+ 
+ =head2 _HasRight
+ 
+ Low level HasRight implementation, use HasRight method instead.
+ 
+ =cut
+ 
+ sub _HasRight {
+     my $self = shift;
+     {
+         my ( $hit, @other ) = $self->_HasGroupRight(@_);
+         return ( $hit, @other ) if $hit;
+     }
+     {
+         my ( $hit, @other ) = $self->_HasRoleRight(@_);
+         return ( $hit, @other ) if $hit;
+     }
+     return (0);
+ }
+ 
+ # this method handles role rights partly in situations
+ # where user plays role X on an object and as well the right is
+ # assigned to this role X of the object, for example right CommentOnTicket
+ # is granted to Cc role of a queue and user is in cc list of the queue
+ sub _HasGroupRight {
+     my $self = shift;
+     my %args = ( Right        => undef,
+                  EquivObjects => [],
+                  @_
+                );
+ 
+     my $query
+         = "SELECT ACL.id, ACL.ObjectType, ACL.ObjectId "
+         . $self->_HasGroupRightQuery( %args );
+ 
+     $self->_Handle->ApplyLimits( \$query, 1 );
+     my ( $hit, $obj, $id ) = $self->_Handle->FetchResult($query);
+     return (0) unless $hit;
+ 
+     $obj .= "-$id" if $id;
+     return ( 1, $obj );
+ }
+ 
+ sub _HasGroupRightQuery {
+     my $self = shift;
+     my %args = (
+         Right        => undef,
+         EquivObjects => [],
+         @_
+     );
+ 
+     my $query
+         = "FROM ACL, Principals, CachedGroupMembers WHERE "
+ 
+         # Never find disabled groups.
+         . "Principals.id = ACL.PrincipalId "
+         . "AND Principals.PrincipalType = 'Group' "
+         . "AND Principals.Disabled = 0 "
+ 
+ # See if the principal is a member of the group recursively or _is the rightholder_
+ # never find recursively disabled group members
+ # also, check to see if the right is being granted _directly_ to this principal,
+ #  as is the case when we want to look up group rights
+         . "AND CachedGroupMembers.GroupId  = ACL.PrincipalId "
+         . "AND CachedGroupMembers.GroupId  = Principals.id "
+         . "AND CachedGroupMembers.MemberId = ". $self->Id . " "
+         . "AND CachedGroupMembers.Disabled = 0 ";
+ 
+     my @clauses;
+     foreach my $obj ( @{ $args{'EquivObjects'} } ) {
+         my $type = ref($obj) || $obj;
+         my $clause = "ACL.ObjectType = '$type'";
+ 
+         if ( defined eval { $obj->id } ) {    # it might be 0
+             $clause .= " AND ACL.ObjectId = " . $obj->id;
+         }
+ 
+         push @clauses, "($clause)";
+     }
+     if (@clauses) {
+         $query .= " AND (" . join( ' OR ', @clauses ) . ")";
+     }
+     if ( my $right = $args{'Right'} ) {
+         # Only find superuser or rights with the name $right
+         $query .= " AND (ACL.RightName = 'SuperUser' "
+             . ( $right ne 'SuperUser' ? "OR ACL.RightName = '$right'" : '' )
+         . ") ";
+     }
+     return $query;
+ }
  
-   $self->Table('Principals');
-   $self->SUPER::_Init(@_);
+ sub _HasRoleRight {
+     my $self = shift;
+     my %args = ( Right        => undef,
+                  EquivObjects => [],
+                  @_
+                );
+ 
+     my @roles = $self->RolesWithRight(%args);
+     return 0 unless @roles;
+ 
+     my $query = "SELECT Groups.id "
+         . $self->_HasRoleRightQuery( %args, Roles => \@roles );
+ 
+     $self->_Handle->ApplyLimits( \$query, 1 );
+     my ($hit) = $self->_Handle->FetchResult($query);
+     return (1) if $hit;
+ 
+     return 0;
  }
  
+ sub _HasRoleRightQuery {
+     my $self = shift;
+     my %args = ( Right        => undef,
+                  EquivObjects => [],
+                  Roles        => undef,
+                  @_
+                );
+ 
+     my $query =
+         " FROM Groups, Principals, CachedGroupMembers WHERE "
+ 
+         # Never find disabled things
+         . "Principals.Disabled = 0 " . "AND CachedGroupMembers.Disabled = 0 "
+ 
+         # We always grant rights to Groups
+         . "AND Principals.id = Groups.id "
+         . "AND Principals.PrincipalType = 'Group' "
+ 
+ # See if the principal is a member of the group recursively or _is the rightholder_
+ # never find recursively disabled group members
+ # also, check to see if the right is being granted _directly_ to this principal,
+ #  as is the case when we want to look up group rights
+         . "AND Principals.id = CachedGroupMembers.GroupId "
+         . "AND CachedGroupMembers.MemberId = " . $self->Id . " "
+     ;
+ 
+     if ( $args{'Roles'} ) {
+         $query .= "AND (" . join( ' OR ', map "Groups.Type = '$_'", @{ $args{'Roles'} } ) . ")";
+     }
+ 
+     my (@object_clauses);
+     foreach my $obj ( @{ $args{'EquivObjects'} } ) {
+         my $type = ref($obj) ? ref($obj) : $obj;
+ 
+         my $clause = "Groups.Domain = '$type-Role'";
+ 
+         # XXX: Groups.Instance is VARCHAR in DB, we should quote value
+         # if we want mysql 4.0 use indexes here. we MUST convert that
+         # field to integer and drop this quotes.
+         if ( my $id = eval { $obj->id } ) {
+             $clause .= " AND Groups.Instance = '$id'";
+         }
+         push @object_clauses, "($clause)";
+     }
+     $query .= " AND (" . join( ' OR ', @object_clauses ) . ")";
+     return $query;
+ }
  
+ =head2 RolesWithRight
  
+ Returns list with names of roles that have right on
+ set of objects. Takes Right, EquiveObjects,
+ IncludeSystemRights and IncludeSuperusers arguments.
  
+ IncludeSystemRights is true by default, rights
+ granted systemwide are ignored when IncludeSystemRights
+ is set to a false value.
  
- =head2 Create PARAMHASH
+ IncludeSuperusers is true by default, SuperUser right
+ is not checked if it's set to a false value.
  
- Create takes a hash of values and creates a row in the database:
+ =cut
  
-   varchar(16) 'PrincipalType'.
-   int(11) 'ObjectId'.
-   smallint(6) 'Disabled'.
+ sub RolesWithRight {
+     my $self = shift;
+     my %args = ( Right               => undef,
+                  IncludeSystemRights => 1,
+                  IncludeSuperusers   => 1,
+                  EquivObjects        => [],
+                  @_
+                );
+ 
+     return () if $args{'Right'} eq 'ExecuteCode'
+         and RT->Config->Get('DisallowExecuteCode');
+ 
+     my $query = "SELECT DISTINCT PrincipalType "
+         . $self->_RolesWithRightQuery( %args );
+ 
+     my $roles = $RT::Handle->dbh->selectcol_arrayref($query);
+     unless ($roles) {
+         $RT::Logger->warning( $RT::Handle->dbh->errstr );
+         return ();
+     }
+     return @$roles;
+ }
+ 
+ sub _RolesWithRightQuery {
+     my $self = shift;
+     my %args = ( Right               => undef,
+                  IncludeSystemRights => 1,
+                  IncludeSuperusers   => 1,
+                  EquivObjects        => [],
+                  @_
+                );
+ 
+     my $query = " FROM ACL WHERE"
+ 
+         # we need only roles
+         . " PrincipalType != 'Group'";
+ 
+     if ( my $right = $args{'Right'} ) {
+         $query .=
+             # Only find superuser or rights with the requested right
+             " AND ( RightName = '$right' "
+ 
+             # Check SuperUser if we were asked to
+             . ( $args{'IncludeSuperusers'} ? "OR RightName = 'SuperUser' " : '' )
+             . ")";
+     }
+ 
+     # skip rights granted on system level if we were asked to
+     unless ( $args{'IncludeSystemRights'} ) {
+         $query .= " AND ObjectType != 'RT::System'";
+     }
+ 
+     my (@object_clauses);
+     foreach my $obj ( @{ $args{'EquivObjects'} } ) {
+         my $type = ref($obj) ? ref($obj) : $obj;
+ 
+         my $object_clause = "ObjectType = '$type'";
+         if ( my $id = eval { $obj->id } ) {
+             $object_clause .= " AND ObjectId = $id";
+         }
+         push @object_clauses, "($object_clause)";
+     }
+ 
+     # find ACLs that are related to our objects only
+     $query .= " AND (" . join( ' OR ', @object_clauses ) . ")"
+         if @object_clauses;
+ 
+     return $query;
+ }
+ 
+ 
+ =head2 InvalidateACLCache
+ 
+ Cleans out and reinitializes the user rights cache
  
  =cut
  
diff --cc lib/RT/Topic.pm
index c2acd9b,3a3bccc..cf6c4da
--- a/lib/RT/Topic.pm
+++ b/lib/RT/Topic.pm
@@@ -65,33 -68,97 +68,97 @@@ Create takes a hash of values and creat
  
  =cut
  
- no warnings 'redefine';
- package RT::Topic;
- use RT::Record; 
+ sub Create {
+     my $self = shift;
+     my %args = (
+                 Parent => '',
+                 Name => '',
+                 Description => '',
+                 ObjectType => '',
+                 ObjectId => '0',
+                 @_);
+ 
+     my $obj = $RT::System;
+     if ($args{ObjectId}) {
+         $obj = $args{ObjectType}->new($self->CurrentUser);
+         $obj->Load($args{ObjectId});
+         $obj = $RT::System unless $obj->id;
+     }
+ 
 -    return ( 0, $self->loc("Permission denied"))
++    return ( 0, $self->loc("Permission Denied"))
+       unless ( $self->CurrentUser->HasRight(
+                                             Right        => "AdminTopics",
+                                             Object       => $obj,
+                                             EquivObjects => [ $RT::System, $obj ],
+                                            ) );
+ 
+     $self->SUPER::Create(@_);
+ }
+ 
+ # }}}
+ 
+ 
+ # {{{ Delete
  
+ =head2 Delete
  
- use base qw( RT::Record );
+ Deletes this topic, reparenting all sub-topics to this one's parent.
  
- sub _Init {
-   my $self = shift; 
+ =cut
  
-   $self->Table('Topics');
-   $self->SUPER::_Init(@_);
+ sub Delete {
+     my $self = shift;
+     
+     unless ( $self->CurrentUserHasRight('AdminTopics') ) {
+         return ( 0, $self->loc("Permission Denied") );
+     }
+ 
+     my $kids = RT::Topics->new($self->CurrentUser);
+     $kids->LimitToKids($self->Id);
+     while (my $topic = $kids->Next) {
+         $topic->setParent($self->Parent);
+     }
+ 
+     $self->SUPER::Delete(@_);
+     return (0, "Topic deleted");
  }
  
+ # }}}
  
  
+ # {{{ DeleteAll
  
+ =head2 DeleteAll
  
- =head2 Create PARAMHASH
+ Deletes this topic, and all of its descendants.
  
- Create takes a hash of values and creates a row in the database:
+ =cut
  
-   int(11) 'Parent'.
-   varchar(255) 'Name'.
-   varchar(255) 'Description'.
-   varchar(64) 'ObjectType'.
-   int(11) 'ObjectId'.
+ sub DeleteAll {
+     my $self = shift;
+     
+     unless ( $self->CurrentUserHasRight('AdminTopics') ) {
+         return ( 0, $self->loc("Permission Denied") );
+     }
+ 
+     $self->SUPER::Delete(@_);
+     my $kids = RT::Topics->new($self->CurrentUser);
+     $kids->LimitToKids($self->Id);
+     while (my $topic = $kids->Next) {
+         $topic->DeleteAll;
+     }
+ 
+     return (0, "Topic tree deleted");
+ }
+ 
+ # }}}
+ 
+ 
+ # {{{ ParentObj
+ 
+ =head2 ParentObj
+ 
+ Returns the parent Topic of this one.
  
  =cut
  

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


More information about the Rt-commit mailing list