Commit 66dca4c3a3a234d888e4cb277512314ad278025c

Authored by Jarrett Jordaan
2 parents aa6befdd 99ab04c8

Merge branch 'edge' of git@github.com:ktgit/knowledgetree into edge

lib/api/ktcmis/classes/CMISObject.inc.php
@@ -78,6 +78,9 @@ abstract class CMISObject { @@ -78,6 +78,9 @@ abstract class CMISObject {
78 78
79 public function __construct() 79 public function __construct()
80 { 80 {
  81 + // set properties shared by all objects of this type
  82 + $this->_setSharedProperties();
  83 +
81 // $propertyDef = new PropertyDefinition(); 84 // $propertyDef = new PropertyDefinition();
82 // $this->properties[] = $propertyDef; 85 // $this->properties[] = $propertyDef;
83 } 86 }
@@ -159,6 +162,16 @@ abstract class CMISObject { @@ -159,6 +162,16 @@ abstract class CMISObject {
159 { 162 {
160 // override in child classes 163 // override in child classes
161 } 164 }
  165 +
  166 + /**
  167 + * Sets properties which are shared between all objects of this type
  168 + */
  169 + protected function _setSharedProperties()
  170 + {
  171 + $this->_setPropertyInternal('objectTypeId', strtolower($this->getAttribute('id')));
  172 + // Needed to distinguish type
  173 + $this->_setPropertyInternal('baseTypeId', strtolower($this->getAttribute('id')));
  174 + }
162 175
163 } 176 }
164 177
lib/api/ktcmis/classes/AbstractEnum.inc.php renamed to lib/api/ktcmis/classes/Enum.inc.php
@@ -6,8 +6,9 @@ @@ -6,8 +6,9 @@
6 6
7 // TODO enable creation of enum instances on the fly - this will most likely be done in an extending class 7 // TODO enable creation of enum instances on the fly - this will most likely be done in an extending class
8 8
9 -abstract class AbstractEnum { 9 +abstract class Enum {
10 10
  11 + // actual implementation of these will be in child classes
11 static private $values; 12 static private $values;
12 static private $value; 13 static private $value;
13 static private $name; 14 static private $name;
lib/api/ktcmis/enums/EnumCapabilityACL.inc.php
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php')); 7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php'));
8 8
9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis'); 9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis');
10 -require_once(CMIS_DIR . '/classes/AbstractEnum.inc.php'); 10 +require_once(CMIS_DIR . '/classes/Enum.inc.php');
11 11
12 -class EnumCapabilityACL extends AbstractEnum { 12 +class EnumCapabilityACL extends Enum {
13 13
14 static private $values = array('none', 'discover', 'manage'); 14 static private $values = array('none', 'discover', 'manage');
15 static private $name = 'capabilityACL'; 15 static private $name = 'capabilityACL';
lib/api/ktcmis/enums/EnumCapabilityChanges.inc.php
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php')); 7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php'));
8 8
9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis'); 9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis');
10 -require_once(CMIS_DIR . '/classes/AbstractEnum.inc.php'); 10 +require_once(CMIS_DIR . '/classes/Enum.inc.php');
11 11
12 -class EnumCapabilityChanges extends AbstractEnum { 12 +class EnumCapabilityChanges extends Enum {
13 13
14 static private $values = array('none', 'objectidsonly', 'properties', 'all'); 14 static private $values = array('none', 'objectidsonly', 'properties', 'all');
15 static private $name = 'capabilityChanges'; 15 static private $name = 'capabilityChanges';
lib/api/ktcmis/enums/EnumCapabilityContentStreamUpdatability.inc.php
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php')); 7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php'));
8 8
9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis'); 9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis');
10 -require_once(CMIS_DIR . '/classes/AbstractEnum.inc.php'); 10 +require_once(CMIS_DIR . '/classes/Enum.inc.php');
11 11
12 -class EnumCapabilityContentStreamUpdatability extends AbstractEnum { 12 +class EnumCapabilityContentStreamUpdatability extends Enum {
13 13
14 static private $values = array('none', 'anytime', 'pwconly'); 14 static private $values = array('none', 'anytime', 'pwconly');
15 static private $name = 'capabilityContentStreamUpdatability'; 15 static private $name = 'capabilityContentStreamUpdatability';
lib/api/ktcmis/enums/EnumCapabilityJoin.inc.php
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php')); 7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php'));
8 8
9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis'); 9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis');
10 -require_once(CMIS_DIR . '/classes/AbstractEnum.inc.php'); 10 +require_once(CMIS_DIR . '/classes/Enum.inc.php');
11 11
12 -class EnumCapabilityJoin extends AbstractEnum { 12 +class EnumCapabilityJoin extends Enum {
13 13
14 static private $values = array('none', 'inneronly', 'innerandouter'); 14 static private $values = array('none', 'inneronly', 'innerandouter');
15 static private $name = 'capabilityJoin'; 15 static private $name = 'capabilityJoin';
lib/api/ktcmis/enums/EnumCapabilityQuery.inc.php
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php')); 7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php'));
8 8
9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis'); 9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis');
10 -require_once(CMIS_DIR . '/classes/AbstractEnum.inc.php'); 10 +require_once(CMIS_DIR . '/classes/Enum.inc.php');
11 11
12 -class EnumCapabilityQuery extends AbstractEnum { 12 +class EnumCapabilityQuery extends Enum {
13 13
14 static private $values = array('none', 'metadataonly', 'fulltextonly', 'bothseparate', 'bothcombined'); 14 static private $values = array('none', 'metadataonly', 'fulltextonly', 'bothseparate', 'bothcombined');
15 static private $name = 'capabilityQuery'; 15 static private $name = 'capabilityQuery';
lib/api/ktcmis/enums/EnumCapabilityRenditions.inc.php
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php')); 7 require_once(realpath(dirname(__FILE__) . '/../../../../config/dmsDefaults.php'));
8 8
9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis'); 9 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis');
10 -require_once(CMIS_DIR . '/classes/AbstractEnum.inc.php'); 10 +require_once(CMIS_DIR . '/classes/Enum.inc.php');
11 11
12 -class EnumCapabilityRenditions extends AbstractEnum { 12 +class EnumCapabilityRenditions extends Enum {
13 13
14 static private $values = array('none', 'objectidsonly', 'properties', 'all'); 14 static private $values = array('none', 'objectidsonly', 'properties', 'all');
15 static private $name = 'capabilityRenditions'; 15 static private $name = 'capabilityRenditions';
lib/api/ktcmis/ktNavigationService.inc.php
@@ -137,7 +137,7 @@ class KTNavigationService extends KTCMISBase { @@ -137,7 +137,7 @@ class KTNavigationService extends KTCMISBase {
137 { 137 {
138 return array( 138 return array(
139 "status_code" => 1, 139 "status_code" => 1,
140 - "message" => "Failed getting descendants for folder" 140 + "message" => "Failed getting children for folder"
141 ); 141 );
142 } 142 }
143 143
@@ -154,38 +154,32 @@ class KTNavigationService extends KTCMISBase { @@ -154,38 +154,32 @@ class KTNavigationService extends KTCMISBase {
154 * 154 *
155 * @param string $repositoryId 155 * @param string $repositoryId
156 * @param string $folderId 156 * @param string $folderId
157 - * @param boolean $includeAllowableActions  
158 - * @param boolean $includeRelationships  
159 - * @param boolean $returnToRoot  
160 * @param string $filter 157 * @param string $filter
161 - * @return ancestry[] 158 + * @return parent[]
162 */ 159 */
163 - public function getFolderParent($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, $returnToRoot, $filter = '') 160 + public function getFolderParent($repositoryId, $folderId, $filter = '')
164 { 161 {
165 try { 162 try {
166 - $ancestryResult = $this->NavigationService->getFolderParent($repositoryId, $folderId, $includeAllowableActions,  
167 - $includeRelationships, $returnToRoot); 163 + $parent = $this->NavigationService->getFolderParent($repositoryId, $folderId, $filter);
168 } 164 }
169 catch (Exception $e) { 165 catch (Exception $e) {
170 return array( 166 return array(
171 "status_code" => 1, 167 "status_code" => 1,
172 - "message" => "Failed getting ancestry for folder: " . $e->getMessage() 168 + "message" => "Failed getting folder parent: " . $e->getMessage()
173 ); 169 );
174 } 170 }
175 171
176 - if (PEAR::isError($ancestryResult)) 172 + if (PEAR::isError($parent))
177 { 173 {
178 return array( 174 return array(
179 "status_code" => 1, 175 "status_code" => 1,
180 - "message" => "Failed getting ancestry for folder" 176 + "message" => "Failed getting folder parent"
181 ); 177 );
182 } 178 }
183 179
184 - $ancestry = CMISUtil::decodeObjectHierarchy($ancestryResult, 'children');  
185 -  
186 return array( 180 return array(
187 "status_code" => 0, 181 "status_code" => 0,
188 - "results" => $ancestry 182 + "results" => CMISUtil::createObjectPropertiesEntry($parent->getProperties())
189 ); 183 );
190 } 184 }
191 185
@@ -201,10 +195,18 @@ class KTNavigationService extends KTCMISBase { @@ -201,10 +195,18 @@ class KTNavigationService extends KTCMISBase {
201 */ 195 */
202 function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '') 196 function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '')
203 { 197 {
204 - $ancestryResult = $this->NavigationService->getObjectParents($repositoryId, $objectId, $includeAllowableActions,  
205 - $includeRelationships); 198 + try {
  199 + $ancestry = $this->NavigationService->getObjectParents($repositoryId, $objectId, $includeAllowableActions,
  200 + $includeRelationships);
  201 + }
  202 + catch (Exception $e) {
  203 + return array(
  204 + "status_code" => 1,
  205 + "message" => $e->getMessage()
  206 + );
  207 + }
206 208
207 - if (PEAR::isError($ancestryResult)) 209 + if (PEAR::isError($ancestry))
208 { 210 {
209 return array( 211 return array(
210 "status_code" => 1, 212 "status_code" => 1,
@@ -212,8 +214,6 @@ class KTNavigationService extends KTCMISBase { @@ -212,8 +214,6 @@ class KTNavigationService extends KTCMISBase {
212 ); 214 );
213 } 215 }
214 216
215 - $ancestry = CMISUtil::decodeObjectHierarchy($ancestryResult, 'children');  
216 -  
217 return array( 217 return array(
218 "status_code" => 0, 218 "status_code" => 0,
219 "results" => $ancestry 219 "results" => $ancestry
@@ -225,18 +225,27 @@ class KTNavigationService extends KTCMISBase { @@ -225,18 +225,27 @@ class KTNavigationService extends KTCMISBase {
225 * 225 *
226 * @param string $repositoryId 226 * @param string $repositoryId
227 * @param string $folderId The folder for which checked out docs are requested 227 * @param string $folderId The folder for which checked out docs are requested
228 - * @param string $filter  
229 - * @param boolean $includeAllowableActions  
230 - * @param boolean $includeRelationships  
231 * @param int $maxItems 228 * @param int $maxItems
232 * @param int $skipCount 229 * @param int $skipCount
233 - * @return array $checkedout The collection of checked out documents 230 + * @param string $filter
  231 + * @param enum $includeRelationships
  232 + * @param boolean $includeAllowableActions
  233 + * @param string $renditionFilter
  234 + * @return array $checkedout The collection of checked out document objects
  235 + * MUST include (unless not requested) for each object:
  236 + * array $properties
  237 + * array $relationships
  238 + * array $renditions
  239 + * $allowableActions
  240 + * @return boolean $hasMoreItems
  241 + * @return int $numItems [optional]
234 */ 242 */
235 - function getCheckedOutDocs($repositoryId, $includeAllowableActions, $includeRelationships, $folderId = null, $filter = '',  
236 - $maxItems = 0, $skipCount = 0) 243 + function getCheckedOutDocs($repositoryId, $folderId = null, $maxItems = 0, $skipCount = 0, $orderBy = '',
  244 + $filter = '', $includeRelationships = null, $includeAllowableActions = false, $renditionFilter = '')
237 { 245 {
238 - $checkedout = $this->NavigationService->getCheckedOutDocs($repositoryId, $includeAllowableActions, $includeRelationships,  
239 - $folderId, $filter, $maxItems, $skipCount); 246 + $checkedout = $this->NavigationService->getCheckedOutDocs($repositoryId, $folderId = null, $maxItems = 0, $skipCount = 0,
  247 + $orderBy, $filter, $includeRelationships, $includeAllowableActions,
  248 + $renditionFilter);
240 249
241 if (PEAR::isError($checkedout)) 250 if (PEAR::isError($checkedout))
242 { 251 {
lib/api/ktcmis/ktRepositoryService.inc.php
@@ -165,25 +165,14 @@ class KTRepositoryService extends KTCMISBase { @@ -165,25 +165,14 @@ class KTRepositoryService extends KTCMISBase {
165 public function getTypeDefinition($repositoryId, $typeId) 165 public function getTypeDefinition($repositoryId, $typeId)
166 { 166 {
167 try { 167 try {
168 - $typeDefinitionResult = $this->RepositoryService->getTypeDefinition($repositoryId, $typeId); 168 + $typeDefinition = $this->RepositoryService->getTypeDefinition($repositoryId, $typeId);
169 } 169 }
170 - catch (Exception $e)  
171 - {  
172 - return array(  
173 - "status_code" => 1,  
174 - "message" => $e->getMessage()  
175 - ); 170 + catch (Exception $e) {
  171 + // propogate upward
  172 + throw $e;
176 } 173 }
177 -  
178 - // format as array style output  
179 - // NOTE only concerned with attributes at this time  
180 - // TODO add support for properties  
181 - $typeDefinition = $typeDefinitionResult['attributes'];  
182 -  
183 - return array (  
184 - "status_code" => 0,  
185 - "results" => $typeDefinition  
186 - ); 174 +
  175 + return $typeDefinition;
187 } 176 }
188 177
189 } 178 }
lib/api/ktcmis/ktService.inc.php
@@ -48,7 +48,6 @@ require_once(realpath(dirname(__FILE__) . '/../../../config/dmsDefaults.php')); @@ -48,7 +48,6 @@ require_once(realpath(dirname(__FILE__) . '/../../../config/dmsDefaults.php'));
48 require_once(KT_DIR . '/ktapi/ktapi.inc.php'); 48 require_once(KT_DIR . '/ktapi/ktapi.inc.php');
49 49
50 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis'); 50 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis');
51 -require_once(CMIS_DIR . '/exceptions/PermissionDeniedException.inc.php');  
52 require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); 51 require_once(CMIS_DIR . '/util/CMISUtil.inc.php');
53 52
54 /** 53 /**
lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
@@ -98,7 +98,7 @@ class CMISDocumentObject extends CMISObject { @@ -98,7 +98,7 @@ class CMISDocumentObject extends CMISObject {
98 } 98 }
99 } 99 }
100 100
101 - // TODO throw exception if unable to create? 101 + parent::__construct();
102 } 102 }
103 103
104 // TODO abstract shared stuff to base class where possible 104 // TODO abstract shared stuff to base class where possible
@@ -124,10 +124,6 @@ class CMISDocumentObject extends CMISObject { @@ -124,10 +124,6 @@ class CMISDocumentObject extends CMISObject {
124 // also ktapidocument::get_download_url 124 // also ktapidocument::get_download_url
125 // $this->_setPropertyInternal('uri', $uri); 125 // $this->_setPropertyInternal('uri', $uri);
126 $this->_setPropertyInternal('uri', ''); 126 $this->_setPropertyInternal('uri', '');
127 - // TODO what is this? Assuming it is the object type id, and not OUR document type?  
128 - $this->_setPropertyInternal('objectTypeId', strtolower($this->getAttribute('id')));  
129 - // Needed to distinguish type  
130 - $this->_setPropertyInternal('baseTypeId', strtolower($this->getAttribute('id')));  
131 $this->_setPropertyInternal('createdBy', $objectProperties['created_by']); 127 $this->_setPropertyInternal('createdBy', $objectProperties['created_by']);
132 $this->_setPropertyInternal('creationDate', $objectProperties['created_date']); 128 $this->_setPropertyInternal('creationDate', $objectProperties['created_date']);
133 $this->_setPropertyInternal('lastModifiedBy', $objectProperties['modified_by']); 129 $this->_setPropertyInternal('lastModifiedBy', $objectProperties['modified_by']);
lib/api/ktcmis/objecttypes/CMISFolderObject.inc.php
@@ -85,6 +85,8 @@ class CMISFolderObject extends CMISObject { @@ -85,6 +85,8 @@ class CMISFolderObject extends CMISObject {
85 throw new ObjectNotFoundException($e->getMessage()); 85 throw new ObjectNotFoundException($e->getMessage());
86 } 86 }
87 } 87 }
  88 +
  89 + parent::__construct();
88 } 90 }
89 91
90 // TODO abstract shared stuff to base class where possible 92 // TODO abstract shared stuff to base class where possible
@@ -111,10 +113,6 @@ class CMISFolderObject extends CMISObject { @@ -111,10 +113,6 @@ class CMISFolderObject extends CMISObject {
111 // TODO this url is probably incorrect...needs to be checked 113 // TODO this url is probably incorrect...needs to be checked
112 // $this->_setPropertyInternal('uri', $uri); 114 // $this->_setPropertyInternal('uri', $uri);
113 $this->_setPropertyInternal('uri', ''); 115 $this->_setPropertyInternal('uri', '');
114 - // TODO what is this? Assuming it is the object type id, and not OUR document type?  
115 - $this->_setPropertyInternal('objectTypeId', strtolower($this->getAttribute('id')));  
116 - // Needed to distinguish type  
117 - $this->_setPropertyInternal('baseTypeId', strtolower($this->getAttribute('id')));  
118 $this->_setPropertyInternal('createdBy', $objectProperties['created_by']); 116 $this->_setPropertyInternal('createdBy', $objectProperties['created_by']);
119 // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by 117 // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by
120 $this->_setPropertyInternal('creationDate', $objectProperties['created_date']); 118 $this->_setPropertyInternal('creationDate', $objectProperties['created_date']);
@@ -125,9 +123,17 @@ class CMISFolderObject extends CMISObject { @@ -125,9 +123,17 @@ class CMISFolderObject extends CMISObject {
125 $this->_setPropertyInternal('changeToken', null); 123 $this->_setPropertyInternal('changeToken', null);
126 $this->_setPropertyInternal('name', $objectProperties['folder_name']); 124 $this->_setPropertyInternal('name', $objectProperties['folder_name']);
127 $this->_setPropertyInternal('parentId', CMISUtil::encodeObjectId(FOLDER, $objectProperties['parent_id'])); 125 $this->_setPropertyInternal('parentId', CMISUtil::encodeObjectId(FOLDER, $objectProperties['parent_id']));
128 - $this->_setPropertyInternal('allowedChildObjectTypeIds', array('cmis:document', 'cmis:folder'));  
129 $this->_setPropertyInternal('author', $objectProperties['created_by']); 126 $this->_setPropertyInternal('author', $objectProperties['created_by']);
130 } 127 }
  128 +
  129 + /**
  130 + * Sets properties shared between all objects of this type
  131 + */
  132 + protected function _setSharedProperties()
  133 + {
  134 + parent::_setSharedProperties();
  135 + $this->_setPropertyInternal('allowedChildObjectTypeIds', array('cmis:document', 'cmis:folder'));
  136 + }
131 137
132 } 138 }
133 139
lib/api/ktcmis/services/CMISNavigationService.inc.php
@@ -87,8 +87,8 @@ class CMISNavigationService { @@ -87,8 +87,8 @@ class CMISNavigationService {
87 // Otherwise, the latest version of the documents SHALL be returned. 87 // Otherwise, the latest version of the documents SHALL be returned.
88 // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid 88 // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid
89 function getChildren($repositoryId, $folderId, $includeAllowableActions = null, $includeRelationships = null, 89 function getChildren($repositoryId, $folderId, $includeAllowableActions = null, $includeRelationships = null,
90 - $typeId = 'Any', $filter = '', $maxItems = 0, $skipCount = 0, $orderBy = '', $renditionFilter = null,  
91 - $includePathSegment = false) 90 + $typeId = 'Any', $filter = '', $maxItems = 0, $skipCount = 0, $orderBy = '', $renditionFilter = null,
  91 + $includePathSegment = false)
92 { 92 {
93 // TODO paging 93 // TODO paging
94 // TODO optional parameters 94 // TODO optional parameters
@@ -134,13 +134,13 @@ class CMISNavigationService { @@ -134,13 +134,13 @@ class CMISNavigationService {
134 // NOTE If the Repository supports the optional โ€œVersionSpecificFiling๏ฟฝ๏ฟฝ? capability, 134 // NOTE If the Repository supports the optional โ€œVersionSpecificFiling๏ฟฝ๏ฟฝ? capability,
135 // then the repository SHALL return the document versions filed in the specified folder or its descendant folders. 135 // then the repository SHALL return the document versions filed in the specified folder or its descendant folders.
136 // Otherwise, the latest version of the documents SHALL be returned. 136 // Otherwise, the latest version of the documents SHALL be returned.
137 - // NOTE If the Repository supports the optional capability capabilityMutlifiling and the same document is encountered 137 + // NOTE If the Repository supports the optional capability capabilityMutlifiling and the same document is encountered
138 // multiple times in the hierarchy, then the repository MUST return that document each time is encountered. 138 // multiple times in the hierarchy, then the repository MUST return that document each time is encountered.
139 // NOTE The default value for the $depth parameter is repository specific and SHOULD be at least 2 or -1 139 // NOTE The default value for the $depth parameter is repository specific and SHOULD be at least 2 or -1
140 // Chosen 2 as the underlying code currently has no concept of digging all the way down 140 // Chosen 2 as the underlying code currently has no concept of digging all the way down
141 // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid 141 // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid
142 - function getDescendants($repositoryId, $folderId, $depth = 2, $filter = '', $includeRelationships = false, $renditionFilter = '',  
143 - $includeAllowableActions = false, $includePathSegment = false) 142 + function getDescendants($repositoryId, $folderId, $depth = 2, $filter = '', $includeRelationships = false, $renditionFilter = '',
  143 + $includeAllowableActions = false, $includePathSegment = false)
144 { 144 {
145 if ($depth == 0) { 145 if ($depth == 0) {
146 throw new InvalidArgumentException('Invalid depth argument supplied'); 146 throw new InvalidArgumentException('Invalid depth argument supplied');
@@ -148,11 +148,11 @@ class CMISNavigationService { @@ -148,11 +148,11 @@ class CMISNavigationService {
148 148
149 // if this is not a folder, cannot get descendants 149 // if this is not a folder, cannot get descendants
150 $folderId = CMISUtil::decodeObjectId($folderId, $type); 150 $folderId = CMISUtil::decodeObjectId($folderId, $type);
151 - 151 +
152 if ($type != 'cmis:folder') { 152 if ($type != 'cmis:folder') {
153 throw new InvalidArgumentException('The supplied object is not a folder, unable to return descendants'); 153 throw new InvalidArgumentException('The supplied object is not a folder, unable to return descendants');
154 } 154 }
155 - 155 +
156 // TODO optional parameters 156 // TODO optional parameters
157 $descendants = array(); 157 $descendants = array();
158 $repository = new CMISRepository($repositoryId); 158 $repository = new CMISRepository($repositoryId);
@@ -171,105 +171,102 @@ class CMISNavigationService { @@ -171,105 +171,102 @@ class CMISNavigationService {
171 * 171 *
172 * @param string $repositoryId 172 * @param string $repositoryId
173 * @param string $folderId 173 * @param string $folderId
174 - * @param boolean $includeAllowableActions  
175 - * @param boolean $includeRelationships  
176 - * @param boolean $returnToRoot If TRUE, then the repository SHALL return all folder objects  
177 - * that are ancestors of the specified folder.  
178 - * If FALSE, the repository SHALL return only the parent folder of the specified folder.  
179 * @param string $filter 174 * @param string $filter
180 - * @return array $ancestry 175 + * @return object $parent The parent folder object
181 */ 176 */
182 // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid 177 // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid
183 - // TODO If this service method is invoked on the root folder of the Repository, then the Repository SHALL return an empty result set.  
184 - // NOTE SHOULD always include the โ€œObjectId๏ฟฝ๏ฟฝ? and โ€œParentId๏ฟฝ๏ฟฝ? properties for all objects returned  
185 - function getFolderParent($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, $returnToRoot, $filter = '') 178 + function getFolderParent($repositoryId, $folderId, $filter = '')
186 { 179 {
187 // NOTE the root folder obviously has no parent, throw an ObjectNotFoundException here if this is the root folder 180 // NOTE the root folder obviously has no parent, throw an ObjectNotFoundException here if this is the root folder
188 if (CMISUtil::isRootFolder($repositoryId, $folderId, $this->ktapi)) { 181 if (CMISUtil::isRootFolder($repositoryId, $folderId, $this->ktapi)) {
189 - throw new ObjectNotFoundException('Root folder has no parent'); 182 + throw new InvalidArgumentException('Root folder has no parent');
190 } 183 }
191 -  
192 - $ancestry = array();  
193 - $repository = new CMISRepository($repositoryId); 184 +
  185 + $parent = null;
194 186
195 // if this is not a folder, cannot get folder parent :) 187 // if this is not a folder, cannot get folder parent :)
196 $folderId = CMISUtil::decodeObjectId($folderId, $type); 188 $folderId = CMISUtil::decodeObjectId($folderId, $type);
197 - // NOTE this will quite possibly break the webservices  
198 - if ($type != 'cmis:folder')  
199 - {  
200 - return $ancestry; 189 + // this exception is not indicated in the CMIS Specification, but it just makes sense and so we include it here
  190 + if ($type != 'cmis:folder') {
  191 + throw new InvalidArgumentException('The specified object is not a folder');
201 } 192 }
202 193
203 $ktapiFolder = $this->ktapi->get_folder_by_id($folderId); 194 $ktapiFolder = $this->ktapi->get_folder_by_id($folderId);
204 -  
205 - if ($returnToRoot)  
206 - {  
207 - $folder = $ktapiFolder->get_folder();  
208 - $parents = $folder->generateFolderIDs($folderId);  
209 - // remove the id of the requesting folder and convert to array  
210 - $ancestry = explode(',', str_replace(','.$folderId, '', $parents));  
211 - // reverse to get bottom up listing? don't think so with the current implementation  
212 - // specifying that objectTypes may have children but do not have parents listed.  
213 -// $ancestry = array_reverse($ancestry);  
214 - }  
215 - else  
216 - {  
217 - $parent = $ktapiFolder->get_parent_folder_id();  
218 - $ancestry[] = $parent; 195 + if (PEAR::isError($ktapiFolder)) {
  196 + throw new RuntimeException($ktapiFolder->getMessage());
219 } 197 }
220 198
221 - // need some info about the parent(s) in order to correctly create the hierarchy  
222 - $tmpArray = array();  
223 - foreach ($ancestry as $key => $ancestor)  
224 - {  
225 - $tmpArray[$key] = $this->ktapi->get_folder_by_id($ancestor);  
226 - }  
227 - $ancestry = $tmpArray;  
228 - unset($tmpArray);  
229 -  
230 - $ancestry = CMISUtil::createParentObjectHierarchy($ancestry, $repository->getRepositoryURI, $this->ktapi);  
231 -  
232 - return $ancestry; 199 + $parentId = $ktapiFolder->get_parent_folder_id();
  200 + $parent = new CMISFolderObject(CMISUtil::encodeObjectId($parentId, FOLDER), $this->ktapi);
  201 +
  202 + return $parent;
233 } 203 }
234 204
235 /** 205 /**
236 - * Fetches the parent(s) of the specified object 206 + * Gets the parent folder(s) for the specified non-folder, fileable object.
237 * Multiple parents may exist if a repository supports multi-filing 207 * Multiple parents may exist if a repository supports multi-filing
238 * It is also possible that linked documents/folders may qualify as having multiple parents 208 * It is also possible that linked documents/folders may qualify as having multiple parents
239 * as they are essentially the same object 209 * as they are essentially the same object
240 * 210 *
241 * @param string $repositoryId 211 * @param string $repositoryId
242 * @param string $objectId 212 * @param string $objectId
243 - * @param boolean $includeAllowableActions  
244 - * @param boolean $includeRelationships  
245 - * @param string $filter  
246 - * @return array $parents 213 + * @param string $filter [optional]
  214 + * @param enum $includeRelationships [optional]
  215 + * @param string $renditionFilter [optional]
  216 + * @param boolean $includeAllowableActions [optional]
  217 + * @param boolean $includeRelativePathSegment [optional]
  218 + * @return array $parents - empty for unfiled objects or the root folder
  219 + * MUST include (unless not requested) for each object:
  220 + * array $properties
  221 + * array $relationships
  222 + * array $renditions
  223 + * $allowableActions
  224 + * string $relativePathSegment
247 */ 225 */
248 - // TODO ConstraintViolationException: The Repository SHALL throw this exception if this method is invoked  
249 - // on an object who Object-Type Definition specifies that it is not fileable.  
250 - // FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid.  
251 - function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '') 226 + // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid.
  227 + function getObjectParents($repositoryId, $objectId, $filter = '', $includeRelationships = null, $renditionFilter = '',
  228 + $includeAllowableActions = false, $includeRelativePathSegment = false)
252 { 229 {
253 $ancestry = array(); 230 $ancestry = array();
254 231
255 $objectId = CMISUtil::decodeObjectId($objectId, $typeId); 232 $objectId = CMISUtil::decodeObjectId($objectId, $typeId);
  233 +
  234 + // if type is a folder, this function does not apply
  235 + if ($typeId == 'cmis:folder') {
  236 + throw new InvalidArgumentException('Cannot call this function for a folder object');
  237 + }
  238 +
  239 + $objectTypeId = ucwords(str_replace('cmis:', '', $typeId));
  240 + $object = 'CMIS' . $objectTypeId . 'Object';
  241 +
  242 + if (!file_exists(CMIS_DIR . '/objecttypes/' . $object . '.inc.php')) {
  243 + throw new InvalidArgumentException('Type ' . $typeId . ' is not supported');
  244 + }
  245 +
  246 + require_once(CMIS_DIR . '/objecttypes/' . $object . '.inc.php');
  247 + $cmisObject = new $object;
  248 +
  249 + if (!$cmisObject->getAttribute('fileable')) {
  250 + throw new ConstraintViolationException('Unable to get parents of non-filable object');
  251 + }
256 252
257 // TODO - what about other types? only implementing folders and documents at the moment so ignore for now 253 // TODO - what about other types? only implementing folders and documents at the moment so ignore for now
  254 + // NOTE this will change if we implement multi-filing and/or unfiling
258 switch($typeId) 255 switch($typeId)
259 { 256 {
260 case 'cmis:document': 257 case 'cmis:document':
261 $document = $this->ktapi->get_document_by_id($objectId); 258 $document = $this->ktapi->get_document_by_id($objectId);
262 - $parent = $document->ktapi_folder;  
263 - $ancestry[] = $parent;  
264 - break;  
265 - case 'cmis:folder':  
266 - $folder = $this->ktapi->get_folder_by_id($objectId);  
267 - $parent = $this->ktapi->get_folder_by_id($folder->get_parent_folder_id());  
268 - $ancestry[] = $parent;  
269 - break; 259 + if ($document->is_deleted()) {
  260 + throw new InvalidArgumentException('The requested object has been deleted');
  261 + }
  262 + $ancestry[] = $document->ktapi_folder->get_folderid();
  263 + break;
  264 + }
  265 +
  266 + foreach ($ancestry as $key => $parentId) {
  267 + $CMISObject = new CMISFolderObject($parentId, $this->ktapi, $repositoryURI);
  268 + $ancestry[$key] = CMISUtil::createObjectPropertiesEntry($CMISObject->getProperties());
270 } 269 }
271 -  
272 - $ancestry = CMISUtil::createParentObjectHierarchy($ancestry, $repository->getRepositoryURI, $this->ktapi);  
273 270
274 return $ancestry; 271 return $ancestry;
275 } 272 }
@@ -279,18 +276,25 @@ class CMISNavigationService { @@ -279,18 +276,25 @@ class CMISNavigationService {
279 * 276 *
280 * @param string $repositoryId 277 * @param string $repositoryId
281 * @param string $folderId The folder for which checked out docs are requested 278 * @param string $folderId The folder for which checked out docs are requested
282 - * @param string $filter  
283 - * @param boolean $includeAllowableActions  
284 - * @param boolean $includeRelationships  
285 * @param int $maxItems 279 * @param int $maxItems
286 * @param int $skipCount 280 * @param int $skipCount
  281 + * @param string $filter
  282 + * @param enum $includeRelationships
  283 + * @param boolean $includeAllowableActions
  284 + * @param string $renditionFilter
287 * @return array $checkedout The collection of checked out document objects 285 * @return array $checkedout The collection of checked out document objects
  286 + * MUST include (unless not requested) for each object:
  287 + * array $properties
  288 + * array $relationships
  289 + * array $renditions
  290 + * $allowableActions
  291 + * @return boolean $hasMoreItems
  292 + * @return int $numItems [optional]
288 */ 293 */
289 // TODO exceptions: โ€ข FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid. 294 // TODO exceptions: โ€ข FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid.
290 - // TODO filter by folder id  
291 // TODO $filter and paging 295 // TODO $filter and paging
292 - function getCheckedOutDocs($repositoryId, $folderId = null, $filter = '', $includeAllowableActions = false, $includeRelationships = null,  
293 - $maxItems = 0, $skipCount = 0, $orderBy = '') 296 + function getCheckedOutDocs($repositoryId, $folderId = null, $maxItems = 0, $skipCount = 0, $orderBy = '',
  297 + $filter = '', $includeRelationships = null, $includeAllowableActions = false, $renditionFilter = '')
294 { 298 {
295 $checkedout = array(); 299 $checkedout = array();
296 300
lib/api/ktcmis/services/CMISRepositoryService.inc.php
@@ -101,9 +101,12 @@ class CMISRepositoryService { @@ -101,9 +101,12 @@ class CMISRepositoryService {
101 * @param boolean $hasMoreItems TRUE if there are more items to return than were requested 101 * @param boolean $hasMoreItems TRUE if there are more items to return than were requested
102 * @return array $objectTypes 102 * @return array $objectTypes
103 */ 103 */
104 - // NOTE this code may fit better within the Repository Class  
105 // TODO return for specific type when $typeId is specified 104 // TODO return for specific type when $typeId is specified
106 // TODO other optional parameters 105 // TODO other optional parameters
  106 + // This code is superseded by getTypeChildren and getTypeDescendants - when implementing those, check
  107 + // whether it is possible to entirely remove this function or if it is to remain and be shared by the
  108 + // other two functions (when no type is specified they will return base types [children] amd all types
  109 + // [descendants] respectively
107 public function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, 110 public function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false,
108 $maxItems = 0, $skipCount = 0, &$hasMoreItems = false) 111 $maxItems = 0, $skipCount = 0, &$hasMoreItems = false)
109 { 112 {
@@ -160,13 +163,15 @@ class CMISRepositoryService { @@ -160,13 +163,15 @@ class CMISRepositoryService {
160 // NOTE this code may fit better in the Repository Class 163 // NOTE this code may fit better in the Repository Class
161 function getTypeDefinition($repositoryId, $typeId) 164 function getTypeDefinition($repositoryId, $typeId)
162 { 165 {
  166 + global $default;
  167 + $default->log->debug();
  168 + $default->log->info(str_replace('cmis:', '', $typeId));
163 $typeId = ucwords(str_replace('cmis:', '', $typeId)); 169 $typeId = ucwords(str_replace('cmis:', '', $typeId));
164 $object = 'CMIS' . $typeId . 'Object'; 170 $object = 'CMIS' . $typeId . 'Object';
165 171
166 // check whether the object type exists, return error if not 172 // check whether the object type exists, return error if not
167 // consider throwing an exception instead (see General Exceptions) 173 // consider throwing an exception instead (see General Exceptions)
168 - if (!file_exists(CMIS_DIR . '/objecttypes/' . $object . '.inc.php'))  
169 - { 174 + if (!file_exists(CMIS_DIR . '/objecttypes/' . $object . '.inc.php')) {
170 throw new InvalidArgumentException('Type ' . $typeId . ' is not supported'); 175 throw new InvalidArgumentException('Type ' . $typeId . ' is not supported');
171 } 176 }
172 177
@@ -174,8 +179,11 @@ class CMISRepositoryService { @@ -174,8 +179,11 @@ class CMISRepositoryService {
174 179
175 require_once(CMIS_DIR . '/objecttypes/' . $object . '.inc.php'); 180 require_once(CMIS_DIR . '/objecttypes/' . $object . '.inc.php');
176 $cmisObject = new $object; 181 $cmisObject = new $object;
177 - $typeDefinition['attributes'] = $cmisObject->getAttributes();  
178 - $typeDefinition['properties'] = $cmisObject->getProperties(); 182 +
  183 + // NOTE The specification is ambigous here: it states that this function must return the type properties, but
  184 + // the atompub example shows the type attributes, not properties; since most properties are only populated
  185 + // on creation of an instance of an object-type, we choose to go with the attributes and not the properties
  186 + $typeDefinition = $cmisObject->getAttributes();
179 187
180 return $typeDefinition; 188 return $typeDefinition;
181 } 189 }
lib/api/ktcmis/util/CMISUtil.inc.php
@@ -104,7 +104,7 @@ class CMISUtil { @@ -104,7 +104,7 @@ class CMISUtil {
104 $typeId = 'unknown'; 104 $typeId = 'unknown';
105 return null; 105 return null;
106 } 106 }
107 - 107 +
108 $typeId = null; 108 $typeId = null;
109 109
110 // NOTE Not sure whether this really belongs here, but probably this is the safest and most reliable place 110 // NOTE Not sure whether this really belongs here, but probably this is the safest and most reliable place
@@ -124,6 +124,7 @@ class CMISUtil { @@ -124,6 +124,7 @@ class CMISUtil {
124 // meantime this minor hack will get things working for the existing system structure, as the root 124 // meantime this minor hack will get things working for the existing system structure, as the root
125 // folder should always be id 1. 125 // folder should always be id 1.
126 $typeId = 'cmis:folder'; 126 $typeId = 'cmis:folder';
  127 + $className = 'Folder';
127 return '1'; 128 return '1';
128 } 129 }
129 130
@@ -180,9 +181,9 @@ class CMISUtil { @@ -180,9 +181,9 @@ class CMISUtil {
180 $CMISObject = new CMISFolderObject($object['id'], $ktapi, $repositoryURI); 181 $CMISObject = new CMISFolderObject($object['id'], $ktapi, $repositoryURI);
181 break; 182 break;
182 } 183 }
183 - 184 +
184 $CMISArray[$count]['object'] = $CMISObject; 185 $CMISArray[$count]['object'] = $CMISObject;
185 - 186 +
186 // if sub-array 187 // if sub-array
187 if (count($object['items']) > 0) { 188 if (count($object['items']) > 0) {
188 $CMISArray[$count]['children'] = self::createChildObjectHierarchy($object['items'], $repositoryURI, $ktapi); 189 $CMISArray[$count]['children'] = self::createChildObjectHierarchy($object['items'], $repositoryURI, $ktapi);
@@ -192,7 +193,7 @@ class CMISUtil { @@ -192,7 +193,7 @@ class CMISUtil {
192 { 193 {
193 // NOTE why is this necessary? That's what you get for not commenting it at the time 194 // NOTE why is this necessary? That's what you get for not commenting it at the time
194 // TODO comment this properly, once we know why it is happening 195 // TODO comment this properly, once we know why it is happening
195 -// $CMISArray[$count] = self::createChildObjectHierarchy($object, $repositoryURI, $ktapi); 196 + // $CMISArray[$count] = self::createChildObjectHierarchy($object, $repositoryURI, $ktapi);
196 } 197 }
197 } 198 }
198 } 199 }
@@ -212,6 +213,7 @@ class CMISUtil { @@ -212,6 +213,7 @@ class CMISUtil {
212 * @return array $CMISArray 213 * @return array $CMISArray
213 */ 214 */
214 // NOTE this will have to change if we implement multi-filing 215 // NOTE this will have to change if we implement multi-filing
  216 + // NOTE this function probably serves no purpose, the parents are to be returned as a flat array
215 static public function createParentObjectHierarchy($input, $repositoryURI, &$ktapi) 217 static public function createParentObjectHierarchy($input, $repositoryURI, &$ktapi)
216 { 218 {
217 $CMISArray = array(); 219 $CMISArray = array();
@@ -251,14 +253,14 @@ class CMISUtil { @@ -251,14 +253,14 @@ class CMISUtil {
251 static public function decodeObjectHierarchy($input, $linkText = 'children') 253 static public function decodeObjectHierarchy($input, $linkText = 'children')
252 { 254 {
253 $hierarchy = array(); 255 $hierarchy = array();
254 - 256 +
255 // first, run through the base array to get the initial children 257 // first, run through the base array to get the initial children
256 foreach ($input as $key => $entry) 258 foreach ($input as $key => $entry)
257 { 259 {
258 $object = $entry['object']; 260 $object = $entry['object'];
259 $properties = $object->getProperties(); 261 $properties = $object->getProperties();
260 $hierarchy[$key] = self::createObjectPropertiesEntry($properties); 262 $hierarchy[$key] = self::createObjectPropertiesEntry($properties);
261 - 263 +
262 if (isset($entry[$linkText]) && count($entry[$linkText])) { 264 if (isset($entry[$linkText]) && count($entry[$linkText])) {
263 $hierarchy[$key][$linkText] = self::decodeObjectHierarchy($entry[$linkText], $linkText); 265 $hierarchy[$key][$linkText] = self::decodeObjectHierarchy($entry[$linkText], $linkText);
264 } 266 }
@@ -279,10 +281,10 @@ class CMISUtil { @@ -279,10 +281,10 @@ class CMISUtil {
279 static public function createObjectPropertiesEntry($properties) 281 static public function createObjectPropertiesEntry($properties)
280 { 282 {
281 $object = array(); 283 $object = array();
282 - 284 +
283 foreach(CMISPropertyCollection::$propertyTypes as $property => $type) 285 foreach(CMISPropertyCollection::$propertyTypes as $property => $type)
284 { 286 {
285 - // hack for Author property 287 + // author property does not work the same as the others
286 if ($property == 'author') { 288 if ($property == 'author') {
287 $object[$property] = array('value' => $properties->getValue($property)); 289 $object[$property] = array('value' => $properties->getValue($property));
288 } 290 }
@@ -316,9 +318,9 @@ class CMISUtil { @@ -316,9 +318,9 @@ class CMISUtil {
316 // clean up ", )" - NOTE this may not be necessary, but is included for safety 318 // clean up ", )" - NOTE this may not be necessary, but is included for safety
317 $stringdata = preg_replace('/, *\r?\n? *\)/', ')', $stringdata); 319 $stringdata = preg_replace('/, *\r?\n? *\)/', ')', $stringdata);
318 320
319 - // NOTE is this while loop even needed?  
320 - while (preg_match('/\b[\w]*::__set_state\(/', $stringdata, $matches))  
321 - { 321 + // NOTE is this while loop even needed, or can we just run a preg_replace without the while?
  322 + // TODO find out...
  323 + while (preg_match('/\b[\w]*::__set_state\(/', $stringdata, $matches)) {
322 $stringdata = preg_replace('/\b[\w]*::__set_state\(/', $matches[1], $stringdata); 324 $stringdata = preg_replace('/\b[\w]*::__set_state\(/', $matches[1], $stringdata);
323 } 325 }
324 326
@@ -342,7 +344,7 @@ class CMISUtil { @@ -342,7 +344,7 @@ class CMISUtil {
342 } 344 }
343 345
344 // TODO more robust base64 encoding detection, if possible 346 // TODO more robust base64 encoding detection, if possible
345 - 347 +
346 /** 348 /**
347 * Checks the contentStream and ensures that it is a correct base64 string; 349 * Checks the contentStream and ensures that it is a correct base64 string;
348 * This is purely for clients such as CMISSpaces breaking the content into 350 * This is purely for clients such as CMISSpaces breaking the content into
@@ -363,23 +365,23 @@ class CMISUtil { @@ -363,23 +365,23 @@ class CMISUtil {
363 { 365 {
364 // always trim content, just in case, as the AtomPub specification says content may be padded with whitespace at the start and end. 366 // always trim content, just in case, as the AtomPub specification says content may be padded with whitespace at the start and end.
365 $contentStream = trim($contentStream); 367 $contentStream = trim($contentStream);
366 - 368 +
367 // check whether the content is encoded first, return as is if not 369 // check whether the content is encoded first, return as is if not
368 // Aโ€“Z, aโ€“z, 0โ€“9, +, / 370 // Aโ€“Z, aโ€“z, 0โ€“9, +, /
369 // NOTE this makes the (fairly reasonable) assumption that text content contains at least one space or punctuation character. 371 // NOTE this makes the (fairly reasonable) assumption that text content contains at least one space or punctuation character.
370 // of course this may fail should something be sent in plain text such as a passwords file containing sha1 or md5 hashes only. 372 // of course this may fail should something be sent in plain text such as a passwords file containing sha1 or md5 hashes only.
371 if (preg_match('/[^\w\/\+=\n]+/', $content)) return $contentStream; 373 if (preg_match('/[^\w\/\+=\n]+/', $content)) return $contentStream;
372 - 374 +
373 $decoded = ''; 375 $decoded = '';
374 - 376 +
375 // split the content stream on ={1,2} 377 // split the content stream on ={1,2}
376 $parts = preg_split('/(={1,2})/', $contentStream, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); 378 $parts = preg_split('/(={1,2})/', $contentStream, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
377 foreach($parts as $part) 379 foreach($parts as $part)
378 - { 380 + {
379 if (preg_match('/={1,2}/', $part)) { 381 if (preg_match('/={1,2}/', $part)) {
380 continue; 382 continue;
381 } 383 }
382 - 384 +
383 // lookahead for delimiter, because we may need it back. 385 // lookahead for delimiter, because we may need it back.
384 // NOTE that decoding appears to work fine without this, so this is just an "in case". 386 // NOTE that decoding appears to work fine without this, so this is just an "in case".
385 // NOTE that even with this it seems the present function works faster than the alternative below. 387 // NOTE that even with this it seems the present function works faster than the alternative below.
@@ -388,14 +390,14 @@ class CMISUtil { @@ -388,14 +390,14 @@ class CMISUtil {
388 $part .= $parts[$key+1]; 390 $part .= $parts[$key+1];
389 } 391 }
390 } 392 }
391 - 393 +
392 // decode, append to output 394 // decode, append to output
393 $decoded .= base64_decode($part); 395 $decoded .= base64_decode($part);
394 } 396 }
395 397
396 return $decoded; 398 return $decoded;
397 } 399 }
398 - 400 +
399 /** 401 /**
400 * Checks the contentStream and ensures that it is a correct base64 string; 402 * Checks the contentStream and ensures that it is a correct base64 string;
401 * This is purely for clients such as CMISSpaces breaking the content into 403 * This is purely for clients such as CMISSpaces breaking the content into
@@ -405,7 +407,7 @@ class CMISUtil { @@ -405,7 +407,7 @@ class CMISUtil {
405 * If it is not chunked it is decoded as is and sent back as a single stream. 407 * If it is not chunked it is decoded as is and sent back as a single stream.
406 * 408 *
407 * NOTE this function and the above need to be checked for efficiency. 409 * NOTE this function and the above need to be checked for efficiency.
408 - * The current one appears to be miles better (1/0/3 vs 14/4/57 on respective test files) 410 + * The other one appears to be miles better (1/0/3 vs 14/4/57 on respective test files)
409 * 411 *
410 * @param object $contentStream 412 * @param object $contentStream
411 * @return string decoded 413 * @return string decoded
@@ -414,13 +416,13 @@ class CMISUtil { @@ -414,13 +416,13 @@ class CMISUtil {
414 { 416 {
415 // always trim content, just in case, as the AtomPub specification says content may be padded with whitespace at the start and end. 417 // always trim content, just in case, as the AtomPub specification says content may be padded with whitespace at the start and end.
416 $contentStream = trim($contentStream); 418 $contentStream = trim($contentStream);
417 - 419 +
418 // check whether the content is encoded first, return as is if not 420 // check whether the content is encoded first, return as is if not
419 // Aโ€“Z, aโ€“z, 0โ€“9, +, / 421 // Aโ€“Z, aโ€“z, 0โ€“9, +, /
420 // NOTE this makes the (fairly reasonable) assumption that text content contains at least one space or punctuation character. 422 // NOTE this makes the (fairly reasonable) assumption that text content contains at least one space or punctuation character.
421 // of course this may fail should something be sent in plain text such as a passwords file containing sha1 or md5 hashes only. 423 // of course this may fail should something be sent in plain text such as a passwords file containing sha1 or md5 hashes only.
422 if (preg_match('/[^\w\/\+=\n]+/', $content)) return $contentStream; 424 if (preg_match('/[^\w\/\+=\n]+/', $content)) return $contentStream;
423 - 425 +
424 // check the content stream for any lines of unusual length (except the last line, which can be any length) 426 // check the content stream for any lines of unusual length (except the last line, which can be any length)
425 $count = -1; 427 $count = -1;
426 $length = 0; 428 $length = 0;
@@ -435,11 +437,11 @@ class CMISUtil { @@ -435,11 +437,11 @@ class CMISUtil {
435 foreach ($splitStream as $line) 437 foreach ($splitStream as $line)
436 { 438 {
437 $curlen = strlen($line); 439 $curlen = strlen($line);
438 - 440 +
439 if ($length == 0) { 441 if ($length == 0) {
440 $length = $curlen; 442 $length = $curlen;
441 } 443 }
442 - 444 +
443 // if we find one we know that we must split the line here and end the previous base64 string 445 // if we find one we know that we must split the line here and end the previous base64 string
444 if ($curlen > $length) 446 if ($curlen > $length)
445 { 447 {
@@ -457,7 +459,7 @@ class CMISUtil { @@ -457,7 +459,7 @@ class CMISUtil {
457 } 459 }
458 460
459 $decode[++$count] = $b64String . $lastChunk; 461 $decode[++$count] = $b64String . $lastChunk;
460 - 462 +
461 $b64String = $nextChunk . "\n"; 463 $b64String = $nextChunk . "\n";
462 $length = strlen($nextChunk); 464 $length = strlen($nextChunk);
463 465
@@ -488,7 +490,7 @@ class CMISUtil { @@ -488,7 +490,7 @@ class CMISUtil {
488 490
489 return $decoded; 491 return $decoded;
490 } 492 }
491 - 493 +
492 /** 494 /**
493 * Function to check whether a specified object exists within the KnowledgeTree system 495 * Function to check whether a specified object exists within the KnowledgeTree system
494 * 496 *
@@ -518,10 +520,10 @@ class CMISUtil { @@ -518,10 +520,10 @@ class CMISUtil {
518 else { 520 else {
519 $exists = false; 521 $exists = false;
520 } 522 }
521 - 523 +
522 return $exists; 524 return $exists;
523 } 525 }
524 - 526 +
525 /** 527 /**
526 * Creates a temporary file 528 * Creates a temporary file
527 * Cleanup is the responsibility of the calling code 529 * Cleanup is the responsibility of the calling code
@@ -533,22 +535,22 @@ class CMISUtil { @@ -533,22 +535,22 @@ class CMISUtil {
533 { 535 {
534 // if contentStream is empty, cannot create file 536 // if contentStream is empty, cannot create file
535 if (empty($contentStream)) return null; 537 if (empty($contentStream)) return null;
536 - 538 +
537 // TODO consider checking whether content is encoded (currently we expect encoded) 539 // TODO consider checking whether content is encoded (currently we expect encoded)
538 // TODO choose between this and the alternative decode function (see CMISUtil class) 540 // TODO choose between this and the alternative decode function (see CMISUtil class)
539 // this will require some basic benchmarking 541 // this will require some basic benchmarking
540 $contentStream = self::decodeChunkedContentStream($contentStream); 542 $contentStream = self::decodeChunkedContentStream($contentStream);
541 - 543 +
542 // NOTE There is a function in CMISUtil to do this, written for the unit tests but since KTUploadManager exists 544 // NOTE There is a function in CMISUtil to do this, written for the unit tests but since KTUploadManager exists
543 // and has more functionality which could come in useful at some point I decided to go with that instead 545 // and has more functionality which could come in useful at some point I decided to go with that instead
544 // (did not know this existed when I wrote the CMISUtil function) 546 // (did not know this existed when I wrote the CMISUtil function)
545 $uploadManager = new KTUploadManager(); 547 $uploadManager = new KTUploadManager();
546 // assumes already decoded from base64, should use store_base64_file if not 548 // assumes already decoded from base64, should use store_base64_file if not
547 $tempfilename = $uploadManager->store_file($contentStream, 'cmis_'); 549 $tempfilename = $uploadManager->store_file($contentStream, 'cmis_');
548 - 550 +
549 return $tempfilename; 551 return $tempfilename;
550 } 552 }
551 - 553 +
552 /** 554 /**
553 * attempts to fetch the folder id from a name 555 * attempts to fetch the folder id from a name
554 * 556 *
@@ -562,10 +564,10 @@ class CMISUtil { @@ -562,10 +564,10 @@ class CMISUtil {
562 static public function getIdFromName($name, &$ktapi) 564 static public function getIdFromName($name, &$ktapi)
563 { 565 {
564 $folder = $ktapi->get_folder_by_name($name); 566 $folder = $ktapi->get_folder_by_name($name);
565 - 567 +
566 return self::encodeObjectId(FOLDER, $folder->get_folderid()); 568 return self::encodeObjectId(FOLDER, $folder->get_folderid());
567 } 569 }
568 - 570 +
569 /** 571 /**
570 * Checks for the root folder 572 * Checks for the root folder
571 * 573 *
@@ -578,12 +580,12 @@ class CMISUtil { @@ -578,12 +580,12 @@ class CMISUtil {
578 { 580 {
579 $repository = new CMISRepository($repositoryId); 581 $repository = new CMISRepository($repositoryId);
580 $repositoryInfo = $repository->getRepositoryInfo(); 582 $repositoryInfo = $repository->getRepositoryInfo();
581 - 583 +
582 // NOTE this call is required to accomodate the definition of the root folder id in the config as required by the drupal module 584 // NOTE this call is required to accomodate the definition of the root folder id in the config as required by the drupal module
583 // we should try to update the drupal module to not require this, but this way is just easier at the moment, and most of 585 // we should try to update the drupal module to not require this, but this way is just easier at the moment, and most of
584 // the code accomodates it without any serious hacks 586 // the code accomodates it without any serious hacks
585 $rootFolder = self::getIdFromName($repositoryInfo->getRootFolderId(), $ktapi); 587 $rootFolder = self::getIdFromName($repositoryInfo->getRootFolderId(), $ktapi);
586 - 588 +
587 return $folderId == $rootFolder; 589 return $folderId == $rootFolder;
588 } 590 }
589 591
webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
@@ -91,8 +91,6 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { @@ -91,8 +91,6 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
91 // TODO this only returns one parent, need to implement returnToRoot also 91 // TODO this only returns one parent, need to implement returnToRoot also
92 else if ($this->params[1] == 'parent') 92 else if ($this->params[1] == 'parent')
93 { 93 {
94 - // abstract this to be used also by the document service (and the PWC service?) ???  
95 - // alternatively use getFolderParent here makes sense and use getObjectParents when document service?  
96 $folderId = $this->params[0]; 94 $folderId = $this->params[0];
97 $NavigationService = new KTNavigationService(KT_cmis_atom_service_helper::getKt()); 95 $NavigationService = new KTNavigationService(KT_cmis_atom_service_helper::getKt());
98 $response = $NavigationService->getFolderParent($repositoryId, $folderId, false, false, false); 96 $response = $NavigationService->getFolderParent($repositoryId, $folderId, false, false, false);
@@ -403,9 +401,7 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { @@ -403,9 +401,7 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service {
403 // update accordingly when updating to newer specification 401 // update accordingly when updating to newer specification
404 if ($this->params[1] == 'parent') 402 if ($this->params[1] == 'parent')
405 { 403 {
406 - // abstract this to be used also by the document service (and the PWC service?) ???  
407 - // alternatively use getFolderParent here makes sense and use getObjectParents when document service?  
408 - $NavigationService = new NavigationService(KT_cmis_atom_service_helper::getKt()); 404 + $NavigationService = new KTNavigationService(KT_cmis_atom_service_helper::getKt());
409 $response = $NavigationService->getObjectParents($repositoryId, $objectId, false, false); 405 $response = $NavigationService->getObjectParents($repositoryId, $objectId, false, false);
410 406
411 if ($response['status_code'] == 1) { 407 if ($response['status_code'] == 1) {
@@ -701,28 +697,20 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service { @@ -701,28 +697,20 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service {
701 { 697 {
702 $RepositoryService = new KTRepositoryService(); 698 $RepositoryService = new KTRepositoryService();
703 $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); 699 $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService);
  700 + $type = $this->params[0];
704 701
705 - if (!isset($this->params[1])) {  
706 - // For easier return in the wanted format, we call getTypes instead of getTypeDefinition.  
707 - // Calling this with a single type specified returns an array containing the definition of  
708 - // just the requested type.  
709 - // NOTE could maybe be more efficient to call getTypeDefinition direct and then place in  
710 - // an array on this side? or directly expose the individual entry response code and  
711 - // call directly from here rather than via getTypeFeed.  
712 - $type = ucwords($this->params[0]);  
713 - $types = $RepositoryService->getTypes($repositoryId, $type);  
714 -  
715 - // hack for removing one level of access  
716 - $types = $types['results'];  
717 -  
718 - $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types); 702 + try {
  703 + $typeDefinition = $RepositoryService->getTypeDefinition($repositoryId, $type);
719 } 704 }
720 - else {  
721 - // TODO dynamic dates, as needed everywhere  
722 - // NOTE children of types not yet implemented and we don't support any non-basic types at this time  
723 - $feed = $this->getTypeChildrenFeed($this->params[1]); 705 + catch (Exception $e) {
  706 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $e->getMessage());
  707 + // Expose the responseFeed
  708 + $this->responseFeed = $feed;
  709 + return null;
724 } 710 }
725 711
  712 + $feed = KT_cmis_atom_service_helper::getTypeFeed($type, array($typeDefinition));
  713 +
726 // Expose the responseFeed 714 // Expose the responseFeed
727 $this->responseFeed=$feed; 715 $this->responseFeed=$feed;
728 } 716 }
webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php
@@ -107,25 +107,25 @@ class KT_cmis_atom_service_helper { @@ -107,25 +107,25 @@ class KT_cmis_atom_service_helper {
107 * @param boolean $pwc Whether this is a PWC object 107 * @param boolean $pwc Whether this is a PWC object
108 * @param $method The request method used (POST/GET/...) 108 * @param $method The request method used (POST/GET/...)
109 */ 109 */
110 - static public function createObjectEntry(&$response, $cmisEntry, $parent, $pwc = false, $method = 'GET') 110 + static public function createObjectEntry(&$feed, $cmisEntry, $parent, $pwc = false, $method = 'GET')
111 { 111 {
112 - $workspace = $response->getWorkspace(); 112 + $workspace = $feed->getWorkspace();
113 $type = strtolower($cmisEntry['properties']['objectTypeId']['value']); 113 $type = strtolower($cmisEntry['properties']['objectTypeId']['value']);
114 114
115 // create entry 115 // create entry
116 - $entry = $response->newEntry(); 116 + $entry = $feed->newEntry();
117 117
118 // When request is a POST we will be returning only an object entry, not a full feed, and so this belongs here 118 // When request is a POST we will be returning only an object entry, not a full feed, and so this belongs here
119 if (($method == 'POST') || $pwc) 119 if (($method == 'POST') || $pwc)
120 { 120 {
121 // append attributes 121 // append attributes
122 - $entry->appendChild($response->newAttr('xmlns', 'http://www.w3.org/2005/Atom'));  
123 - $entry->appendChild($response->newAttr('xmlns:app', 'http://www.w3.org/2007/app'));  
124 - $entry->appendChild($response->newAttr('xmlns:cmis', 'http://docs.oasis-open.org/ns/cmis/core/200908/'));  
125 - $entry->appendChild($response->newAttr('xmlns:cmisra', 'http://docs.oasis-open.org/ns/cmis/restatom/200908/')); 122 + $entry->appendChild($feed->newAttr('xmlns', 'http://www.w3.org/2005/Atom'));
  123 + $entry->appendChild($feed->newAttr('xmlns:app', 'http://www.w3.org/2007/app'));
  124 + $entry->appendChild($feed->newAttr('xmlns:cmis', 'http://docs.oasis-open.org/ns/cmis/core/200908/'));
  125 + $entry->appendChild($feed->newAttr('xmlns:cmisra', 'http://docs.oasis-open.org/ns/cmis/restatom/200908/'));
126 } 126 }
127 127
128 - self::createObjectEntryContent($entry, $response, $cmisEntry, $parent, $pwc, $method); 128 + self::createObjectEntryContent($entry, $feed, $cmisEntry, $parent, $pwc, $method);
129 } 129 }
130 130
131 /** 131 /**
@@ -151,13 +151,13 @@ class KT_cmis_atom_service_helper { @@ -151,13 +151,13 @@ class KT_cmis_atom_service_helper {
151 // NOTE this approach appears to be necessary due to the structure of the underlying atompub code and specification, 151 // NOTE this approach appears to be necessary due to the structure of the underlying atompub code and specification,
152 // which does not directly support nesting - attempting to create a new feed and append it within the outer 152 // which does not directly support nesting - attempting to create a new feed and append it within the outer
153 // feed resulted in an empty cmisra:children node, so this approach was substituted 153 // feed resulted in an empty cmisra:children node, so this approach was substituted
154 - static public function createChildObjectEntry(&$childrenFeed, $cmisEntry, $workspace, $response, $folderNam) 154 + static public function createChildObjectEntry(&$childrenFeed, $cmisEntry, $workspace, $feed, $folderNam)
155 { 155 {
156 $type = strtolower($cmisEntry['properties']['objectTypeId']['value']); 156 $type = strtolower($cmisEntry['properties']['objectTypeId']['value']);
157 157
158 // create entry 158 // create entry
159 - $entry = $response->newElement('entry');  
160 - self::createObjectEntryContent($entry, $response, $cmisEntry);//, $parent, $pwc, $method); 159 + $entry = $feed->newElement('entry');
  160 + self::createObjectEntryContent($entry, $feed, $cmisEntry);//, $parent, $pwc, $method);
161 $childrenFeed->appendChild($entry); 161 $childrenFeed->appendChild($entry);
162 } 162 }
163 163
@@ -165,26 +165,26 @@ class KT_cmis_atom_service_helper { @@ -165,26 +165,26 @@ class KT_cmis_atom_service_helper {
165 * Creates the actual object entry: this is shared between other functions which require this content 165 * Creates the actual object entry: this is shared between other functions which require this content
166 * 166 *
167 * @param object $entry The entry object 167 * @param object $entry The entry object
168 - * @param object $response The response feed 168 + * @param object $feed The response feed
169 * @param array $cmisEntry The CMIS object content 169 * @param array $cmisEntry The CMIS object content
170 * @param string $parent The parent folder name 170 * @param string $parent The parent folder name
171 * @param boolean $pwc Whether this is a PWC object (will be returned slightly differently) 171 * @param boolean $pwc Whether this is a PWC object (will be returned slightly differently)
172 * @param string $method The calling method (slightly affects the output) 172 * @param string $method The calling method (slightly affects the output)
173 */ 173 */
174 - static public function createObjectEntryContent($entry, &$response, $cmisEntry, $parent = '', $pwc = false, $method = 'GET') 174 + static public function createObjectEntryContent($entry, &$feed, $cmisEntry, $parent = '', $pwc = false, $method = 'GET')
175 { 175 {
176 // TODO dynamic actual creator name 176 // TODO dynamic actual creator name
177 - $responseElement = $response->newField('author');  
178 - $element = $response->newField('name', 'admin', $responseElement); 177 + $responseElement = $feed->newField('author');
  178 + $element = $feed->newField('name', 'admin', $responseElement);
179 $entry->appendChild($responseElement); 179 $entry->appendChild($responseElement);
180 180
181 $typeString = str_replace('cmis:', '', $type); 181 $typeString = str_replace('cmis:', '', $type);
182 182
183 if (!empty($cmisEntry['properties']['contentStreamLength']['value'])) 183 if (!empty($cmisEntry['properties']['contentStreamLength']['value']))
184 { 184 {
185 - $field = $response->newElement('content');  
186 - $field->appendChild($response->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));  
187 - $field->appendChild($response->newAttr('src', CMIS_APP_BASE_URI . $workspace . '/' . $typeString 185 + $field = $feed->newElement('content');
  186 + $field->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));
  187 + $field->appendChild($feed->newAttr('src', CMIS_APP_BASE_URI . $workspace . '/' . $typeString
188 . '/' . $cmisEntry['properties']['objectId']['value'] 188 . '/' . $cmisEntry['properties']['objectId']['value']
189 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 189 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
190 $entry->appendChild($field); 190 $entry->appendChild($field);
@@ -192,37 +192,37 @@ class KT_cmis_atom_service_helper { @@ -192,37 +192,37 @@ class KT_cmis_atom_service_helper {
192 192
193 // content & id tags 193 // content & id tags
194 $id = $cmisEntry['properties']['objectId']['value']; 194 $id = $cmisEntry['properties']['objectId']['value'];
195 - $response->newField('id', 'urn:uuid:' . $id, $entry); 195 + $feed->newField('id', 'urn:uuid:' . $id, $entry);
196 196
197 // links 197 // links
198 - $link = $response->newElement('link');  
199 - $link->appendChild($response->newAttr('rel', 'self'));  
200 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' 198 + $link = $feed->newElement('link');
  199 + $link->appendChild($feed->newAttr('rel', 'self'));
  200 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/'
201 . (!$pwc ? $typeString : 'pwc') . '/' 201 . (!$pwc ? $typeString : 'pwc') . '/'
202 . $cmisEntry['properties']['objectId']['value'])); 202 . $cmisEntry['properties']['objectId']['value']));
203 $entry->appendChild($link); 203 $entry->appendChild($link);
204 204
205 - $link = $response->newElement('link');  
206 - $link->appendChild($response->newAttr('rel', 'edit'));  
207 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString 205 + $link = $feed->newElement('link');
  206 + $link->appendChild($feed->newAttr('rel', 'edit'));
  207 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString
208 . '/' . $cmisEntry['properties']['objectId']['value'])); 208 . '/' . $cmisEntry['properties']['objectId']['value']));
209 $entry->appendChild($link); 209 $entry->appendChild($link);
210 210
211 if ((strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:document') 211 if ((strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:document')
212 && (!empty($cmisEntry['properties']['contentStreamLength']['value']))) 212 && (!empty($cmisEntry['properties']['contentStreamLength']['value'])))
213 { 213 {
214 - $link = $response->newElement('link');  
215 - $link->appendChild($response->newAttr('rel', 'edit-media'));  
216 - $link->appendChild($response->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));  
217 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString 214 + $link = $feed->newElement('link');
  215 + $link->appendChild($feed->newAttr('rel', 'edit-media'));
  216 + $link->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));
  217 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString
218 . '/' . $cmisEntry['properties']['objectId']['value'] 218 . '/' . $cmisEntry['properties']['objectId']['value']
219 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 219 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
220 $entry->appendChild($link); 220 $entry->appendChild($link);
221 221
222 - $link = $response->newElement('link');  
223 - $link->appendChild($response->newAttr('rel', 'enclosure'));  
224 - $link->appendChild($response->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));  
225 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString 222 + $link = $feed->newElement('link');
  223 + $link->appendChild($feed->newAttr('rel', 'enclosure'));
  224 + $link->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));
  225 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString
226 . '/' . $cmisEntry['properties']['objectId']['value'] 226 . '/' . $cmisEntry['properties']['objectId']['value']
227 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 227 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
228 $entry->appendChild($link); 228 $entry->appendChild($link);
@@ -230,17 +230,17 @@ class KT_cmis_atom_service_helper { @@ -230,17 +230,17 @@ class KT_cmis_atom_service_helper {
230 230
231 // according to spec this MUST be present, but spec says that links for function which are not supported 231 // according to spec this MUST be present, but spec says that links for function which are not supported
232 // do not need to be present, so unsure for the moment 232 // do not need to be present, so unsure for the moment
233 - $link = $response->newElement('link');  
234 - $link->appendChild($response->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions'));  
235 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/' 233 + $link = $feed->newElement('link');
  234 + $link->appendChild($feed->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions'));
  235 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/'
236 . $cmisEntry['properties']['objectId']['value'] . '/allowableactions')); 236 . $cmisEntry['properties']['objectId']['value'] . '/allowableactions'));
237 $entry->appendChild($link); 237 $entry->appendChild($link);
238 238
239 // according to spec this MUST be present, but spec says that links for function which are not supported 239 // according to spec this MUST be present, but spec says that links for function which are not supported
240 // do not need to be present, so unsure for the moment 240 // do not need to be present, so unsure for the moment
241 - $link = $response->newElement('link');  
242 - $link->appendChild($response->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/relationships'));  
243 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/' 241 + $link = $feed->newElement('link');
  242 + $link->appendChild($feed->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/relationships'));
  243 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/'
244 . $cmisEntry['properties']['objectId']['value'] . '/rels')); 244 . $cmisEntry['properties']['objectId']['value'] . '/rels'));
245 $entry->appendChild($link); 245 $entry->appendChild($link);
246 246
@@ -251,9 +251,9 @@ class KT_cmis_atom_service_helper { @@ -251,9 +251,9 @@ class KT_cmis_atom_service_helper {
251 if (!CMISUtil::isRootFolder(self::$repositoryId, $cmisEntry['properties']['objectId']['value'], self::$ktapi)) 251 if (!CMISUtil::isRootFolder(self::$repositoryId, $cmisEntry['properties']['objectId']['value'], self::$ktapi))
252 { 252 {
253 // TODO check parent link is correct, fix if needed 253 // TODO check parent link is correct, fix if needed
254 - $link = $response->newElement('link');  
255 - $link->appendChild($response->newAttr('rel', 'up'));  
256 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/' 254 + $link = $feed->newElement('link');
  255 + $link->appendChild($feed->newAttr('rel', 'up'));
  256 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/'
257 . $cmisEntry['properties']['parentId']['value'])); 257 . $cmisEntry['properties']['parentId']['value']));
258 $entry->appendChild($link); 258 $entry->appendChild($link);
259 } 259 }
@@ -261,16 +261,16 @@ class KT_cmis_atom_service_helper { @@ -261,16 +261,16 @@ class KT_cmis_atom_service_helper {
261 // Folder/Document specific links 261 // Folder/Document specific links
262 if (strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:folder') 262 if (strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:folder')
263 { 263 {
264 - $link = $response->newElement('link');  
265 - $link->appendChild($response->newAttr('rel', 'down'));  
266 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' 264 + $link = $feed->newElement('link');
  265 + $link->appendChild($feed->newAttr('rel', 'down'));
  266 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/'
267 . $typeString 267 . $typeString
268 . '/' . $cmisEntry['properties']['objectId']['value'] 268 . '/' . $cmisEntry['properties']['objectId']['value']
269 . '/children')); 269 . '/children'));
270 $entry->appendChild($link); 270 $entry->appendChild($link);
271 - $link = $response->newElement('link');  
272 - $link->appendChild($response->newAttr('rel', 'down'));  
273 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' 271 + $link = $feed->newElement('link');
  272 + $link->appendChild($feed->newAttr('rel', 'down'));
  273 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/'
274 . $typeString 274 . $typeString
275 . '/' . $cmisEntry['properties']['objectId']['value'] 275 . '/' . $cmisEntry['properties']['objectId']['value']
276 . '/descendants')); 276 . '/descendants'));
@@ -285,10 +285,10 @@ class KT_cmis_atom_service_helper { @@ -285,10 +285,10 @@ class KT_cmis_atom_service_helper {
285 // not sure yet where it must point... 285 // not sure yet where it must point...
286 if (!empty($cmisEntry['properties']['contentStreamLength']['value'])) 286 if (!empty($cmisEntry['properties']['contentStreamLength']['value']))
287 { 287 {
288 - $link = $response->newElement('link');  
289 - $link->appendChild($response->newAttr('rel', 'stream'));  
290 - $link->appendChild($response->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));  
291 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type 288 + $link = $feed->newElement('link');
  289 + $link->appendChild($feed->newAttr('rel', 'stream'));
  290 + $link->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));
  291 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type
292 . '/' . $cmisEntry['properties']['objectId']['value'] 292 . '/' . $cmisEntry['properties']['objectId']['value']
293 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 293 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
294 $entry->appendChild($link); 294 $entry->appendChild($link);
@@ -299,68 +299,51 @@ class KT_cmis_atom_service_helper { @@ -299,68 +299,51 @@ class KT_cmis_atom_service_helper {
299 // TODO separated code for PWC and actual document object 299 // TODO separated code for PWC and actual document object
300 if (!empty($cmisEntry['properties']['versionSeriesCheckedOutId']['value'])) 300 if (!empty($cmisEntry['properties']['versionSeriesCheckedOutId']['value']))
301 { 301 {
302 - $link = $response->newElement('link');  
303 - $link->appendChild($response->newAttr('rel', 'pwc'));  
304 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type 302 + $link = $feed->newElement('link');
  303 + $link->appendChild($feed->newAttr('rel', 'pwc'));
  304 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type
305 . '/' . $cmisEntry['properties']['objectId']['value'] 305 . '/' . $cmisEntry['properties']['objectId']['value']
306 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 306 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
307 $entry->appendChild($link); 307 $entry->appendChild($link);
308 - $link = $response->newElement('link');  
309 - $link->appendChild($response->newAttr('rel', 'source'));  
310 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type 308 + $link = $feed->newElement('link');
  309 + $link->appendChild($feed->newAttr('rel', 'source'));
  310 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type
311 . '/' . $cmisEntry['properties']['objectId']['value'] 311 . '/' . $cmisEntry['properties']['objectId']['value']
312 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 312 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
313 $entry->appendChild($link); 313 $entry->appendChild($link);
314 } 314 }
315 315
316 -// $link = $response->newElement('link');  
317 -// $link->appendChild($response->newAttr('rel', 'stream'));  
318 -// $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type 316 +// $link = $feed->newElement('link');
  317 +// $link->appendChild($feed->newAttr('rel', 'stream'));
  318 +// $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type
319 // . '/' . $cmisEntry['properties']['objectId']['value'] 319 // . '/' . $cmisEntry['properties']['objectId']['value']
320 // . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 320 // . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
321 } 321 }
322 322
323 - $link = $response->newElement('link');  
324 - $link->appendChild($response->newAttr('rel', 'describedby'));  
325 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . $type)); 323 + $link = $feed->newElement('link');
  324 + $link->appendChild($feed->newAttr('rel', 'describedby'));
  325 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . $type));
326 $entry->appendChild($link); 326 $entry->appendChild($link);
327 327
328 - $link = $response->newElement('link');  
329 - $link->appendChild($response->newAttr('rel', 'service'));  
330 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument')); 328 + $link = $feed->newElement('link');
  329 + $link->appendChild($feed->newAttr('rel', 'service'));
  330 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument'));
331 $entry->appendChild($link); 331 $entry->appendChild($link);
332 332
333 // TODO proper date 333 // TODO proper date
334 - $entry->appendChild($response->newField('published', self::formatDatestamp()));  
335 - $entry->appendChild($response->newElement('summary', $cmisEntry['properties']['name']['value']));  
336 - $entry->appendChild($response->newElement('title', $cmisEntry['properties']['name']['value']));  
337 - $entry->appendChild($response->newField('updated', self::formatDatestamp())); 334 + $entry->appendChild($feed->newField('published', self::formatDatestamp()));
  335 + $entry->appendChild($feed->newElement('summary', $cmisEntry['properties']['name']['value']));
  336 + $entry->appendChild($feed->newElement('title', $cmisEntry['properties']['name']['value']));
  337 + $entry->appendChild($feed->newField('updated', self::formatDatestamp()));
338 338
339 // main CMIS entry 339 // main CMIS entry
340 - $objectElement = $response->newElement('cmisra:object');  
341 - $propertiesElement = $response->newElement('cmis:properties');  
342 -  
343 - foreach($cmisEntry['properties'] as $propertyName => $property)  
344 - {  
345 - $propElement = $response->newElement('cmis:' . $property['type']);  
346 -// $propElement->appendChild($response->newAttr('localName', 'rep-cmis:' . $propertyName));  
347 - $propElement->appendChild($response->newAttr('propertyDefinitionId', 'cmis:' . $propertyName));  
348 - if (!empty($property['value']))  
349 - {  
350 - if ($propertyName == 'contentStreamUri') {  
351 - $property['value'] = CMIS_APP_BASE_URI . $workspace . '/' . $type . '/' .$property['value'];  
352 - }  
353 - $response->newField('cmis:value', CMISUtil::boolToString($property['value']), $propElement);  
354 - }  
355 - $propertiesElement->appendChild($propElement);  
356 - }  
357 -  
358 - $objectElement->appendChild($propertiesElement); 340 + $objectElement = $feed->newElement('cmisra:object');
  341 + $objectElement->appendChild(self::createEntryPropertiesElement($feed, $cmisEntry['properties']));
359 $entry->appendChild($objectElement); 342 $entry->appendChild($objectElement);
360 343
361 // TODO check determination of when to add app:edited tag 344 // TODO check determination of when to add app:edited tag
362 // if ($method == 'POST') { 345 // if ($method == 'POST') {
363 - $entry->appendChild($response->newElement('app:edited', self::formatDatestamp())); 346 + $entry->appendChild($feed->newElement('app:edited', self::formatDatestamp()));
364 // } 347 // }
365 348
366 // TODO pathSegment entry 349 // TODO pathSegment entry
@@ -368,14 +351,43 @@ class KT_cmis_atom_service_helper { @@ -368,14 +351,43 @@ class KT_cmis_atom_service_helper {
368 // deal with child objects 351 // deal with child objects
369 if (isset($cmisEntry['children'])) { 352 if (isset($cmisEntry['children'])) {
370 // add children node and fill with child entries 353 // add children node and fill with child entries
371 - $childrenFeed = $response->newElement('feed');  
372 - self::createObjectChildrenFeed($childrenFeed, $cmisEntry['children'], $workspace, $response, '' /*folderName not passed through*/); 354 + $childrenFeed = $feed->newElement('feed');
  355 + self::createObjectChildrenFeed($childrenFeed, $cmisEntry['children'], $workspace, $feed, '' /*folderName not passed through*/);
373 356
374 - $childrenElement = $response->newElement('cmisra:children'); 357 + $childrenElement = $feed->newElement('cmisra:children');
375 $childrenElement->appendChild($childrenFeed); 358 $childrenElement->appendChild($childrenFeed);
376 $entry->appendChild($childrenElement); 359 $entry->appendChild($childrenElement);
377 } 360 }
378 } 361 }
  362 +
  363 + /**
  364 + * Shared function for creating an object properties node
  365 + *
  366 + * @param object $feed AtomPub response feed
  367 + * @param array $properties CMIS object properties
  368 + * @return object $propertiesElement AtomPub node
  369 + */
  370 + // TODO leave out unset properties?
  371 + static public function createEntryPropertiesElement(&$feed, $properties)
  372 + {
  373 + $propertiesElement = $feed->newElement('cmis:properties');
  374 + foreach($properties as $propertyName => $property)
  375 + {
  376 + $propElement = $feed->newElement('cmis:' . $property['type']);
  377 +// $propElement->appendChild($feed->newAttr('localName', 'rep-cmis:' . $propertyName));
  378 + $propElement->appendChild($feed->newAttr('propertyDefinitionId', 'cmis:' . $propertyName));
  379 + if (!empty($property['value']))
  380 + {
  381 + if ($propertyName == 'contentStreamUri') {
  382 + $property['value'] = CMIS_APP_BASE_URI . $workspace . '/' . $type . '/' .$property['value'];
  383 + }
  384 + $feed->newField('cmis:value', CMISUtil::boolToString($property['value']), $propElement);
  385 + }
  386 + $propertiesElement->appendChild($propElement);
  387 + }
  388 +
  389 + return $propertiesElement;
  390 + }
379 391
380 /** 392 /**
381 * Retrieves the list of types|type definition as a CMIS AtomPub feed 393 * Retrieves the list of types|type definition as a CMIS AtomPub feed
@@ -386,6 +398,10 @@ class KT_cmis_atom_service_helper { @@ -386,6 +398,10 @@ class KT_cmis_atom_service_helper {
386 */ 398 */
387 static public function getTypeFeed($typeDef, $types) 399 static public function getTypeFeed($typeDef, $types)
388 { 400 {
  401 + global $default;
  402 +// $default->log->info(print_r($types));
  403 +// $default->log->info(print_r($types, true));
  404 + $default->log->info($typeDef);
389 $typesString = ''; 405 $typesString = '';
390 $typesHeading = ''; 406 $typesHeading = '';
391 switch($typeDef) 407 switch($typeDef)
@@ -417,21 +433,6 @@ class KT_cmis_atom_service_helper { @@ -417,21 +433,6 @@ class KT_cmis_atom_service_helper {
417 $element = $feed->newField('name', 'admin', $feedElement); 433 $element = $feed->newField('name', 'admin', $feedElement);
418 $feed->appendChild($feedElement); 434 $feed->appendChild($feedElement);
419 435
420 - // NOTE spec says this link MUST be present but is vague on where it points  
421 - // as of 0.61c:  
422 - // "The source link relation points to the underlying CMIS Type Definition as Atom Entry"  
423 - // so what is the underlying CMIS Type Definition for a collection of base types?  
424 - // suspect that it only applies when not listing all types, i.e. a base type is asked for  
425 - /*  
426 - $link = $feed->newElement('link');  
427 - $link->appendChild($feed->newAttr('rel','source'));  
428 - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['typeId'])));  
429 - $feed->appendChild($link);  
430 - */  
431 -  
432 - // current time: format = 2009-07-13T14:49:27.659+02:00  
433 - $feed->appendChild($feed->newElement('updated', self::formatDatestamp()));  
434 -  
435 foreach($types as $type) 436 foreach($types as $type)
436 { 437 {
437 $entry = $feed->newEntry(); 438 $entry = $feed->newEntry();
@@ -439,48 +440,37 @@ class KT_cmis_atom_service_helper { @@ -439,48 +440,37 @@ class KT_cmis_atom_service_helper {
439 $feedElement = $feed->newField('author'); 440 $feedElement = $feed->newField('author');
440 $element = $feed->newField('name', 'admin', $feedElement); 441 $element = $feed->newField('name', 'admin', $feedElement);
441 $entry->appendChild($feedElement); 442 $entry->appendChild($feedElement);
442 - $feedElement = $feed->newField('content', $type['typeId']); 443 + $feedElement = $feed->newField('content', 'Type definition for ' . $type['baseId']);
443 $entry->appendChild($feedElement); 444 $entry->appendChild($feedElement);
444 445
445 - $feed->newField('id', 'urn:uuid:type-' . $type['typeId'], $feed);  
446 -  
447 - // TODO add parents link when not selecting a base type.  
448 - // TODO add children link when type has children  
449 - // TODO add descendants link when type has children  
450 - // NOTE KnowledgeTree currently only supports base types so these are not important at the present time.  
451 - 446 + $feed->newField('id', 'urn:uuid:type-' . $type['baseId'], $feed);
  447 +
452 // links 448 // links
453 $link = $feed->newElement('link'); 449 $link = $feed->newElement('link');
454 $link->appendChild($feed->newAttr('rel','self')); 450 $link->appendChild($feed->newAttr('rel','self'));
455 - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['typeId']))); 451 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['baseId'])));
456 $entry->appendChild($link); 452 $entry->appendChild($link);
457 // TODO type link MUST point to base type 453 // TODO type link MUST point to base type
458 // KnowledgeTree currently only supports base types so this is not important 454 // KnowledgeTree currently only supports base types so this is not important
459 // at the present time as it will always point at the base type. 455 // at the present time as it will always point at the base type.
460 $link = $feed->newElement('link'); 456 $link = $feed->newElement('link');
461 $link->appendChild($feed->newAttr('rel','type')); 457 $link->appendChild($feed->newAttr('rel','type'));
462 - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['typeId']))); 458 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['baseId'])));
463 $entry->appendChild($link); 459 $entry->appendChild($link);
464 $link = $feed->newElement('link'); 460 $link = $feed->newElement('link');
465 $link->appendChild($feed->newAttr('rel','repository')); 461 $link->appendChild($feed->newAttr('rel','repository'));
466 $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument')); 462 $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument'));
467 $entry->appendChild($link); 463 $entry->appendChild($link);
468 -  
469 - $entry->appendChild($feed->newElement('summary', $type['typeId'] . ' Type'));  
470 - $entry->appendChild($feed->newElement('title', $type['typeId'])); 464 +
  465 + $entry->appendChild($feed->newElement('summary', 'Summary for ' . $type['baseId'] . ' type'));
  466 + $entry->appendChild($feed->newElement('title', $type['baseId']));
471 $entry->appendChild($feed->newElement('updated', self::formatDatestamp())); 467 $entry->appendChild($feed->newElement('updated', self::formatDatestamp()));
472 -  
473 - // main CMIS entry  
474 - $feedElement = $feed->newElement('cmis:' . strtolower($type['typeId']) . 'Type');  
475 - foreach($type as $property => $value)  
476 - {  
477 - $feed->newField('cmis:' . $property, CMISUtil::boolToString($value), $feedElement);  
478 - }  
479 -  
480 - $entry->appendChild($feedElement);  
481 468
482 - // after every entry, append a cmis:terminator tag  
483 -// $entry->appendChild($feed->newElement('cmis:terminator')); 469 + $objectElement = $feed->newElement('cmisra:type');
  470 + foreach($type as $property => $value) {
  471 + $feed->newField('cmis:' . $property, CMISUtil::boolToString($value), $objectElement);
  472 + }
  473 + $entry->appendChild($objectElement);
484 } 474 }
485 475
486 return $feed; 476 return $feed;
webservice/clienttools/services/0.9.1/.htaccess
1 -# This file sets up the necessary PHP settings to run KnowledgeTree  
2 -# optimally.  
3 -#  
4 -# It is best that KnowledgeTree be allowed to manage its PHP and access  
5 -# permissions using these .htaccess files. This prevents direct access  
6 -# to libraries, scripts, and documents that should not be available via  
7 -# the web.  
8 -#  
9 -# By default, to facilitate quick testing of functionality,  
10 -# KnowledgeTree places the Documents directory within the KnowledgeTree  
11 -# web root. This, by default, would allow people to browse the  
12 -# documents in the DMS, bypassing the security permissions. The  
13 -# default .htaccess settings would prevent this.  
14 -#  
15 -# KnowledgeTree itself is able to deal with most PHP configurations,  
16 -# excepting "safe mode" currently, but is unable to handle certain  
17 -# inherent configuration options (for example, setting the upload size  
18 -# very low). Check the setup checklists (as described in the  
19 -# documentation) to see how your configuration is handled.  
20 -#  
21 -# The default .htaccess settings ensure that no workarounds occur in the  
22 -# PHP code, leading to better performance and robustness.  
23 -#  
24 -<IfModule mod_php5.c>  
25 -php_value default_mimetype text/html  
26 -php_value auto_prepend_file none  
27 -php_value auto_append_file none  
28 -php_flag display_startup_errors ON  
29 -php_flag display_errors ON  
30 -php_flag file_uploads ON  
31 -php_flag magic_quotes_gpc OFF  
32 -php_flag magic_quotes_runtime OFF  
33 -php_flag register_globals OFF  
34 -php_flag output_buffering OFF  
35 -php_flag session.auto_start OFF  
36 -</IfModule>  
37 -  
38 -<IfModule sapi_apache2.c>  
39 -php_value default_mimetype text/html  
40 -php_value auto_prepend_file none  
41 -php_value auto_append_file none  
42 -php_flag display_startup_errors ON  
43 -php_flag display_errors ON  
44 -php_flag file_uploads ON  
45 -php_flag magic_quotes_gpc OFF  
46 -php_flag magic_quotes_runtime OFF  
47 -php_flag register_globals OFF  
48 -php_flag output_buffering OFF  
49 -php_flag session.auto_start OFF  
50 -</IfModule>  
51 -  
52 -<IfModule mod_env.c>  
53 -SetEnv kt_htaccess_worked yes  
54 -SetEnvIf Authorization (.*) kt_auth=$1  
55 -</IfModule>  
56 -LimitRequestBody 0  
57 -DirectoryIndex index.html index.php  
58 -Options none  
59 -Options +ExecCGI  
60 -Options +SymLinksIfOwnerMatch  
61 -#AcceptPathInfo On  
62 -  
63 -AddOutputFilter DEFLATE text/html text/plain text/xml text/javascript application/x-javascript text/css  
64 -# The following seems to breaking things on ZendServer - kgf  
65 -#ExpiresActive ON  
66 -#ExpiresByType text/html "access plus 1 day"  
67 -#ExpiresByType text/css "access plus 1 day"  
68 -#ExpiresByType text/javascript "access plus 7 days"  
69 -#ExpiresByType application/x-javascript "access plus 7 days"  
70 -#ExpiresByType image/gif "access plus 1 month"  
71 -#ExpiresByType image/jpg "access plus 1 month"  
72 -#ExpiresByType image/png "access plus 1 month"  
73 -#ExpiresByType image/x-icon "access plus 1 month"  
74 -  
75 -#  
76 -# If you are having uploading larger documents, adjust the 16M examples  
77 -# below to increase the maximum file size. This is set to a reasonable  
78 -# size for testing and most usage patterns, as increased sizes may allow  
79 -# malicious users to use up resources.  
80 -#  
81 -<IfModule mod_php5.c>  
82 -php_value upload_max_filesize -1  
83 -php_value post_max_size 2000M  
84 -php_value memory_limit -1  
85 -php_value max_input_time -1  
86 -php_value max_execution_time 0  
87 -php_value error_reporting 5  
88 -</IfModule>  
89 -<IfModule sapi_apache2.c>  
90 -php_value upload_max_filesize -1  
91 -php_value post_max_size 2000M  
92 -php_value memory_limit -1  
93 -php_value max_input_time -1  
94 -php_value max_execution_time 0  
95 -php_value error_reporting 5  
96 -</IfModule>  
97 -  
98 -# Workaround for mod_auth when running php cgi  
99 -<IfModule mod_rewrite.c>  
100 -RewriteEngine on  
101 -RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]  
102 -</IfModule>  
103 -  
104 -#<IfModule mod_rewrite.c>  
105 -#RewriteEngine On  
106 -#RewriteBase /  
107 -## Set RewriteBase to the base directory that KnowledgeTree is viewable  
108 -## from via the web. So http://foo.org/ is /, and  
109 -## http://bar.com/knowledgeTree/ is /knowledgeTree  
110 -##RewriteBase /knowledgeTree  
111 -#RewriteCond %{REQUEST_FILENAME} !-f  
112 -#RewriteCond %{REQUEST_FILENAME}.php -f  
113 -#RewriteRule !^[^/]*.php - [C]  
114 -#RewriteRule ^([^/]*)([/].+)? $1.php [E=kt_path_info:$2,E=kt_orig_file:$1.php]  
115 -#<IfModule mod_env.c>  
116 -#SetEnv kt_no_extensions yes  
117 -#</IfModule>  
118 -#</IfModule> 1 +# This file sets up the necessary PHP settings to run KnowledgeTree
  2 +# optimally.
  3 +#
  4 +# It is best that KnowledgeTree be allowed to manage its PHP and access
  5 +# permissions using these .htaccess files. This prevents direct access
  6 +# to libraries, scripts, and documents that should not be available via
  7 +# the web.
  8 +#
  9 +# By default, to facilitate quick testing of functionality,
  10 +# KnowledgeTree places the Documents directory within the KnowledgeTree
  11 +# web root. This, by default, would allow people to browse the
  12 +# documents in the DMS, bypassing the security permissions. The
  13 +# default .htaccess settings would prevent this.
  14 +#
  15 +# KnowledgeTree itself is able to deal with most PHP configurations,
  16 +# excepting "safe mode" currently, but is unable to handle certain
  17 +# inherent configuration options (for example, setting the upload size
  18 +# very low). Check the setup checklists (as described in the
  19 +# documentation) to see how your configuration is handled.
  20 +#
  21 +# The default .htaccess settings ensure that no workarounds occur in the
  22 +# PHP code, leading to better performance and robustness.
  23 +#
  24 +<IfModule mod_php5.c>
  25 +php_value default_mimetype text/html
  26 +php_value auto_prepend_file none
  27 +php_value auto_append_file none
  28 +php_flag display_startup_errors ON
  29 +php_flag display_errors ON
  30 +php_flag file_uploads ON
  31 +php_flag magic_quotes_gpc OFF
  32 +php_flag magic_quotes_runtime OFF
  33 +php_flag register_globals OFF
  34 +php_flag output_buffering OFF
  35 +php_flag session.auto_start OFF
  36 +</IfModule>
  37 +
  38 +<IfModule sapi_apache2.c>
  39 +php_value default_mimetype text/html
  40 +php_value auto_prepend_file none
  41 +php_value auto_append_file none
  42 +php_flag display_startup_errors ON
  43 +php_flag display_errors ON
  44 +php_flag file_uploads ON
  45 +php_flag magic_quotes_gpc OFF
  46 +php_flag magic_quotes_runtime OFF
  47 +php_flag register_globals OFF
  48 +php_flag output_buffering OFF
  49 +php_flag session.auto_start OFF
  50 +</IfModule>
  51 +
  52 +<IfModule mod_env.c>
  53 +SetEnv kt_htaccess_worked yes
  54 +SetEnvIf Authorization (.*) kt_auth=$1
  55 +</IfModule>
  56 +LimitRequestBody 0
  57 +DirectoryIndex index.html index.php
  58 +Options none
  59 +Options +ExecCGI
  60 +Options +SymLinksIfOwnerMatch
  61 +#AcceptPathInfo On
  62 +
  63 +AddOutputFilter DEFLATE text/html text/plain text/xml text/javascript application/x-javascript text/css
  64 +# The following seems to breaking things on ZendServer - kgf
  65 +#ExpiresActive ON
  66 +#ExpiresByType text/html "access plus 1 day"
  67 +#ExpiresByType text/css "access plus 1 day"
  68 +#ExpiresByType text/javascript "access plus 7 days"
  69 +#ExpiresByType application/x-javascript "access plus 7 days"
  70 +#ExpiresByType image/gif "access plus 1 month"
  71 +#ExpiresByType image/jpg "access plus 1 month"
  72 +#ExpiresByType image/png "access plus 1 month"
  73 +#ExpiresByType image/x-icon "access plus 1 month"
  74 +
  75 +#
  76 +# If you are having uploading larger documents, adjust the 16M examples
  77 +# below to increase the maximum file size. This is set to a reasonable
  78 +# size for testing and most usage patterns, as increased sizes may allow
  79 +# malicious users to use up resources.
  80 +#
  81 +<IfModule mod_php5.c>
  82 +php_value upload_max_filesize -1
  83 +php_value post_max_size 2000M
  84 +php_value memory_limit -1
  85 +php_value max_input_time -1
  86 +php_value max_execution_time 0
  87 +php_value error_reporting 5
  88 +</IfModule>
  89 +<IfModule sapi_apache2.c>
  90 +php_value upload_max_filesize -1
  91 +php_value post_max_size 2000M
  92 +php_value memory_limit -1
  93 +php_value max_input_time -1
  94 +php_value max_execution_time 0
  95 +php_value error_reporting 5
  96 +</IfModule>
  97 +
  98 +# Workaround for mod_auth when running php cgi
  99 +<IfModule mod_rewrite.c>
  100 +RewriteEngine on
  101 +RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
  102 +</IfModule>
  103 +
  104 +#<IfModule mod_rewrite.c>
  105 +#RewriteEngine On
  106 +#RewriteBase /
  107 +## Set RewriteBase to the base directory that KnowledgeTree is viewable
  108 +## from via the web. So http://foo.org/ is /, and
  109 +## http://bar.com/knowledgeTree/ is /knowledgeTree
  110 +##RewriteBase /knowledgeTree
  111 +#RewriteCond %{REQUEST_FILENAME} !-f
  112 +#RewriteCond %{REQUEST_FILENAME}.php -f
  113 +#RewriteRule !^[^/]*.php - [C]
  114 +#RewriteRule ^([^/]*)([/].+)? $1.php [E=kt_path_info:$2,E=kt_orig_file:$1.php]
  115 +#<IfModule mod_env.c>
  116 +#SetEnv kt_no_extensions yes
  117 +#</IfModule>
  118 +#</IfModule>