Commit 94662b4a39a860f595e672a98ec2f146b99270d8

Authored by kevin_fourie
1 parent cb5c72c3

Merged in from DEV trunk...

KTC-399
"Bulk checkout: when you checkout an already checked out document you get an information alert that is not clear"
Fixed. If a document is checked out by the current user it now gets added to the downloaded files.

Committed by: Megan Watson
Reviewed by: Jonathan Byrne

KTS-2655
"Error Message On Removing Permissions but action goes ahead anyway"
Fixed. Added a check to ensure the user doesn't removed his/her own permission to manage security.

Committed by: Megan Watson
Reviewed by: Jonathan Byrne

KTS-2873
"Double quote (") is not accepted as valid input for metadata when the name of a Lookup field or a Tree field has a Double quote in."
Fixed. The values in the sub categories needed to be htmlentities().

Committed by: Megan Watson
Reviewed by: Jonathan Byrne

KTS-3091
"The name of the open office service needs to be changed in the script to check if its running"
Fixed. Changed the name and the paths to match the new stack.

Committed by: Megan Watson
Reviewed by: Jonathan Byrne

KTS-3093
"Creating fieldsets and fields with quotes results in double escaping of names and descriptions"
Fixed.

Committed By: Conrad Vermeulen
Reviewed By: Megan Watson

KTS-3096
"Creating workflow, workflow states, workflow transition names with quotes results in double escaping of names and descriptions"
Fixed.

Committed By: Conrad Vermeulen
Reviewed By: Megan Watson

KTS-3097
"Field names with quotes was impacting on search2 query builder"
Fixed.

Committed By: Conrad Vermeulen
Reviewed By: Megan Watson

KTS-3085
"Storage utilisation plugin does not seem to be working on Windows Vista."
Fixed. Unfortunately, df does not work on Vista. We now detect if df has a problem and disable the dashlet accordingly.

Committed By: Conrad Vermeulen
Reviewed By: Megan Watson

KTC-403
"One is able to make a checked out document immutable"

Fixed. Added a check to return an error if the document is checked out.

Committed By: Jonathan Byrne
Reviewed By: Megan Watson

KTS-1888
"Expunge page in the DMS Administration section, pagination not working, links to consecutive pages do not work"

Fixed. Changed the php file to return the contents of a div and not just a table body so that pagination works in Internet Explorer.

Committed By: Jonathan Byrne
Reviewed By: Jalaloedien Abrahams


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/STABLE/trunk@8171 c91229c3-7414-0410-bfa2-8a42b809f60b
bin/checkopenoffice.php
... ... @@ -42,24 +42,23 @@ require_once('../config/dmsDefaults.php');
42 42 // Check if open office is running
43 43 $sCheckOO = SearchHelper::checkOpenOfficeAvailablity();
44 44  
45   -
46 45 // If it is running - exit, we don't need to do anything otherwise start it
47 46 if(!empty($sCheckOO)){
48   -
  47 +
49 48 $default->log->debug('Check Open Office Task: Open office service is not running... trying to start it.');
50   -
  49 +
51 50 if(OS_WINDOWS){
52   -
  51 +
53 52 // Check the path first
54   - $sPath = realpath('../../winserv.exe');
  53 + $sPath = realpath('../../bin/winserv.exe');
55 54  
56 55 if(file_exists($sPath)){
57   - $sCmd = "\"$sPath\" start kt_openoffice";
  56 + $sCmd = "\"$sPath\" start ktopenoffice";
58 57 KTUtil::pexec($sCmd);
59 58 exit;
60 59 }
61 60 // If that doesn't work, check for the all start
62   - $sPath = realpath('../../bin/allctl.bat');
  61 + $sPath = realpath('../../bin/dmsctl.bat');
63 62 if(file_exists($sPath)){
64 63 $sCmd = "\"$sPath\" start";
65 64 KTUtil::pexec($sCmd);
... ...
lib/documentmanagement/DocumentField.inc
... ... @@ -7,32 +7,32 @@
7 7 * KnowledgeTree Open Source Edition
8 8 * Document Management Made Simple
9 9 * Copyright (C) 2004 - 2008 The Jam Warehouse Software (Pty) Limited
10   - *
  10 + *
11 11 * This program is free software; you can redistribute it and/or modify it under
12 12 * the terms of the GNU General Public License version 3 as published by the
13 13 * Free Software Foundation.
14   - *
  14 + *
15 15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 18 * details.
19   - *
  19 + *
20 20 * You should have received a copy of the GNU General Public License
21 21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22   - *
  22 + *
23 23 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
24 24 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
25   - *
  25 + *
26 26 * The interactive user interfaces in modified source and object code versions
27 27 * of this program must display Appropriate Legal Notices, as required under
28 28 * Section 5 of the GNU General Public License version 3.
29   - *
  29 + *
30 30 * In accordance with Section 7(b) of the GNU General Public License version 3,
31 31 * these Appropriate Legal Notices must retain the display of the "Powered by
32   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  32 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
33 33 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
34   - * must display the words "Powered by KnowledgeTree" and retain the original
35   - * copyright notice.
  34 + * must display the words "Powered by KnowledgeTree" and retain the original
  35 + * copyright notice.
36 36 * Contributor( s): ______________________________________
37 37 */
38 38  
... ... @@ -79,10 +79,10 @@ class DocumentField extends KTEntity {
79 79 }
80 80  
81 81 function getID() { return $this->iId; }
82   - function getName() { return sanitizeForSQLtoHTML($this->sName); }
83   - function setName($sNewValue) { $this->sName = sanitizeForSQL($sNewValue); }
84   - function setDescription($sNewValue) { $this->sDescription = sanitizeForSQL($sNewValue); }
85   - function getDescription() { return sanitizeForSQLtoHTML($this->sDescription); }
  82 + function getName() { return $this->sName; }
  83 + function setName($sNewValue) { $this->sName = $sNewValue; }
  84 + function setDescription($sNewValue) { $this->sDescription = $sNewValue; }
  85 + function getDescription() { return $this->sDescription; }
86 86 function getDataType() { return $this->sDataType; }
87 87 function setDataType($sNewValue) { $this->sDataType = $sNewValue; }
88 88 function getIsGeneric() { return $this->bIsGeneric; }
... ...
lib/documentmanagement/MDTree.inc
... ... @@ -289,7 +289,7 @@ class MDTree {
289 289 $extraclass = ' inactive';
290 290 }
291 291  
292   - $treeStr .= '<li class="treenode' . $extraclass . '"><a class="pathnode" onclick="toggleElementClass(\'active\', this.parentNode);toggleElementClass(\'inactive\', this.parentNode);">' . $treeToRender->mapnodes[$subnode_val]->getName() . '</a>';
  292 + $treeStr .= '<li class="treenode' . $extraclass . '"><a class="pathnode" onclick="toggleElementClass(\'active\', this.parentNode);toggleElementClass(\'inactive\', this.parentNode);">' . htmlentities($treeToRender->mapnodes[$subnode_val]->getName()) . '</a>';
293 293 $treeStr .= $this->_evilTreeRecursion($subnode_val, $treeToRender, $inputname);
294 294 $treeStr .= '</li>';
295 295 }
... ... @@ -301,7 +301,8 @@ class MDTree {
301 301 if ($leaf === $this->activevalue) {
302 302 $is_selected=' checked="checked"';
303 303 }
304   - $treeStr .= '<li class="leafnode"><input type="radio" name="'.$inputname.'" value="'.$treeToRender->lookups[$leaf]->getName().'" '.$is_selected.'>' . $treeToRender->lookups[$leaf]->getName() .'</input>';
  304 + $sValue = htmlentities($treeToRender->lookups[$leaf]->getName());
  305 + $treeStr .= '<li class="leafnode"><input type="radio" name="'.$inputname.'" value="'.$sValue.'" '.$is_selected.'>' . $sValue .'</input>';
305 306 $treeStr .= '</li>'; }
306 307 }
307 308 }
... ...
lib/groups/GroupUtil.php
... ... @@ -7,32 +7,32 @@
7 7 * KnowledgeTree Open Source Edition
8 8 * Document Management Made Simple
9 9 * Copyright (C) 2004 - 2008 The Jam Warehouse Software (Pty) Limited
10   - *
  10 + *
11 11 * This program is free software; you can redistribute it and/or modify it under
12 12 * the terms of the GNU General Public License version 3 as published by the
13 13 * Free Software Foundation.
14   - *
  14 + *
15 15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 18 * details.
19   - *
  19 + *
20 20 * You should have received a copy of the GNU General Public License
21 21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22   - *
  22 + *
23 23 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
24 24 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
25   - *
  25 + *
26 26 * The interactive user interfaces in modified source and object code versions
27 27 * of this program must display Appropriate Legal Notices, as required under
28 28 * Section 5 of the GNU General Public License version 3.
29   - *
  29 + *
30 30 * In accordance with Section 7(b) of the GNU General Public License version 3,
31 31 * these Appropriate Legal Notices must retain the display of the "Powered by
32   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  32 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
33 33 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
34   - * must display the words "Powered by KnowledgeTree" and retain the original
35   - * copyright notice.
  34 + * must display the words "Powered by KnowledgeTree" and retain the original
  35 + * copyright notice.
36 36 * Contributor( s): ______________________________________
37 37 */
38 38  
... ... @@ -304,6 +304,26 @@ class GroupUtil {
304 304 }
305 305 // }}}
306 306  
  307 + function checkUserInGroups($iUserId, $aGroupIds) {
  308 + $sGroupIds = implode(', ', $aGroupIds);
  309 +
  310 + global $default;
  311 + $sTable = $default->users_groups_table;
  312 + $sQuery = "SELECT count(*) AS cnt FROM $sTable WHERE user_id = ? AND group_id IN (?)";
  313 + $aParams = array($iUserId, $sGroupIds);
  314 +
  315 + $res = DBUtil::getOneResult(array($sQuery, $aParams));
  316 +
  317 + if(PEAR::isError($res) || empty($res)){
  318 + return false;
  319 + }
  320 +
  321 + if($res['cnt'] > 0){
  322 + return true;
  323 + }
  324 + return false;
  325 + }
  326 +
307 327 // {{{
308 328 function buildGroupArray() {
309 329 global $default;
... ...
lib/metadata/fieldset.inc.php
... ... @@ -5,32 +5,32 @@
5 5 * KnowledgeTree Open Source Edition
6 6 * Document Management Made Simple
7 7 * Copyright (C) 2004 - 2008 The Jam Warehouse Software (Pty) Limited
8   - *
  8 + *
9 9 * This program is free software; you can redistribute it and/or modify it under
10 10 * the terms of the GNU General Public License version 3 as published by the
11 11 * Free Software Foundation.
12   - *
  12 + *
13 13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 15 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 16 * details.
17   - *
  17 + *
18 18 * You should have received a copy of the GNU General Public License
19 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20   - *
  20 + *
21 21 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
22 22 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
23   - *
  23 + *
24 24 * The interactive user interfaces in modified source and object code versions
25 25 * of this program must display Appropriate Legal Notices, as required under
26 26 * Section 5 of the GNU General Public License version 3.
27   - *
  27 + *
28 28 * In accordance with Section 7(b) of the GNU General Public License version 3,
29 29 * these Appropriate Legal Notices must retain the display of the "Powered by
30   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  30 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
31 31 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
32   - * must display the words "Powered by KnowledgeTree" and retain the original
33   - * copyright notice.
  32 + * must display the words "Powered by KnowledgeTree" and retain the original
  33 + * copyright notice.
34 34 * Contributor( s): ______________________________________
35 35 *
36 36 */
... ... @@ -45,7 +45,7 @@ require_once(KT_LIB_DIR . &quot;/util/sanitize.inc&quot;);
45 45 * Represents the basic grouping of fields into a fieldset.
46 46 */
47 47 class KTFieldset extends KTEntity {
48   -
  48 +
49 49 /** primary key value */
50 50 var $iId = -1;
51 51 /** document fieldset name */
... ... @@ -54,7 +54,7 @@ class KTFieldset extends KTEntity {
54 54 var $sDescription;
55 55 /** document fieldset namespace */
56 56 var $sNamespace;
57   -
  57 +
58 58 /** document fieldset mandatory flag */
59 59 var $bMandatory = false;
60 60 var $iMasterFieldId;
... ... @@ -70,30 +70,30 @@ class KTFieldset extends KTEntity {
70 70 * is used only by the document management system.
71 71 */
72 72 var $bIsSystem = false;
73   -
  73 +
74 74 var $_bUsePearError = true;
75   -
  75 +
76 76 function getId() { return $this->iId; }
77   - function getName() { return sanitizeForSQLtoHTML($this->sName); }
78   - function setDescription($sNewValue) { $this->sDescription = sanitizeForSQL($sNewValue); }
79   - function getDescription() { return sanitizeForSQLtoHTML($this->sDescription); }
80   - function setName($sNewValue) { $this->sName = sanitizeForSQL($sNewValue); }
  77 + function getName() { return $this->sName; }
  78 + function setDescription($sNewValue) { $this->sDescription = $sNewValue; }
  79 + function getDescription() { return $this->sDescription; }
  80 + function setName($sNewValue) { $this->sName = $sNewValue; }
81 81 function getNamespace() { return $this->sNamespace; }
82 82 function setNamespace($sNewValue) { $this->sNamespace = $sNewValue; }
83 83 function getMandatory() { return $this->bMandatory; }
84   - function setMandatory($bNewValue) { $this->bMandatory = $bNewValue; }
  84 + function setMandatory($bNewValue) { $this->bMandatory = $bNewValue; }
85 85 function getIsConditional () { return $this->bIsConditional; }
86   - function setIsConditional ($bNewValue) { $this->bIsConditional = $bNewValue; }
  86 + function setIsConditional ($bNewValue) { $this->bIsConditional = $bNewValue; }
87 87 function getMasterFieldId () { return $this->iMasterFieldId; }
88   - function setMasterFieldId ($iNewValue) { $this->iMasterFieldId = $iNewValue; }
  88 + function setMasterFieldId ($iNewValue) { $this->iMasterFieldId = $iNewValue; }
89 89 function getIsGeneric () { return $this->bIsGeneric; }
90   - function setIsGeneric ($bNewValue) { $this->bIsGeneric = $bNewValue; }
  90 + function setIsGeneric ($bNewValue) { $this->bIsGeneric = $bNewValue; }
91 91 function getIsComplete () { return $this->bIsComplete; }
92   - function setIsComplete ($bNewValue) { $this->bIsComplete = $bNewValue; }
  92 + function setIsComplete ($bNewValue) { $this->bIsComplete = $bNewValue; }
93 93 function getIsComplex () { return $this->bIsComplex; }
94   - function setIsComplex ($bNewValue) { $this->bIsComplex = $bNewValue; }
  94 + function setIsComplex ($bNewValue) { $this->bIsComplex = $bNewValue; }
95 95 function getIsSystem () { return $this->bIsSystem; }
96   - function setIsSystem ($bNewValue) { $this->bIsSystem = $bNewValue; }
  96 + function setIsSystem ($bNewValue) { $this->bIsSystem = $bNewValue; }
97 97  
98 98 var $_aFieldToSelect = array(
99 99 "iId" => "id",
... ... @@ -108,17 +108,17 @@ class KTFieldset extends KTEntity {
108 108 "bIsComplex" => "is_complex",
109 109 "bIsSystem" => "is_system",
110 110 );
111   -
  111 +
112 112 // returns TRUE if all children are lookup enabled, false otherwise.
113 113 function canBeMadeConditional() {
114 114 if ($this->getIsConditional()) {
115 115 return false;
116 116 }
117   -
  117 +
118 118 // DEBUG
119 119 return false;
120 120 }
121   -
  121 +
122 122 function _table () {
123 123 return KTUtil::getTableName('fieldsets');
124 124 }
... ... @@ -127,13 +127,13 @@ class KTFieldset extends KTEntity {
127 127  
128 128  
129 129  
130   - /*
  130 + /*
131 131 * get document types using this field
132   - * for listing displays
  132 + * for listing displays
133 133 */
134 134 function &getDocumentTypesUsing($aOptions = null) {
135 135 $bIds = KTUtil::arrayGet($aOptions, 'ids');
136   -
  136 +
137 137 $sTable = KTUtil::getTableName('document_type_fieldsets');
138 138  
139 139 $aQuery = array(
... ... @@ -161,7 +161,7 @@ class KTFieldset extends KTEntity {
161 161  
162 162 // Static function
163 163 function &get($iId) { return KTEntityUtil::get('KTFieldset', $iId); }
164   - function &getList($sWhereClause = null) { return KTEntityUtil::getList2('KTFieldset', $sWhereClause); }
  164 + function &getList($sWhereClause = null) { return KTEntityUtil::getList2('KTFieldset', $sWhereClause); }
165 165 function &createFromArray($aOptions) { return KTEntityUtil::createFromArray('KTFieldset', $aOptions); }
166 166  
167 167 function &getNonGenericFieldsets($aOptions = null) {
... ... @@ -172,18 +172,18 @@ class KTFieldset extends KTEntity {
172 172 'is_generic' => false,
173 173 'disabled' => false,
174 174 ), $aOptions);
175   - }
  175 + }
176 176  
177 177 function &getGenericFieldsets($aOptions = null) {
178 178 $aOptions = KTUtil::meldOptions(
179   - $aOptions,
  179 + $aOptions,
180 180 array('multi' => true,)
181 181 );
182 182 return KTEntityUtil::getByDict('KTFieldset', array(
183 183 'is_generic' => true,
184 184 'disabled' => false,
185 185 ), $aOptions);
186   - }
  186 + }
187 187  
188 188 function &getForDocumentType($oDocumentType, $aOptions = null) {
189 189 $bIds = KTUtil::arrayGet($aOptions, 'ids');
... ... @@ -192,7 +192,7 @@ class KTFieldset extends KTEntity {
192 192 } else {
193 193 $iDocumentTypeId = $oDocumentType;
194 194 }
195   -
  195 +
196 196 $sTable = KTUtil::getTableName('document_type_fieldsets');
197 197 $aQuery = array(
198 198 "SELECT fieldset_id FROM $sTable WHERE document_type_id = ?",
... ... @@ -210,22 +210,22 @@ class KTFieldset extends KTEntity {
210 210 }
211 211 return $aRet;
212 212 }
213   -
  213 +
214 214 function &getAssociatedTypes() {
215 215 // NOTE: this returns null if we are generic (all is the wrong answer)
216 216 if ($this->getIsGeneric()) { return array(); }
217   -
  217 +
218 218 $sTable = KTUtil::getTableName('document_type_fieldsets');
219 219 $aQuery = array(
220 220 "SELECT document_type_id FROM $sTable WHERE fieldset_id = ?",
221 221 array($this->getId()),
222 222 );
223 223 $aIds = DBUtil::getResultArrayKey($aQuery, 'document_type_id');
224   -
  224 +
225 225 $aRet = array();
226 226 foreach ($aIds as $iID) {
227 227 $oType = DocumentType::get($iID);
228   - if (!PEAR::isError($oType)) {
  228 + if (!PEAR::isError($oType)) {
229 229 $aRet[] = $oType;
230 230 }
231 231 }
... ... @@ -248,13 +248,13 @@ class KTFieldset extends KTEntity {
248 248 'disabled' => false,
249 249 ));
250 250 }
251   -
  251 +
252 252 function &getByName($sName) {
253 253 return KTEntityUtil::getByDict('KTFieldset', array(
254 254 'name' => $sName,
255 255 'disabled' => false,
256 256 ));
257   - }
  257 + }
258 258 }
259 259  
260 260 ?>
... ...
lib/workflow/workflow.inc.php
... ... @@ -9,32 +9,32 @@
9 9 * KnowledgeTree Open Source Edition
10 10 * Document Management Made Simple
11 11 * Copyright (C) 2004 - 2008 The Jam Warehouse Software (Pty) Limited
12   - *
  12 + *
13 13 * This program is free software; you can redistribute it and/or modify it under
14 14 * the terms of the GNU General Public License version 3 as published by the
15 15 * Free Software Foundation.
16   - *
  16 + *
17 17 * This program is distributed in the hope that it will be useful, but WITHOUT
18 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
20 20 * details.
21   - *
  21 + *
22 22 * You should have received a copy of the GNU General Public License
23 23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24   - *
  24 + *
25 25 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
26 26 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
27   - *
  27 + *
28 28 * The interactive user interfaces in modified source and object code versions
29 29 * of this program must display Appropriate Legal Notices, as required under
30 30 * Section 5 of the GNU General Public License version 3.
31   - *
  31 + *
32 32 * In accordance with Section 7(b) of the GNU General Public License version 3,
33 33 * these Appropriate Legal Notices must retain the display of the "Powered by
34   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  34 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
35 35 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
36   - * must display the words "Powered by KnowledgeTree" and retain the original
37   - * copyright notice.
  36 + * must display the words "Powered by KnowledgeTree" and retain the original
  37 + * copyright notice.
38 38 * Contributor( s): ______________________________________
39 39 */
40 40  
... ... @@ -59,13 +59,13 @@ class KTWorkflow extends KTEntity {
59 59 var $_bUsePearError = true;
60 60  
61 61 function getID() { return $this->iId; }
62   - function getName() { return sanitizeForSQLtoHTML($this->sName); }
63   - function getHumanName() { return sanitizeForSQLtoHTML($this->sHumanName); }
  62 + function getName() { return ($this->sName); }
  63 + function getHumanName() { return ($this->sHumanName); }
64 64 function getStartStateId() { return $this->iStartStateId; }
65 65 function getIsEnabled() { return ($this->bEnabled == true); }
66 66 function setID($iId) { $this->iId = $iId; }
67   - function setName($sName) { $this->sName = sanitizeForSQL($sName); }
68   - function setHumanName($sHumanName) { $this->sHumanName = sanitizeForSQL($sHumanName); }
  67 + function setName($sName) { $this->sName = ($sName); }
  68 + function setHumanName($sHumanName) { $this->sHumanName = ($sHumanName); }
69 69 function setStartStateId($iStartStateId) { $this->iStartStateId = $iStartStateId; }
70 70 function setIsEnabled($mValue) { $this->bEnabled = ($mValue == true); }
71 71  
... ... @@ -98,7 +98,7 @@ class KTWorkflow extends KTEntity {
98 98 function &getByName($sName) {
99 99 return KTEntityUtil::getBy('KTWorkflow', 'name', $sName);
100 100 }
101   -
  101 +
102 102 function getIsFunctional() {
103 103 return (($this->getStartStateId() != false) && ($this->getIsEnabled()));
104 104 }
... ...
lib/workflow/workflowstate.inc.php
... ... @@ -8,32 +8,32 @@
8 8 * KnowledgeTree Open Source Edition
9 9 * Document Management Made Simple
10 10 * Copyright (C) 2004 - 2008 The Jam Warehouse Software (Pty) Limited
11   - *
  11 + *
12 12 * This program is free software; you can redistribute it and/or modify it under
13 13 * the terms of the GNU General Public License version 3 as published by the
14 14 * Free Software Foundation.
15   - *
  15 + *
16 16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 18 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 19 * details.
20   - *
  20 + *
21 21 * You should have received a copy of the GNU General Public License
22 22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23   - *
  23 + *
24 24 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
25 25 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
26   - *
  26 + *
27 27 * The interactive user interfaces in modified source and object code versions
28 28 * of this program must display Appropriate Legal Notices, as required under
29 29 * Section 5 of the GNU General Public License version 3.
30   - *
  30 + *
31 31 * In accordance with Section 7(b) of the GNU General Public License version 3,
32 32 * these Appropriate Legal Notices must retain the display of the "Powered by
33   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  33 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
34 34 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
35   - * must display the words "Powered by KnowledgeTree" and retain the original
36   - * copyright notice.
  35 + * must display the words "Powered by KnowledgeTree" and retain the original
  36 + * copyright notice.
37 37 * Contributor( s): ______________________________________
38 38 */
39 39  
... ... @@ -57,20 +57,20 @@ class KTWorkflowState extends KTEntity {
57 57 var $_bUsePearError = true;
58 58  
59 59 function getId() { return $this->iId; }
60   - function getName() { return sanitizeForSQLtoHTML($this->sName); }
61   - function getHumanName() { return sanitizeForSQLtoHTML($this->sHumanName); }
  60 + function getName() { return ($this->sName); }
  61 + function getHumanName() { return ($this->sHumanName); }
62 62 function getWorkflowId() { return $this->iWorkflowId; }
63 63 function getInformDescriptorId() { return $this->iInformDescriptorId; }
64 64 function setId($iId) { $this->iId = $iId; }
65   - function setName($sName) { $this->sName = sanitizeForSQL($sName); }
66   - function setHumanName($sHumanName) { $this->sHumanName = sanitizeForSQL($sHumanName); }
  65 + function setName($sName) { $this->sName = ($sName); }
  66 + function setHumanName($sHumanName) { $this->sHumanName = ($sHumanName); }
67 67 function setWorkflowId($iWorkflowId) { $this->iWorkflowId = $iWorkflowId; }
68 68 function setInformDescriptorId($iInformDescriptorId) { $this->iInformDescriptorId = $iInformDescriptorId; }
69 69  
70 70 function _table () {
71 71 return KTUtil::getTableName('workflow_states');
72 72 }
73   -
  73 +
74 74 function _ktentityOptions() {
75 75 return array(
76 76 'orderby' => 'human_name',
... ... @@ -128,13 +128,13 @@ class KTWorkflowState extends KTEntity {
128 128 'KTWorkflowState', array(
129 129 'name' => $sName,
130 130 'workflow_id' => $iWorkflowId
131   - )
  131 + )
132 132 );
133 133 // expect KTEntityNoObjects
134 134 if (PEAR::isError($res)) {
135 135 return false;
136 136 }
137   -
  137 +
138 138 return true;
139 139 }
140 140  
... ...
lib/workflow/workflowtransition.inc.php
... ... @@ -8,32 +8,32 @@
8 8 * KnowledgeTree Open Source Edition
9 9 * Document Management Made Simple
10 10 * Copyright (C) 2004 - 2008 The Jam Warehouse Software (Pty) Limited
11   - *
  11 + *
12 12 * This program is free software; you can redistribute it and/or modify it under
13 13 * the terms of the GNU General Public License version 3 as published by the
14 14 * Free Software Foundation.
15   - *
  15 + *
16 16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 18 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 19 * details.
20   - *
  20 + *
21 21 * You should have received a copy of the GNU General Public License
22 22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23   - *
  23 + *
24 24 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
25 25 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
26   - *
  26 + *
27 27 * The interactive user interfaces in modified source and object code versions
28 28 * of this program must display Appropriate Legal Notices, as required under
29 29 * Section 5 of the GNU General Public License version 3.
30   - *
  30 + *
31 31 * In accordance with Section 7(b) of the GNU General Public License version 3,
32 32 * these Appropriate Legal Notices must retain the display of the "Powered by
33   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  33 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
34 34 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
35   - * must display the words "Powered by KnowledgeTree" and retain the original
36   - * copyright notice.
  35 + * must display the words "Powered by KnowledgeTree" and retain the original
  36 + * copyright notice.
37 37 * Contributor( s): ______________________________________
38 38 */
39 39  
... ... @@ -67,8 +67,8 @@ class KTWorkflowTransition extends KTEntity {
67 67 var $_bUsePearError = true;
68 68  
69 69 function getId() { return $this->iId; }
70   - function getName() { return sanitizeForSQLtoHTML($this->sName); }
71   - function getHumanName() { return sanitizeForSQLtoHTML($this->sHumanName); }
  70 + function getName() { return ($this->sName); }
  71 + function getHumanName() { return ($this->sHumanName); }
72 72 function getWorkflowId() { return $this->iWorkflowId; }
73 73 function getTargetStateId() { return $this->iTargetStateId; }
74 74 function getGuardPermissionId() { return $this->iGuardPermissionId; }
... ... @@ -77,8 +77,8 @@ class KTWorkflowTransition extends KTEntity {
77 77 function getGuardConditionId() { return $this->iGuardConditionId; }
78 78  
79 79 function setId($iId) { $this->iId = $iId; }
80   - function setName($sName) { $this->sName = sanitizeForSQL($sName); }
81   - function setHumanName($sHumanName) { $this->sHumanName = sanitizeForSQL($sHumanName); }
  80 + function setName($sName) { $this->sName = ($sName); }
  81 + function setHumanName($sHumanName) { $this->sHumanName = ($sHumanName); }
82 82 function setWorkflowId($iWorkflowId) { $this->iWorkflowId = $iWorkflowId; }
83 83 function setTargetStateId($iTargetStateId) { $this->iTargetStateId = $iTargetStateId; }
84 84 function setGuardPermissionId($iGuardPermissionId) { $this->iGuardPermissionId = $iGuardPermissionId; }
... ... @@ -89,7 +89,7 @@ class KTWorkflowTransition extends KTEntity {
89 89 function _table () {
90 90 return KTUtil::getTableName('workflow_transitions');
91 91 }
92   -
  92 +
93 93 // STATIC
94 94 function _ktentityOptions() {
95 95 return array(
... ... @@ -146,7 +146,7 @@ class KTWorkflowTransition extends KTEntity {
146 146 $oWorkflowState =& KTWorkflowState::get($this->getTargetStateId());
147 147 return sprintf(_kt("%s (to state %s)"), $this->getName(), $oWorkflowState->getName());
148 148 }
149   -
  149 +
150 150 // STATIC
151 151 function nameExists($sName, $oWorkflow) {
152 152 $iWorkflowId = KTUtil::getId($oWorkflow);
... ... @@ -154,16 +154,16 @@ class KTWorkflowTransition extends KTEntity {
154 154 'KTWorkflowTransition', array(
155 155 'name' => $sName,
156 156 'workflow_id' => $iWorkflowId
157   - )
  157 + )
158 158 );
159 159 // expect KTEntityNoObjects
160 160 if (PEAR::isError($res)) {
161 161 return false;
162 162 }
163   -
  163 +
164 164 return true;
165 165 }
166   -
  166 +
167 167 }
168 168  
169 169 ?>
... ...
plugins/housekeeper/DiskUsageDashlet.inc.php
... ... @@ -61,13 +61,23 @@ class DiskUsageDashlet extends KTBaseDashlet
61 61 $this->warningPercent = $config->get('DiskUsage/warningThreshold', 15);
62 62 $this->urgentPercent = $config->get('DiskUsage/urgentThreshold', 5);
63 63  
64   - $this->getUsage();
  64 + $got_usage = $this->getUsage();
  65 +
  66 + if ($got_usage == false)
  67 + {
  68 + return false;
  69 + }
65 70  
66 71 return Permission::userIsSystemAdministrator();
67 72 }
68 73  
69 74 function getUsage($refresh=false)
70 75 {
  76 + if (isset($_SESSION['DiskUsage']['problem']))
  77 + {
  78 + return false;
  79 + }
  80 +
71 81 $check = true;
72 82 // check if we have a cached result
73 83 if (isset($_SESSION['DiskUsage']))
... ... @@ -96,6 +106,13 @@ class DiskUsageDashlet extends KTBaseDashlet
96 106 $result = shell_exec($cmd." 2>&1");
97 107 }
98 108  
  109 + if (strpos($result, 'cannot read table of mounted file systems') !== false)
  110 + {
  111 + $_SESSION['DiskUsage']['problem'] = true;
  112 + return false;
  113 + }
  114 +
  115 +
99 116 $result = explode("\n", $result);
100 117  
101 118 unset($result[0]); // gets rid of headings
... ... @@ -135,6 +152,8 @@ class DiskUsageDashlet extends KTBaseDashlet
135 152 $_SESSION['DiskUsage']['time'] = time();
136 153 $_SESSION['DiskUsage']['usage'] = $this->usage;
137 154 }
  155 +
  156 + return true;
138 157 }
139 158  
140 159 function render()
... ...
plugins/ktcore/KTBulkActions.php
... ... @@ -49,13 +49,13 @@ class KTBulkDeleteAction extends KTBulkAction {
49 49 function getDisplayName() {
50 50 return _kt('Delete');
51 51 }
52   -
  52 +
53 53 function check_entity($oEntity) {
54 54 if(is_a($oEntity, 'Document')) {
55 55 if($oEntity->getImmutable())
56 56 {
57 57 return PEAR::raiseError(_kt('Document cannot be deleted as it is immutable'));
58   - }
  58 + }
59 59 }
60 60 return parent::check_entity($oEntity);
61 61 }
... ... @@ -894,11 +894,23 @@ class KTBrowseBulkCheckoutAction extends KTBulkAction {
894 894 $sReason = $this->sReason;
895 895  
896 896 if(is_a($oEntity, 'Document')) {
897   - $res = KTDocumentUtil::checkout($oEntity, $sReason, $this->oUser);
898 897  
899   - if(PEAR::isError($res)) {
900   - return PEAR::raiseError($oEntity->getName().': '.$res->getMessage());
  898 + if($oEntity->getIsCheckedOut()){
  899 + $checkedOutUser = $oEntity->getCheckedOutUserID();
  900 + $sUserId = $_SESSION['userID'];
  901 +
  902 + if($checkedOutUser != $sUserId){
  903 + $oCheckedOutUser = User::get($checkedOutUser);
  904 + return PEAR::raiseError($oEntity->getName().': '._kt('Document has already been checked out by ').$oCheckedOutUser->getName());
  905 + }
  906 + }else{
  907 + $res = KTDocumentUtil::checkout($oEntity, $sReason, $this->oUser);
  908 +
  909 + if(PEAR::isError($res)) {
  910 + return PEAR::raiseError($oEntity->getName().': '.$res->getMessage());
  911 + }
901 912 }
  913 +
902 914 if($this->bDownload){
903 915 if ($this->bNoisy) {
904 916 $oDocumentTransaction = new DocumentTransaction($oEntity, "Document part of bulk checkout", 'ktstandard.transactions.check_out', array());
... ...
plugins/ktcore/admin/expungeList.php
... ... @@ -39,8 +39,9 @@ require_once(KT_LIB_DIR . &#39;/browse/browseutil.inc.php&#39;);
39 39  
40 40 require_once(KT_LIB_DIR . '/documentmanagement/Document.inc');
41 41 require_once(KT_LIB_DIR . '/documentmanagement/DocumentTransaction.inc');
42   -
43   -$aDocuments =& Document::getList("status_id=" . DELETED);
  42 +
  43 +$sWhere = "status_id=" . DELETED;
  44 +$aDocuments =& Document::getList($sWhere);
44 45  
45 46 $pageNum = $_REQUEST['page'];
46 47  
... ... @@ -50,6 +51,11 @@ if(fmod($items, 10) &gt; 0){
50 51 }else{
51 52 $pages = ($items/10);
52 53 }
  54 +
  55 +for($i=1; $i<=$pages; $i++){
  56 + $aPages[] = $i;
  57 +}
  58 +
53 59 if($pageNum == 1){
54 60 $listStart = 0;
55 61 $listEnd = 9;
... ... @@ -60,13 +66,53 @@ if($pageNum == 1){
60 66 $listStart = (10*($pageNum-1));
61 67 $listEnd = $listStart+9;
62 68 }
  69 +
  70 +
  71 +
  72 +$output = "<table class=\"kt_collection\">
  73 + <thead>
  74 + <tr>
  75 + <th style=\"width:2em\"><input type=\"checkbox\" onclick=\"toggleSelectFor(this, 'selected_docs')\" title=\"toggle all\"/></th>
  76 + <th>"._kt('Document Name').'</th>
  77 + <th>'._kt('Last Modification').'</th>
  78 + <th>'._kt('Deletion Comment').'</th>
  79 + </tr>
  80 + </thead>
  81 + <tbody>';
  82 +
  83 +
63 84 for($i = $listStart; $i <= $listEnd; $i++){
64   - $output .= "<tr>
65   - <td><input type='checkbox' name='selected_docs[]' value='".$aDocuments[$i]->getId()."'/></td>
  85 + $output .= "
  86 + <tr>
  87 + <td><input type=\"checkbox\" name=\"selected_docs[]\" value=\"".$aDocuments[$i]->getId()."\"/></td>
66 88 <td>".$aDocuments[$i]->getName()."</td>
67 89 <td>".$aDocuments[$i]->getLastModifiedDate()."</td>
68 90 <td>".$aDocuments[$i]->getLastDeletionComment()."</td>
69 91 </tr>";
  92 +
70 93 }
  94 +
  95 +
  96 +$output .= '<tfoot>
  97 + <tr>
  98 + <td colspan="4">
  99 + <span style="float: left">'.$items.' '._kt('items, 10 per page').'</span>
  100 + </td>
  101 + </tr>
  102 + <tr>
  103 + <td colspan="4">
  104 + <div align="center">';
  105 +
  106 + foreach($aPages as $page){
  107 + $output .= '<a href="#" onclick="buildList(this.innerHTML)">'.$page.'</a>&nbsp;';
  108 + }
  109 +
  110 +$output .= '</div>
  111 + </td>
  112 + </tr>
  113 + </tfoot>
  114 + </table>
  115 + </tbody></table>';
  116 +
71 117 echo $output;
72 118 ?>
... ...
plugins/ktcore/folder/Permissions.php
... ... @@ -453,11 +453,29 @@ class KTFolderPermissionsAction extends KTFolderAction {
453 453 if (!KTBrowseUtil::inAdminMode($this->oUser, $this->oFolder)) {
454 454 $this->oValidator->userHasPermissionOnItem($this->oUser, $this->_sEditShowPermission, $this->oFolder, $aOptions);
455 455 }
  456 +
  457 + $aFoo = $_REQUEST['foo'];
  458 + $aPermissions = KTPermission::getList();
  459 +
  460 + // Check which groups have permission to manage security
  461 + $aNewGroups = $aFoo[4]['group'];
  462 + $aNewRoles = (isset($aFoo[4]['role']) ? $aFoo[4]['role'] : array());
  463 +
  464 + // Ensure the user is not removing his/her own permission to update the folder permissions (manage security)
  465 + if(!in_array(-3, $aNewRoles)){
  466 + $iUserId = $this->oUser->getId();
  467 + if(!GroupUtil::checkUserInGroups($iUserId, $aNewGroups)){
  468 + // If user no longer has permission, return an error.
  469 + $this->addErrorMessage(_kt('The selected permissions cannot be updated. You will no longer have permission to manage security on this folder.'));
  470 + $this->redirectTo('edit', 'fFolderId=' . $this->oFolder->getId());
  471 + exit(0);
  472 + }
  473 + }
  474 +
  475 +
456 476 require_once(KT_LIB_DIR . '/documentmanagement/observers.inc.php');
457 477 $oPO = KTPermissionObject::get($this->oFolder->getPermissionObjectId());
458   - $aFoo = $_REQUEST['foo'];
459 478  
460   - $aPermissions = KTPermission::getList();
461 479 foreach ($aPermissions as $oPermission) {
462 480 $iPermId = $oPermission->getId();
463 481  
... ... @@ -471,11 +489,11 @@ class KTFolderPermissionsAction extends KTFolderAction {
471 489 'transactionNS' => 'ktcore.transactions.permissions_change',
472 490 'userid' => $_SESSION['userID'],
473 491 'ip' => Session::getClientIP(),
474   - ));
  492 + ));
475 493 $aOptions = array(
476 494 'defaultmessage' => _kt('Error updating permissions'),
477 495 'redirect_to' => array('edit', sprintf('fFolderId=%d', $this->oFolder->getId())),
478   - );
  496 + );
479 497 $this->oValidator->notErrorFalse($oTransaction, $aOptions);
480 498  
481 499 $po =& new JavascriptObserver($this);
... ...
plugins/ktstandard/ImmutableActionPlugin.php
... ... @@ -65,9 +65,17 @@ class KTDocumentImmutableAction extends KTDocumentAction {
65 65 }
66 66  
67 67 function do_main() {
68   - $this->oDocument->setImmutable(true);
69   - $this->oDocument->update();
70   - controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
  68 + if(!$this->oDocument->getIsCheckedOut())
  69 + {
  70 + $this->oDocument->setImmutable(true);
  71 + $this->oDocument->update();
  72 + controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
  73 + }
  74 + else
  75 + {
  76 + $this->addErrorMessage(_kt('Document is checked out and cannot be made immutable'));
  77 + controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId());
  78 + }
71 79 }
72 80 }
73 81  
... ...
resources/js/expungeList.js
... ... @@ -16,7 +16,7 @@ function buildList(value){
16 16  
17 17 function stateChanged(){
18 18 if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete"){
19   - document.getElementById("output").innerHTML=xmlHttp.responseText;
  19 + document.getElementById("tableoutput").innerHTML=xmlHttp.responseText;
20 20 }
21 21 }
22 22  
... ...
search2/search/fieldRegistry.inc.php
... ... @@ -259,8 +259,8 @@ class ExprFieldRegistry
259 259  
260 260 foreach($result as $record)
261 261 {
262   - $fieldset = $record['fieldset'];
263   - $field = $record['field'];
  262 + $fieldset = addslashes($record['fieldset']);
  263 + $field = addslashes($record['field']);
264 264 $fieldsetid = $record['fsid'];
265 265 $fieldid = $record['fid'];
266 266 $classname = "MetadataField$fieldid";
... ...
search2/search/search.inc.php
... ... @@ -96,7 +96,7 @@ class SearchHelper
96 96 {
97 97 if ($dt++ > 0) $documenttypes_str .= ',';
98 98 $id=$user['id'];
99   - $name=$user['name'];
  99 + $name=(addslashes($user['name']));
100 100  
101 101 $documenttypes_str .= "\n\t{id: \"$id\", name: \"$name\"}";
102 102 }
... ... @@ -139,7 +139,7 @@ class SearchHelper
139 139 {
140 140 if ($uo++ > 0) $users_str .= ',';
141 141 $id=$user['id'];
142   - $name=$user['name'];
  142 + $name=(addslashes($user['name']));
143 143  
144 144 $users_str .= "\n\t{id: \"$id\", name: \"$name\"}";
145 145 }
... ... @@ -159,8 +159,8 @@ class SearchHelper
159 159 foreach($fields as $field)
160 160 {
161 161 if ($fo++ > 0) $fields_str .= ',';
162   - $alias = $field['alias'];
163   - $display = $field['display'];
  162 + $alias = (addslashes($field['alias']));
  163 + $display = (addslashes($field['display']));
164 164 $type = $field['type'];
165 165 $fields_str .= "\n\t{alias: \"$alias\", name: \"$display\", type:\"$type\"}";
166 166 }
... ... @@ -182,7 +182,7 @@ class SearchHelper
182 182 {
183 183 if ($wo++ > 0) $workflow_str .= ',';
184 184 $wid = $workflow['id'];
185   - $name = $workflow['name'];
  185 + $name = (addslashes($workflow['name']));
186 186  
187 187 $workflow_str .= "\n\t{id:\"$wid\", name: \"$name\", states: [ ";
188 188  
... ... @@ -194,7 +194,7 @@ class SearchHelper
194 194 {
195 195 if ($so++>0) $workflow_str .= ',';
196 196 $sid = $state['id'];
197   - $name=$state['name'];
  197 + $name=(addslashes($state['name']));
198 198 $result['workflows'][$wid]['states'][$sid] = $state;
199 199 $workflow_str .= "\n\t\t{id:\"$wid\", name: \"$name\"}";
200 200 }
... ... @@ -217,8 +217,8 @@ class SearchHelper
217 217 foreach($fieldsets as $fieldset)
218 218 {
219 219 $fsid=$fieldset['id'];
220   - $name = $fieldset['name'];
221   - $desc = $fieldset['description'];
  220 + $name = (addslashes($fieldset['name']));
  221 + $desc = (addslashes($fieldset['description']));
222 222 if ($fso++>0) $fieldset_str .= ',';
223 223 $fieldset_str .= "\n\t{id:\"$fsid\",name:\"$name\",description:\"$desc\", fields: [";
224 224  
... ... @@ -231,8 +231,8 @@ class SearchHelper
231 231 {
232 232 if ($fo++ >0) $fieldset_str .= ',';
233 233 $fid = $field['id'];
234   - $name= $field['name'];
235   - $desc = $field['description'];
  234 + $name= (addslashes($field['name']));
  235 + $desc = (addslashes($field['description']));
236 236 $datatype=$field['datatype'];
237 237 $control=$field['control'];
238 238 $fieldset_str .= "\n\t\t{id:\"$fid\", name:\"$name\", description:\"$desc\", datatype:\"$datatype\", control:\"$control\", options: [";
... ... @@ -246,7 +246,7 @@ class SearchHelper
246 246 {
247 247 if ($oo++ > 0) $fieldset_str .= ',';
248 248 $oid = $option['id'];
249   - $name= $option['name'];
  249 + $name= (addslashes($option['name']));
250 250 $fieldset_str .= "\n\t\t\t{id: \"$oid\", name: \"$name\"}";
251 251 }
252 252 $fieldset_str .= ']}';
... ...
templates/ktcore/document/admin/deletedlist.smarty
... ... @@ -17,6 +17,7 @@ can &lt;strong&gt;restore&lt;/strong&gt; them as necessary.{/i18n}&lt;/p&gt;
17 17 {foreach item=oFDoc from=$fullList}
18 18 <input type="hidden" name="docIds[]" value="{$oFDoc->getId()}">
19 19 {/foreach}
  20 +<div id="tableoutput">
20 21 <table class="kt_collection">
21 22 <thead>
22 23 <tr>
... ... @@ -55,6 +56,7 @@ can &lt;strong&gt;restore&lt;/strong&gt; them as necessary.{/i18n}&lt;/p&gt;
55 56 </tr>
56 57 </tfoot>
57 58 </table>
  59 +</div>
58 60 <div class="form_actions">
59 61 <input type="submit" name="submit[expunge]" value="{i18n}Expunge{/i18n}" />
60 62 <input type="submit" name="submit[restore]" value="{i18n}Restore{/i18n}" />
... ...