Commit a83c2de9c6e334c34fdb017579ee5d421fee746f

Authored by Paul Barrett
1 parent 07800ae6

Added PermissionDeniedException class. Throw this on failed auth attempts (stil…

…l needed for service doc but in place for general services.) Added header for HTTP Basic Auth on failure.

Committed by: Paul Barrett
lib/api/ktcmis/exceptions/PermissionDeniedException.inc.php 0 → 100644
  1 +<?php
  2 +
  3 +class PermissionDeniedException extends Exception {
  4 +
  5 +}
  6 +
  7 +?>
lib/api/ktcmis/ktcmis.inc.php
@@ -52,12 +52,14 @@ require_once(realpath(dirname(__FILE__) . &#39;/../../../config/dmsDefaults.php&#39;)); @@ -52,12 +52,14 @@ require_once(realpath(dirname(__FILE__) . &#39;/../../../config/dmsDefaults.php&#39;));
52 require_once(KT_DIR . '/ktapi/ktapi.inc.php'); 52 require_once(KT_DIR . '/ktapi/ktapi.inc.php');
53 53
54 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis'); 54 define ('CMIS_DIR', KT_LIB_DIR . '/api/ktcmis');
  55 +require_once(CMIS_DIR . '/exceptions/PermissionDeniedException.inc.php');
55 require_once(CMIS_DIR . '/services/CMISRepositoryService.inc.php'); 56 require_once(CMIS_DIR . '/services/CMISRepositoryService.inc.php');
56 require_once(CMIS_DIR . '/services/CMISNavigationService.inc.php'); 57 require_once(CMIS_DIR . '/services/CMISNavigationService.inc.php');
57 require_once(CMIS_DIR . '/services/CMISObjectService.inc.php'); 58 require_once(CMIS_DIR . '/services/CMISObjectService.inc.php');
58 require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); 59 require_once(CMIS_DIR . '/util/CMISUtil.inc.php');
59 60
60 /** 61 /**
  62 + * Base class for all KT CMIS classes
61 * Handles authentication 63 * Handles authentication
62 */ 64 */
63 class KTCMISBase { 65 class KTCMISBase {
@@ -67,6 +69,11 @@ class KTCMISBase { @@ -67,6 +69,11 @@ class KTCMISBase {
67 static protected $ktapi; 69 static protected $ktapi;
68 static protected $session; 70 static protected $session;
69 71
  72 +// public function __construct($username = null, $password = null)
  73 +// {
  74 +// $this->startSession($username, $password);
  75 +// }
  76 +
70 // TODO try to pick up existing session if possible, i.e. if the $session value is not empty 77 // TODO try to pick up existing session if possible, i.e. if the $session value is not empty
71 public function startSession($username, $password) 78 public function startSession($username, $password)
72 { 79 {
@@ -85,6 +92,12 @@ class KTCMISBase { @@ -85,6 +92,12 @@ class KTCMISBase {
85 self::$ktapi = new KTAPI(); 92 self::$ktapi = new KTAPI();
86 self::$session =& self::$ktapi->start_session($username, $password); 93 self::$session =& self::$ktapi->start_session($username, $password);
87 } 94 }
  95 +
  96 + // failed authentication?
  97 + if (PEAR::isError(self::$session))
  98 + {
  99 + throw new PermissionDeniedException('You must be authenticated to perform this action');
  100 + }
88 101
89 // print_r(self::$ktapi); 102 // print_r(self::$ktapi);
90 return self::$session; 103 return self::$session;
@@ -181,7 +194,7 @@ class KTRepositoryService extends KTCMISBase { @@ -181,7 +194,7 @@ class KTRepositoryService extends KTCMISBase {
181 * @param string $repositoryId 194 * @param string $repositoryId
182 */ 195 */
183 public function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, 196 public function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false,
184 - $maxItems = 0, $skipCount = 0, &$hasMoreItems = false) 197 + $maxItems = 0, $skipCount = 0, &$hasMoreItems = false)
185 { 198 {
186 try { 199 try {
187 $repositoryObjectTypeResult = $this->RepositoryService->getTypes($repositoryId, $typeId, $returnPropertyDefinitions, 200 $repositoryObjectTypeResult = $this->RepositoryService->getTypes($repositoryId, $typeId, $returnPropertyDefinitions,
lib/api/ktcmis/services/CMISObjectService.inc.php
@@ -166,6 +166,12 @@ class CMISObjectService { @@ -166,6 +166,12 @@ class CMISObjectService {
166 $properties['name'] = $properties['title']; 166 $properties['name'] = $properties['title'];
167 } 167 }
168 168
  169 + // TODO if name is blank! throw another exception (check type) - using invalidArgument Exception for now
  170 + if (trim($properties['name']) == '')
  171 + {
  172 + throw new InvalidArgumentException('Refusing to create an un-named document');
  173 + }
  174 +
169 // TODO also set to Default if a non-supported type is submitted 175 // TODO also set to Default if a non-supported type is submitted
170 if ($properties['type'] == '') 176 if ($properties['type'] == '')
171 { 177 {
@@ -262,10 +268,10 @@ class CMISObjectService { @@ -262,10 +268,10 @@ class CMISObjectService {
262 throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')'); 268 throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')');
263 } 269 }
264 270
265 - // TODO if name is blank! throw another exception (check type) - using RuntimeException for now 271 + // TODO if name is blank! throw another exception (check type) - using invalidArgument Exception for now
266 if (trim($properties['name']) == '') 272 if (trim($properties['name']) == '')
267 { 273 {
268 - throw new RuntimeException('Refusing to create an un-named folder'); 274 + throw new InvalidArgumentException('Refusing to create an un-named folder');
269 } 275 }
270 276
271 $response = $this->ktapi->create_folder((int)$folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = ''); 277 $response = $this->ktapi->create_folder((int)$folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = '');
webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
@@ -5,7 +5,7 @@ include_once CMIS_ATOM_LIB_FOLDER . &#39;NavigationService.inc.php&#39;; @@ -5,7 +5,7 @@ include_once CMIS_ATOM_LIB_FOLDER . &#39;NavigationService.inc.php&#39;;
5 include_once CMIS_ATOM_LIB_FOLDER . 'ObjectService.inc.php'; 5 include_once CMIS_ATOM_LIB_FOLDER . 'ObjectService.inc.php';
6 include_once 'KT_cmis_atom_service_helper.inc.php'; 6 include_once 'KT_cmis_atom_service_helper.inc.php';
7 7
8 -// TODO response if failed auth, need generic response which can be used by all code 8 +// TODO auth failed response requires WWW-Authenticate: Basic realm="KnowledgeTree DMS" header
9 9
10 /** 10 /**
11 * AtomPub Service: folder 11 * AtomPub Service: folder
@@ -13,12 +13,22 @@ include_once &#39;KT_cmis_atom_service_helper.inc.php&#39;; @@ -13,12 +13,22 @@ include_once &#39;KT_cmis_atom_service_helper.inc.php&#39;;
13 * Returns children, descendants (up to arbitrary depth) or detail for a particular folder 13 * Returns children, descendants (up to arbitrary depth) or detail for a particular folder
14 * 14 *
15 */ 15 */
16 -class KT_cmis_atom_service_folder extends KT_cmis_atom_service  
17 -{  
18 - public function GET_action() 16 +class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
  17 +
  18 + public function GET_action()
19 { 19 {
20 $RepositoryService = new RepositoryService(); 20 $RepositoryService = new RepositoryService();
21 - $RepositoryService->startSession(self::$authData['username'], self::$authData['password']); 21 + try {
  22 + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
  23 + }
  24 + catch (Exception $e)
  25 + {
  26 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  27 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  28 + $this->responseFeed = $feed;
  29 + return null;
  30 + }
  31 +
22 $repositories = $RepositoryService->getRepositories(); 32 $repositories = $RepositoryService->getRepositories();
23 $repositoryId = $repositories[0]['repositoryId']; 33 $repositoryId = $repositories[0]['repositoryId'];
24 34
@@ -31,7 +41,6 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service @@ -31,7 +41,6 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
31 $folderId = CMISUtil::encodeObjectId('Folder', 1); 41 $folderId = CMISUtil::encodeObjectId('Folder', 1);
32 $folderName = urldecode($this->params[0]); 42 $folderName = urldecode($this->params[0]);
33 } 43 }
34 - // this is a bit of a hack, but then it's to accomodate a bit of a hack to work with the knowledgetree/drupal cmis modules...  
35 else if ($this->params[0] == 'path') 44 else if ($this->params[0] == 'path')
36 { 45 {
37 $ktapi =& $RepositoryService->getInterface(); 46 $ktapi =& $RepositoryService->getInterface();
@@ -41,43 +50,84 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service @@ -41,43 +50,84 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
41 { 50 {
42 $folderId = $this->params[0]; 51 $folderId = $this->params[0];
43 $ObjectService = new ObjectService(); 52 $ObjectService = new ObjectService();
44 - $ObjectService->startSession(self::$authData['username'], self::$authData['password']); 53 +
  54 + try {
  55 + $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
  56 + }
  57 + catch (Exception $e)
  58 + {
  59 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  60 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  61 + $this->responseFeed = $feed;
  62 + return null;
  63 + }
  64 +
45 $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false); 65 $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false);
46 $folderName = $cmisEntry['properties']['Name']['value']; 66 $folderName = $cmisEntry['properties']['Name']['value'];
47 -// $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $newObjectId, $cmisEntry['properties']['Name']['value']); 67 + // $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $newObjectId, $cmisEntry['properties']['Name']['value']);
48 } 68 }
49 69
50 if (!empty($this->params[1]) && (($this->params[1] == 'children') || ($this->params[1] == 'descendants'))) 70 if (!empty($this->params[1]) && (($this->params[1] == 'children') || ($this->params[1] == 'descendants')))
51 { 71 {
52 $NavigationService = new NavigationService(); 72 $NavigationService = new NavigationService();
53 - $NavigationService->startSession(self::$authData['username'], self::$authData['password']); 73 +
  74 + try {
  75 + $NavigationService->startSession(self::$authData['username'], self::$authData['password']);
  76 + }
  77 + catch (Exception $e)
  78 + {
  79 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  80 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  81 + $this->responseFeed = $feed;
  82 + return null;
  83 + }
54 84
55 $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $this->params[1]); 85 $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $this->params[1]);
56 } 86 }
57 else 87 else
58 { 88 {
59 $ObjectService = new ObjectService(); 89 $ObjectService = new ObjectService();
60 - $ObjectService->startSession(self::$authData['username'], self::$authData['password']); 90 +
  91 + try {
  92 + $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
  93 + }
  94 + catch (Exception $e)
  95 + {
  96 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  97 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  98 + $this->responseFeed = $feed;
  99 + return null;
  100 + }
61 101
62 $feed = $this->getFolderFeed($ObjectService, $repositoryId, $folderId); 102 $feed = $this->getFolderFeed($ObjectService, $repositoryId, $folderId);
63 } 103 }
64 104
65 - //Expose the responseFeed  
66 - $this->responseFeed = $feed;  
67 - }  
68 -  
69 - public function POST_action() 105 + //Expose the responseFeed
  106 + $this->responseFeed = $feed;
  107 + }
  108 +
  109 + public function POST_action()
70 { 110 {
71 -// $username = $password = 'admin';  
72 $RepositoryService = new RepositoryService(); 111 $RepositoryService = new RepositoryService();
73 - $RepositoryService->startSession(self::$authData['username'], self::$authData['password']); 112 +
  113 + try {
  114 + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
  115 + }
  116 + catch (Exception $e)
  117 + {
  118 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  119 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  120 + $this->responseFeed = $feed;
  121 + return null;
  122 + }
  123 +
74 $repositories = $RepositoryService->getRepositories(); 124 $repositories = $RepositoryService->getRepositories();
75 $repositoryId = $repositories[0]['repositoryId']; 125 $repositoryId = $repositories[0]['repositoryId'];
76 126
77 $folderId = $this->params[0]; 127 $folderId = $this->params[0];
78 $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title'); 128 $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title');
79 $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary'); 129 $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary');
80 - 130 +
81 $properties = array('name' => $title, 'summary' => $summary); 131 $properties = array('name' => $title, 'summary' => $summary);
82 132
83 // determine whether this is a folder or a document create 133 // determine whether this is a folder or a document create
@@ -109,7 +159,18 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service @@ -109,7 +159,18 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
109 [0]['@children']); 159 [0]['@children']);
110 160
111 $ObjectService = new ObjectService(); 161 $ObjectService = new ObjectService();
112 - $ObjectService->startSession(self::$authData['username'], self::$authData['password']); 162 +
  163 + try {
  164 + $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
  165 + }
  166 + catch (Exception $e)
  167 + {
  168 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  169 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  170 + $this->responseFeed = $feed;
  171 + return null;
  172 + }
  173 +
113 if ($type == 'folder') 174 if ($type == 'folder')
114 $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId); 175 $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId);
115 else 176 else
@@ -127,22 +188,30 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service @@ -127,22 +188,30 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
127 else 188 else
128 { 189 {
129 $NavigationService = new NavigationService(); 190 $NavigationService = new NavigationService();
130 - $NavigationService->startSession(self::$authData['username'], self::$authData['password']); 191 +
  192 + try {
  193 + $NavigationService->startSession(self::$authData['username'], self::$authData['password']);
  194 + }
  195 + catch (Exception $e)
  196 + {
  197 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  198 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  199 + $this->responseFeed = $feed;
  200 + return null;
  201 + }
  202 +
131 $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false); 203 $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false);
132 $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $cmisEntry['properties']['Name']['value']); 204 $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $cmisEntry['properties']['Name']['value']);
133 } 205 }
134 } 206 }
135 else 207 else
136 { 208 {
137 - $this->setStatus(self::STATUS_SERVER_ERROR);  
138 - $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Error: ' . self::STATUS_SERVER_ERROR);  
139 - $entry = $feed->newEntry();  
140 - $feed->newField('error', $newObjectId['message'], $entry); 209 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $newObjectId['message']);
141 } 210 }
142 211
143 //Expose the responseFeed 212 //Expose the responseFeed
144 - $this->responseFeed = $feed;  
145 - } 213 + $this->responseFeed = $feed;
  214 + }
146 215
147 /** 216 /**
148 * Retrieves children/descendants of the specified folder 217 * Retrieves children/descendants of the specified folder
@@ -169,7 +238,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service @@ -169,7 +238,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
169 } 238 }
170 239
171 // $baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL 240 // $baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL
172 - $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $folderName . ' ' . ucwords($feedType), null, null, null, 241 + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $folderName . ' ' . ucwords($feedType), null, null, null,
173 'urn:uuid:' . $folderName . '-' . $feedType); 242 'urn:uuid:' . $folderName . '-' . $feedType);
174 243
175 foreach($entries as $cmisEntry) 244 foreach($entries as $cmisEntry)
@@ -200,14 +269,15 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service @@ -200,14 +269,15 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
200 269
201 $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $cmisEntry['properties']['ObjectTypeId']['value'], null, null, null, 270 $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $cmisEntry['properties']['ObjectTypeId']['value'], null, null, null,
202 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value']); 271 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value']);
203 - 272 +
204 KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $folderName); 273 KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $folderName);
205 -// // <cmis:hasMoreItems>false</cmis:hasMoreItems>  
206 -// // global $folderFeed;  
207 -// // $outputs = 274 + // // <cmis:hasMoreItems>false</cmis:hasMoreItems>
  275 + // // global $folderFeed;
  276 + // // $outputs =
208 277
209 return $feed; 278 return $feed;
210 } 279 }
  280 +
211 } 281 }
212 282
213 /** 283 /**
@@ -216,15 +286,22 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service @@ -216,15 +286,22 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
216 * Returns a list of supported object types 286 * Returns a list of supported object types
217 * 287 *
218 */ 288 */
219 -class KT_cmis_atom_service_types extends KT_cmis_atom_service  
220 -{  
221 - public function GET_action() 289 +class KT_cmis_atom_service_types extends KT_cmis_atom_service {
  290 +
  291 + public function GET_action()
222 { 292 {
223 -// $username = $password = 'admin';  
224 $RepositoryService = new RepositoryService(); 293 $RepositoryService = new RepositoryService();
225 - // technically do not need to log in to access this information  
226 - // TODO consider requiring authentication even to access basic repository information  
227 - $RepositoryService->startSession(self::$authData['username'], self::$authData['password']); 294 +
  295 + try {
  296 + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
  297 + }
  298 + catch (Exception $e)
  299 + {
  300 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  301 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  302 + $this->responseFeed = $feed;
  303 + return null;
  304 + }
228 305
229 // fetch repository id 306 // fetch repository id
230 $repositories = $RepositoryService->getRepositories(); 307 $repositories = $RepositoryService->getRepositories();
@@ -234,9 +311,10 @@ class KT_cmis_atom_service_types extends KT_cmis_atom_service @@ -234,9 +311,10 @@ class KT_cmis_atom_service_types extends KT_cmis_atom_service
234 $type = ((empty($this->params[0])) ? 'all' : $this->params[0]); 311 $type = ((empty($this->params[0])) ? 'all' : $this->params[0]);
235 $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types); 312 $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types);
236 313
237 - //Expose the responseFeed  
238 - $this->responseFeed = $feed;  
239 - } 314 + //Expose the responseFeed
  315 + $this->responseFeed = $feed;
  316 + }
  317 +
240 } 318 }
241 319
242 /** 320 /**
@@ -245,42 +323,48 @@ class KT_cmis_atom_service_types extends KT_cmis_atom_service @@ -245,42 +323,48 @@ class KT_cmis_atom_service_types extends KT_cmis_atom_service
245 * Returns the type defintion for the selected type 323 * Returns the type defintion for the selected type
246 * 324 *
247 */ 325 */
248 -class KT_cmis_atom_service_type extends KT_cmis_atom_service  
249 -{  
250 - public function GET_action() 326 +class KT_cmis_atom_service_type extends KT_cmis_atom_service {
  327 +
  328 + public function GET_action()
251 { 329 {
252 -// $username = $password = 'admin';  
253 $RepositoryService = new RepositoryService(); 330 $RepositoryService = new RepositoryService();
254 - // technically do not need to log in to access this information  
255 - // TODO consider requiring authentication even to access basic repository information  
256 - $RepositoryService->startSession(self::$authData['username'], self::$authData['password']); 331 +
  332 + try {
  333 + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
  334 + }
  335 + catch (Exception $e)
  336 + {
  337 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  338 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  339 + $this->responseFeed = $feed;
  340 + return null;
  341 + }
257 342
258 // fetch repository id 343 // fetch repository id
259 $repositories = $RepositoryService->getRepositories(); 344 $repositories = $RepositoryService->getRepositories();
260 $repositoryId = $repositories[0]['repositoryId']; 345 $repositoryId = $repositories[0]['repositoryId'];
261 -  
262 - if (!isset($this->params[1]))  
263 - {  
264 - // For easier return in the wanted format, we call getTypes instead of getTypeDefinition.  
265 - // Calling this with a single type specified returns an array containing the definition of  
266 - // just the requested type.  
267 - // NOTE could maybe be more efficient to call getTypeDefinition direct and then place in  
268 - // an array on this side? or directly expose the individual entry response code and  
269 - // call directly from here rather than via getTypeFeed. 346 +
  347 + if (!isset($this->params[1])) {
  348 + // For easier return in the wanted format, we call getTypes instead of getTypeDefinition.
  349 + // Calling this with a single type specified returns an array containing the definition of
  350 + // just the requested type.
  351 + // NOTE could maybe be more efficient to call getTypeDefinition direct and then place in
  352 + // an array on this side? or directly expose the individual entry response code and
  353 + // call directly from here rather than via getTypeFeed.
270 $type = ucwords($this->params[0]); 354 $type = ucwords($this->params[0]);
271 $types = $RepositoryService->getTypes($repositoryId, $type); 355 $types = $RepositoryService->getTypes($repositoryId, $type);
272 $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types); 356 $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types);
273 } 357 }
274 - else  
275 - {  
276 - // TODO dynamic dates, as needed everywhere  
277 - // NOTE children of types not yet implemented and we don't support any non-basic types at this time 358 + else {
  359 + // TODO dynamic dates, as needed everywhere
  360 + // NOTE children of types not yet implemented and we don't support any non-basic types at this time
278 $feed = $this->getTypeChildrenFeed($this->params[1]); 361 $feed = $this->getTypeChildrenFeed($this->params[1]);
279 } 362 }
280 363
281 - //Expose the responseFeed  
282 - $this->responseFeed=$feed;  
283 - } 364 + //Expose the responseFeed
  365 + $this->responseFeed=$feed;
  366 + }
  367 +
284 /** 368 /**
285 * Retrieves a list of child types for the supplied type 369 * Retrieves a list of child types for the supplied type
286 * 370 *
@@ -292,10 +376,10 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service @@ -292,10 +376,10 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service
292 */ 376 */
293 private function getTypeChildrenFeed() 377 private function getTypeChildrenFeed()
294 { 378 {
295 - //Create a new response feed  
296 - // $baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL  
297 - $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Child Types of ' . ucwords($this->params[0]), null, null, null,  
298 - $this->params[0] . '-children'); 379 + //Create a new response feed
  380 + // $baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL
  381 + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Child Types of ' . ucwords($this->params[0]), null, null, null,
  382 + $this->params[0] . '-children');
299 383
300 // TODO actually fetch child types - to be implemented when we support child types in the API 384 // TODO actually fetch child types - to be implemented when we support child types in the API
301 385
@@ -316,8 +400,8 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service @@ -316,8 +400,8 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service
316 // TODO actual dynamic listing, currently we have no objects with which to test 400 // TODO actual dynamic listing, currently we have no objects with which to test
317 401
318 // TODO 402 // TODO
319 -// <updated>2009-06-23T13:40:32.786+02:00</updated>  
320 -// <cmis:hasMoreItems>false</cmis:hasMoreItems> 403 + // <updated>2009-06-23T13:40:32.786+02:00</updated>
  404 + // <cmis:hasMoreItems>false</cmis:hasMoreItems>
321 /* 405 /*
322 // TODO need to create this dynamically now, will no longer work with static output 406 // TODO need to create this dynamically now, will no longer work with static output
323 $output = '<?xml version="1.0" encoding="UTF-8"?> 407 $output = '<?xml version="1.0" encoding="UTF-8"?>
@@ -343,23 +427,31 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service @@ -343,23 +427,31 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service
343 * 427 *
344 */ 428 */
345 // NOTE this is always an empty document, underlying API code still to be implemented 429 // NOTE this is always an empty document, underlying API code still to be implemented
346 -class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service  
347 -{  
348 - public function GET_action() 430 +class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service {
  431 +
  432 + public function GET_action()
349 { 433 {
350 -// $username = $password = 'admin';  
351 $RepositoryService = new RepositoryService(); 434 $RepositoryService = new RepositoryService();
352 $NavigationService = new NavigationService(); 435 $NavigationService = new NavigationService();
353 436
354 - $NavigationService->startSession(self::$authData['username'], self::$authData['password']); 437 + try {
  438 + $NavigationService->startSession(self::$authData['username'], self::$authData['password']);
  439 + }
  440 + catch (Exception $e)
  441 + {
  442 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  443 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  444 + $this->responseFeed = $feed;
  445 + return null;
  446 + }
355 447
356 $repositories = $RepositoryService->getRepositories(); 448 $repositories = $RepositoryService->getRepositories();
357 $repositoryId = $repositories[0]['repositoryId']; 449 $repositoryId = $repositories[0]['repositoryId'];
358 450
359 $checkedout = $NavigationService->getCheckedoutDocs($repositoryId); 451 $checkedout = $NavigationService->getCheckedoutDocs($repositoryId);
360 452
361 - //Create a new response feed  
362 - $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Checked out Documents', null, null, null, 'urn:uuid:checkedout'); 453 + //Create a new response feed
  454 + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Checked out Documents', null, null, null, 'urn:uuid:checkedout');
363 455
364 foreach($checkedout as $document) 456 foreach($checkedout as $document)
365 { 457 {
@@ -382,9 +474,9 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service @@ -382,9 +474,9 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service
382 $entry = null; 474 $entry = null;
383 $feed->newField('hasMoreItems', 'false', $entry, true); 475 $feed->newField('hasMoreItems', 'false', $entry, true);
384 476
385 - //Expose the responseFeed  
386 - $this->responseFeed = $feed;  
387 - } 477 + //Expose the responseFeed
  478 + $this->responseFeed = $feed;
  479 + }
388 480
389 } 481 }
390 482
@@ -394,35 +486,45 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service @@ -394,35 +486,45 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service
394 * Returns detail on a particular document 486 * Returns detail on a particular document
395 * 487 *
396 */ 488 */
397 -class KT_cmis_atom_service_document extends KT_cmis_atom_service  
398 -{  
399 - public function GET_action() 489 +class KT_cmis_atom_service_document extends KT_cmis_atom_service {
  490 +
  491 + public function GET_action()
400 { 492 {
401 -// $username = $password = 'admin';  
402 $RepositoryService = new RepositoryService(); 493 $RepositoryService = new RepositoryService();
403 494
404 $ObjectService = new ObjectService(); 495 $ObjectService = new ObjectService();
405 - $ObjectService->startSession(self::$authData['username'], self::$authData['password']);  
406 - 496 +
  497 + try {
  498 + $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
  499 + }
  500 + catch (Exception $e)
  501 + {
  502 + $this->headers[] = 'WWW-Authenticate: Basic realm="KnowledgeTree Secure Area"';
  503 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_NOT_AUTHENTICATED, $e->getMessage());
  504 + $this->responseFeed = $feed;
  505 + return null;
  506 + }
  507 +
407 $repositories = $RepositoryService->getRepositories(); 508 $repositories = $RepositoryService->getRepositories();
408 $repositoryId = $repositories[0]['repositoryId']; 509 $repositoryId = $repositories[0]['repositoryId'];
409 510
410 $cmisEntry = $ObjectService->getProperties($repositoryId, $this->params[0], false, false); 511 $cmisEntry = $ObjectService->getProperties($repositoryId, $this->params[0], false, false);
411 512
412 //Create a new response feed 513 //Create a new response feed
413 - $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $cmisEntry['properties']['ObjectTypeId']['value'], null, null, null,  
414 - 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value']); 514 + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $cmisEntry['properties']['ObjectTypeId']['value'], null, null, null,
  515 + 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value']);
415 516
416 KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $cmisEntry['properties']['ParentId']['value']); 517 KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $cmisEntry['properties']['ParentId']['value']);
417 518
418 // <cmis:hasMoreItems>false</cmis:hasMoreItems> 519 // <cmis:hasMoreItems>false</cmis:hasMoreItems>
419 520
420 -// global $docFeed;  
421 -// $output = $docFeed; 521 + // global $docFeed;
  522 + // $output = $docFeed;
422 523
423 - //Expose the responseFeed  
424 - $this->responseFeed=$feed;  
425 - } 524 + //Expose the responseFeed
  525 + $this->responseFeed=$feed;
  526 + }
  527 +
426 } 528 }
427 529
428 $childrenFeed[] = '<?xml version="1.0" encoding="utf-8"?> 530 $childrenFeed[] = '<?xml version="1.0" encoding="utf-8"?>
@@ -532,7 +634,7 @@ $childrenFeed[] = &#39;&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt; @@ -532,7 +634,7 @@ $childrenFeed[] = &#39;&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
532 </entry> 634 </entry>
533 </feed>'; 635 </feed>';
534 636
535 - $childrenFeed[] = '<?xml version="1.0" encoding="UTF-8"?> 637 +$childrenFeed[] = '<?xml version="1.0" encoding="UTF-8"?>
536 <feed xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:cmis="http://www.cmis.org/2008/05" xmlns:alf="http://www.alfresco.org" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"> 638 <feed xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:cmis="http://www.cmis.org/2008/05" xmlns:alf="http://www.alfresco.org" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
537 <author><name>System</name></author> 639 <author><name>System</name></author>
538 <generator version="3.0.0 (Stable 1526)">Alfresco (Labs)</generator> 640 <generator version="3.0.0 (Stable 1526)">Alfresco (Labs)</generator>
webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php
@@ -112,7 +112,7 @@ class KT_cmis_atom_service_helper { @@ -112,7 +112,7 @@ class KT_cmis_atom_service_helper {
112 } 112 }
113 113
114 //Create a new response feed 114 //Create a new response feed
115 - $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $typesHeading, null, null, null, 'urn:uuid:' . $typesString); 115 + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $typesHeading, null, null, null, 'urn:uuid:' . $typesString);
116 116
117 foreach($types as $type) 117 foreach($types as $type)
118 { 118 {
@@ -157,6 +157,16 @@ class KT_cmis_atom_service_helper { @@ -157,6 +157,16 @@ class KT_cmis_atom_service_helper {
157 return $feed; 157 return $feed;
158 } 158 }
159 159
  160 + static public function getErrorFeed(&$service, $status, $message)
  161 + {
  162 + $service->setStatus($status);
  163 + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Error: ' . $status);
  164 + $entry = $feed->newEntry();
  165 + $feed->newField('error', $message, $entry);
  166 +
  167 + return $feed;
  168 + }
  169 +
160 /** 170 /**
161 * Fetches the CMIS objectId based on the path 171 * Fetches the CMIS objectId based on the path
162 * 172 *
webservice/classes/atompub/KT_atom_server.inc.php
1 <?php 1 <?php
2 -class KT_atom_server{ 2 +class KT_atom_server {
  3 +
  4 + public $output='';
3 protected $services=array(); 5 protected $services=array();
4 protected $workspaceDetail=array(); 6 protected $workspaceDetail=array();
5 protected $errors=array(); 7 protected $errors=array();
6 - public $output='';  
7 protected $queryArray=array(); 8 protected $queryArray=array();
8 protected $serviceName=''; 9 protected $serviceName='';
9 protected $method=''; 10 protected $method='';
10 protected $workspace=''; 11 protected $workspace='';
11 - 12 + protected $serviceObject = null;
12 13
13 public function __construct(){ 14 public function __construct(){
14 } 15 }
webservice/classes/atompub/KT_atom_service.inc.php
@@ -3,11 +3,11 @@ class KT_atom_service{ @@ -3,11 +3,11 @@ class KT_atom_service{
3 const STATUS_OK = '200 OK'; 3 const STATUS_OK = '200 OK';
4 const STATUS_NOT_FOUND = '204 No Content'; 4 const STATUS_NOT_FOUND = '204 No Content';
5 const STATUS_NOT_ALLOWED = '204 Not Allowed'; 5 const STATUS_NOT_ALLOWED = '204 Not Allowed';
6 - const STATUS_NOT_AUTHENTICATED = '204 Not Authenticated';  
7 const STATUS_CREATED = '201 Created'; 6 const STATUS_CREATED = '201 Created';
8 const STATUS_UPDATED = '200 Updated'; 7 const STATUS_UPDATED = '200 Updated';
9 const STATUS_NOT_MODIFIED = '304 Not Modified'; // For use with ETag & If-None-Match headers. 8 const STATUS_NOT_MODIFIED = '304 Not Modified'; // For use with ETag & If-None-Match headers.
10 const STATUS_BAD_REQUEST = '400 Bad Request'; // Client issued a wrongly constructed request 9 const STATUS_BAD_REQUEST = '400 Bad Request'; // Client issued a wrongly constructed request
  10 + const STATUS_NOT_AUTHENTICATED = '401 Not Authenticated';
11 const STATUS_PRECONDITION_FAILED = '412 Precondition Failed'; // Could not update document because another a newer version exist on the server than the one you are trying to update 11 const STATUS_PRECONDITION_FAILED = '412 Precondition Failed'; // Could not update document because another a newer version exist on the server than the one you are trying to update
12 const STATUS_SERVER_ERROR = '500 Internal Server Error'; // Server encountered an error processing the request 12 const STATUS_SERVER_ERROR = '500 Internal Server Error'; // Server encountered an error processing the request
13 13
@@ -56,6 +56,10 @@ class KT_atom_service{ @@ -56,6 +56,10 @@ class KT_atom_service{
56 $this->setStatus(KT_atom_service::STATUS_NOT_FOUND ); 56 $this->setStatus(KT_atom_service::STATUS_NOT_FOUND );
57 } 57 }
58 58
  59 + public function getHeaders()
  60 + {
  61 + return $this->headers;
  62 + }
59 63
60 public function render(){ 64 public function render(){
61 return $this->responseFeed->render(); 65 return $this->responseFeed->render();
webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php
@@ -119,6 +119,24 @@ class KT_cmis_atom_server extends KT_atom_server { @@ -119,6 +119,24 @@ class KT_cmis_atom_server extends KT_atom_server {
119 return false; 119 return false;
120 } 120 }
121 121
  122 + // TODO we probably want this version in the base class for auth purposes
  123 + public function render()
  124 + {
  125 + ob_end_clean();
  126 + // possible additional headers, e.g. basic auth request
  127 + // FIXME this won't work with the service document as no service object exists
  128 + if (!is_null($this->serviceObject))
  129 + {
  130 + $headers = $this->serviceObject->getHeaders();
  131 + foreach ($headers as $header)
  132 + {
  133 + header($header);
  134 + }
  135 + }
  136 + header('Content-type: text/xml');
  137 + echo $this->output;
  138 + }
  139 +
122 } 140 }
123 141
124 ?> 142 ?>
125 \ No newline at end of file 143 \ No newline at end of file
webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php
@@ -10,17 +10,12 @@ class KT_cmis_atom_service extends KT_atom_service { @@ -10,17 +10,12 @@ class KT_cmis_atom_service extends KT_atom_service {
10 10
11 protected function parseHeaders() 11 protected function parseHeaders()
12 { 12 {
13 -// echo "PARSE HEADERS\n";  
14 parent::parseHeaders(); 13 parent::parseHeaders();
15 -// echo "CHECKING HEADERS\n";  
16 -// print_r($this->headers);  
17 -// print_r($_SERVER);  
18 // attempt to fetch auth info from supplied headers 14 // attempt to fetch auth info from supplied headers
19 if (!empty($this->headers['Authorization'])) 15 if (!empty($this->headers['Authorization']))
20 { 16 {
21 $auth = base64_decode(preg_replace('/Basic */', '', $this->headers['Authorization'])); 17 $auth = base64_decode(preg_replace('/Basic */', '', $this->headers['Authorization']));
22 $authData = explode(':', $auth); 18 $authData = explode(':', $auth);
23 -// print_r($authData);  
24 self::$authData['username'] = $authData[0]; 19 self::$authData['username'] = $authData[0];
25 self::$authData['password'] = $authData[1]; 20 self::$authData['password'] = $authData[1];
26 } 21 }
webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php
@@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
32 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices 32 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
33 * must display the words "Powered by KnowledgeTree" and retain the original 33 * must display the words "Powered by KnowledgeTree" and retain the original
34 * copyright notice. 34 * copyright notice.
35 - * Contributor( s): 35 + * Contributor( s):
36 * Mark Holtzhausen <mark@knowledgetree.com> 36 * Mark Holtzhausen <mark@knowledgetree.com>
37 * Paul Barrett <paul@knowledgetree.com> 37 * Paul Barrett <paul@knowledgetree.com>
38 * 38 *
@@ -47,13 +47,13 @@ include_once(KT_ATOM_LIB_FOLDER.&#39;KT_atom_serviceDoc.inc.php&#39;); @@ -47,13 +47,13 @@ include_once(KT_ATOM_LIB_FOLDER.&#39;KT_atom_serviceDoc.inc.php&#39;);
47 47
48 class KT_cmis_atom_serviceDoc extends KT_atom_serviceDoc { 48 class KT_cmis_atom_serviceDoc extends KT_atom_serviceDoc {
49 49
50 - // override and extend as needed 50 +// override and extend as needed
51 51
52 public $repositoryInfo = array(); 52 public $repositoryInfo = array();
53 53
54 public function __construct($baseURI = NULL) 54 public function __construct($baseURI = NULL)
55 { 55 {
56 - parent::__construct(); 56 + parent::__construct();
57 57
58 // get repositoryInfo 58 // get repositoryInfo
59 // NOTE currently we only support one repository, which will be the first one found in the repositories.xml config 59 // NOTE currently we only support one repository, which will be the first one found in the repositories.xml config
@@ -61,63 +61,65 @@ class KT_cmis_atom_serviceDoc extends KT_atom_serviceDoc { @@ -61,63 +61,65 @@ class KT_cmis_atom_serviceDoc extends KT_atom_serviceDoc {
61 61
62 include 'services/cmis/RepositoryService.inc.php'; 62 include 'services/cmis/RepositoryService.inc.php';
63 $RepositoryService = new RepositoryService(); 63 $RepositoryService = new RepositoryService();
  64 + // TODO add auth requirement here, don't want to even supply service doc without auth
  65 +// $RepositoryService->startSession();
64 66
65 // fetch data for response 67 // fetch data for response
66 $repositories = $RepositoryService->getRepositories(); 68 $repositories = $RepositoryService->getRepositories();
67 // fetch for default first repo; NOTE that this will probably have to change at some point, quick and dirty for now 69 // fetch for default first repo; NOTE that this will probably have to change at some point, quick and dirty for now
68 $this->repositoryInfo = $RepositoryService->getRepositoryInfo($repositories[0]['repositoryId']); 70 $this->repositoryInfo = $RepositoryService->getRepositoryInfo($repositories[0]['repositoryId']);
69 - }  
70 -  
71 - protected function constructServiceDocumentHeaders() 71 + }
  72 +
  73 + protected function constructServiceDocumentHeaders()
72 { 74 {
73 - $service = $this->newElement('service');  
74 - $service->appendChild($this->newAttr('xmlns', 'http://www.w3.org/2007/app'));  
75 - $service->appendChild($this->newAttr('xmlns:atom', 'http://www.w3.org/2005/Atom')); 75 + $service = $this->newElement('service');
  76 + $service->appendChild($this->newAttr('xmlns', 'http://www.w3.org/2007/app'));
  77 + $service->appendChild($this->newAttr('xmlns:atom', 'http://www.w3.org/2005/Atom'));
76 $service->appendChild($this->newAttr('xmlns:cmis', 'http://www.cmis.org/2008/05')); 78 $service->appendChild($this->newAttr('xmlns:cmis', 'http://www.cmis.org/2008/05'));
77 $this->service =& $service; 79 $this->service =& $service;
78 - $this->DOM->appendChild($this->service);  
79 - }  
80 -  
81 - public function &newCollection($url = NULL, $title = NULL, $cmisCollectionType = NULL, &$ws = NULL) 80 + $this->DOM->appendChild($this->service);
  81 + }
  82 +
  83 + public function &newCollection($url = NULL, $title = NULL, $cmisCollectionType = NULL, &$ws = NULL)
82 { 84 {
83 - $collection=$this->newElement('collection');  
84 - $collection->appendChild($this->newAttr('href', $url));  
85 - $collection->appendChild($this->newAttr('cmis:collectionType', $cmisCollectionType));  
86 - $collection->appendChild($this->newElement('atom:title', $title));  
87 - if(isset($ws))$ws->appendChild($collection);  
88 - return $collection;  
89 - }  
90 - 85 + $collection=$this->newElement('collection');
  86 + $collection->appendChild($this->newAttr('href', $url));
  87 + $collection->appendChild($this->newAttr('cmis:collectionType', $cmisCollectionType));
  88 + $collection->appendChild($this->newElement('atom:title', $title));
  89 + if(isset($ws))$ws->appendChild($collection);
  90 + return $collection;
  91 + }
  92 +
91 } 93 }
92 94
93 /** 95 /**
94 -<?xml version="1.0" encoding="utf-8"?>  
95 -<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">  
96 - <workspace>  
97 - <atom:title>Main Site</atom:title>  
98 - <collection href="http://example.org/blog/main" >  
99 - <atom:title>My Blog Entries</atom:title>  
100 - <categories href="http://example.com/cats/forMain.cats" />  
101 - </collection>  
102 - <collection href="http://example.org/blog/pic" >  
103 - <atom:title>Pictures</atom:title>  
104 - <accept>image/png</accept>  
105 - <accept>image/jpeg</accept>  
106 - <accept>image/gif</accept>  
107 - </collection>  
108 - </workspace>  
109 - <workspace>  
110 - <atom:title>Sidebar Blog</atom:title>  
111 - <collection href="http://example.org/sidebar/list" >  
112 - <atom:title>Remaindered Links</atom:title>  
113 - <accept>application/atom+xml;type=entry</accept>  
114 - <categories fixed="yes">  
115 - <atom:category scheme="http://example.org/extra-cats/" term="joke" />  
116 - <atom:category scheme="http://example.org/extra-cats/" term="serious" />  
117 - </categories>  
118 - </collection>  
119 - </workspace>  
120 -</service> 96 + <?xml version="1.0" encoding="utf-8"?>
  97 + <service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
  98 + <workspace>
  99 + <atom:title>Main Site</atom:title>
  100 + <collection href="http://example.org/blog/main" >
  101 + <atom:title>My Blog Entries</atom:title>
  102 + <categories href="http://example.com/cats/forMain.cats" />
  103 + </collection>
  104 + <collection href="http://example.org/blog/pic" >
  105 + <atom:title>Pictures</atom:title>
  106 + <accept>image/png</accept>
  107 + <accept>image/jpeg</accept>
  108 + <accept>image/gif</accept>
  109 + </collection>
  110 + </workspace>
  111 + <workspace>
  112 + <atom:title>Sidebar Blog</atom:title>
  113 + <collection href="http://example.org/sidebar/list" >
  114 + <atom:title>Remaindered Links</atom:title>
  115 + <accept>application/atom+xml;type=entry</accept>
  116 + <categories fixed="yes">
  117 + <atom:category scheme="http://example.org/extra-cats/" term="joke" />
  118 + <atom:category scheme="http://example.org/extra-cats/" term="serious" />
  119 + </categories>
  120 + </collection>
  121 + </workspace>
  122 + </service>
121 123
122 */ 124 */
123 125