Commit 07800ae62e89f829fe4ef2170376a29b4e55d27d

Authored by Paul Barrett
1 parent fa3eed7c

AtomPub support for create folder and create document via CMIS API. internal se…

…rvice auth support via APACHE (note that auth will fail if PHP is run as a CGI module).  Attempt to re-use sessions in ktcmis (untested).

Committed by: Paul Barrett
lib/api/ktcmis/config/repositories.xml
... ... @@ -13,7 +13,7 @@
13 13 <repositoryURI>http://127.0.0.1/</repositoryURI>
14 14 <repositoryInfo>
15 15 <repositoryId>0ad7de04-7914-41b1-b5ee-be9f0b626437</repositoryId>
16   - <repositoryName>KnowledgeTree</repositoryName>
  16 + <repositoryName>KnowledgeTree DMS</repositoryName>
17 17 <repositoryRelationship>self</repositoryRelationship>
18 18 <repositoryDescription>KnowledgeTree Repository</repositoryDescription>
19 19 <vendorName>KnowledgeTree</vendorName>
... ...
lib/api/ktcmis/ktcmis.inc.php
... ... @@ -70,18 +70,23 @@ class KTCMISBase {
70 70 // TODO try to pick up existing session if possible, i.e. if the $session value is not empty
71 71 public function startSession($username, $password)
72 72 {
73   - if (is_null(self::$session))
  73 +// echo $username." :: ".$password."<BR>";
  74 + // attempt to recover session if one exists
  75 + if (!is_null(self::$session) && !PEAR::isError(self::$session))
74 76 {
75   - self::$ktapi = new KTAPI();
76   - self::$session =& self::$ktapi->start_session($username, $password);
  77 +// echo "ATTEMPT TO RECOVER SESSION: ".print_r(self::$session, true)."<BR>\n";
  78 + self::$session =& self::$ktapi->get_active_session(self::$session->get_sessionid());
77 79 }
78   - else
  80 +
  81 + // start new session if no existing session or problem getting existing session (expired, etc...)
  82 + if (is_null(self::$session) || PEAR::isError(self::$session))
79 83 {
80   - // add session restart code here
81   - self::$session =& self::$ktapi->get_active_session(self::$session->get_sessionid());
  84 +// echo "ATTEMPT TO START NEW SESSION<BR>\n";
  85 + self::$ktapi = new KTAPI();
  86 + self::$session =& self::$ktapi->start_session($username, $password);
82 87 }
83 88  
84   - //var_dump(self::$ktapi);
  89 +// print_r(self::$ktapi);
85 90 return self::$session;
86 91 }
87 92  
... ... @@ -90,6 +95,11 @@ class KTCMISBase {
90 95 return self::$ktapi;
91 96 }
92 97  
  98 + public function getSession()
  99 + {
  100 + return self::$session;
  101 + }
  102 +
93 103 // TODO what about destroying sessions? only on logout (which is not offered by the CMIS clients tested so far)
94 104 }
95 105  
... ...
lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
... ... @@ -110,6 +110,7 @@ class CMISDocumentObject extends CMISBaseObject {
110 110 }
111 111  
112 112 $objectProperties = $object->get_detail();
  113 +// print_r($objectProperties);
113 114  
114 115 $this->_setPropertyInternal('ObjectId', CMISUtil::encodeObjectId($this->typeId, $objectProperties['document_id']));
115 116 // prevent doubled '/' chars
... ... @@ -131,6 +132,7 @@ class CMISDocumentObject extends CMISBaseObject {
131 132 $this->_setPropertyInternal('LastModificationDate', $objectProperties['modified_date']);
132 133 $this->_setPropertyInternal('ChangeToken', null);
133 134 $this->_setPropertyInternal('Name', $objectProperties['title']);
  135 + $this->_setPropertyInternal('ParentId', $objectProperties['folder_id']);
134 136 $this->_setPropertyInternal('IsImmutable', $objectProperties['is_immutable']);
135 137 // NOTE if access to older versions is allowed, this will need to be checked, else just set to yes
136 138 // see ktapi::get_document_version_history
... ...
lib/api/ktcmis/services/CMISObjectService.inc.php
... ... @@ -262,6 +262,12 @@ class CMISObjectService {
262 262 throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')');
263 263 }
264 264  
  265 + // TODO if name is blank! throw another exception (check type) - using RuntimeException for now
  266 + if (trim($properties['name']) == '')
  267 + {
  268 + throw new RuntimeException('Refusing to create an un-named folder');
  269 + }
  270 +
265 271 $response = $this->ktapi->create_folder((int)$folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = '');
266 272 if ($response['status_code'] != 0)
267 273 {
... ...
lib/api/ktcmis/util/CMISUtil.inc.php
... ... @@ -86,6 +86,12 @@ class CMISUtil {
86 86 */
87 87 static public function decodeObjectId($objectId, &$typeId = null)
88 88 {
  89 + if (!is_string($objectId))
  90 + {
  91 + $typeId = 'Unknown';
  92 + return null;
  93 + }
  94 +
89 95 $typeId = null;
90 96  
91 97 preg_match('/(\D)(\d*)/', $objectId, $matches);
... ... @@ -240,14 +246,11 @@ class CMISUtil {
240 246 'value' => $properties->getValue('Name'));
241 247 $object['Author'] = array('value' => $properties->getValue('Author'));
242 248  
243   - if (strtolower($properties->getValue('ObjectTypeId')) == 'folder')
244   - {
245   - $object['properties']['ParentId'] = array('type' => $properties->getFieldType('ParentId'),
246   - 'value' => CMISUtil::encodeObjectId('Folder',
247   - $properties->getValue('ParentId')));
248   - }
  249 + $object['properties']['ParentId'] = array('type' => $properties->getFieldType('ParentId'),
  250 + 'value' => CMISUtil::encodeObjectId('Folder',
  251 + $properties->getValue('ParentId')));
249 252 // TODO should check for content stream data before filling these in
250   - else //if ()
  253 + if (strtolower($properties->getValue('ObjectTypeId')) == 'document')
251 254 {
252 255 $object['properties']['ContentStreamLength'] = array('type' => $properties->getFieldType('ContentStreamLength'),
253 256 'value' => $properties->getValue('ContentStreamLength'));
... ...
webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
... ... @@ -17,14 +17,15 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
17 17 {
18 18 public function GET_action()
19 19 {
20   - $username = $password = 'admin';
21 20 $RepositoryService = new RepositoryService();
22   - $RepositoryService->startSession($username, $password);
  21 + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
23 22 $repositories = $RepositoryService->getRepositories();
24 23 $repositoryId = $repositories[0]['repositoryId'];
25   -//var_dump($RepositoryService->ktapi);
26   -// $folderId = $this->getFolderData();
27 24  
  25 + // TODO implement full path/node separation as with Alfresco - i.e. path requests come in on path/ and node requests come in on node/
  26 + // path request e.g.: Root Folder/DroppedDocuments
  27 + // node request e.g.: F1/children
  28 + // node request e.g.: F2
28 29 if (urldecode($this->params[0]) == 'Root Folder')
29 30 {
30 31 $folderId = CMISUtil::encodeObjectId('Folder', 1);
... ... @@ -35,35 +36,28 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
35 36 {
36 37 $ktapi =& $RepositoryService->getInterface();
37 38 $folderId = KT_cmis_atom_service_helper::getFolderId($this->params, $ktapi);
38   -// echo "DA FOLDER ID IS $folderId<BR>";
39 39 }
40 40 else
41 41 {
42 42 $folderId = $this->params[0];
43   -// // get folder name from id, using the ObjectService methods
44   -// $ObjectService = new ObjectService();
45   -//// var_dump($ObjectService->ktapi);
46   -// $ObjectService->setInterface();
47   -// $cmisProps = $ObjectService->getProperties($repositoryId, $folderId, false, false);
48   -//// var_dump($cmisObject);
49   -//// $props = $cmisObject->getProperties();
50   -//// var_dump($props);
51   -// $folderName = $cmisProps['properties']['Name']['value'];
  43 + $ObjectService = new ObjectService();
  44 + $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
  45 + $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false);
  46 + $folderName = $cmisEntry['properties']['Name']['value'];
  47 +// $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $newObjectId, $cmisEntry['properties']['Name']['value']);
52 48 }
53 49  
54   - $username = $password = 'admin';
55 50 if (!empty($this->params[1]) && (($this->params[1] == 'children') || ($this->params[1] == 'descendants')))
56 51 {
57 52 $NavigationService = new NavigationService();
58   - $NavigationService->startSession($username, $password);
  53 + $NavigationService->startSession(self::$authData['username'], self::$authData['password']);
59 54  
60 55 $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $this->params[1]);
61 56 }
62 57 else
63 58 {
64   -// echo "UHUHUHUHUH: $folderId<BR>\n";
65 59 $ObjectService = new ObjectService();
66   - $ObjectService->startSession($username, $password);
  60 + $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
67 61  
68 62 $feed = $this->getFolderFeed($ObjectService, $repositoryId, $folderId);
69 63 }
... ... @@ -71,6 +65,84 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
71 65 //Expose the responseFeed
72 66 $this->responseFeed = $feed;
73 67 }
  68 +
  69 + public function POST_action()
  70 + {
  71 +// $username = $password = 'admin';
  72 + $RepositoryService = new RepositoryService();
  73 + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
  74 + $repositories = $RepositoryService->getRepositories();
  75 + $repositoryId = $repositories[0]['repositoryId'];
  76 +
  77 + $folderId = $this->params[0];
  78 + $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title');
  79 + $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary');
  80 +
  81 + $properties = array('name' => $title, 'summary' => $summary);
  82 +
  83 + // determine whether this is a folder or a document create
  84 + // document create will have a content tag <atom:content> or <content> containing base64 encoding of the document
  85 + $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content');
  86 + if (is_null($content))
  87 + $type = 'folder';
  88 + else
  89 + $type = 'document';
  90 +
  91 + // TODO what if mime-type is incorrect? CMISSpaces appears to be sending text/plain on an executable file.
  92 + // perhaps because the content is text/plain once base64 encoded?
  93 + // How to determine the actual content type?
  94 + /*
  95 + * <atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:cmis="http://www.cmis.org/2008/05">
  96 + * <atom:title>setup.txt</atom:title>
  97 + * <atom:summary>setup.txt</atom:summary>
  98 + * <atom:content type="text/plain">dGhpcyBiZSBzb21lIHRlc3QgY29udGVudCBmb3IgYSBkb2N1bWVudCwgeWVzPw==</atom:content>
  99 + * <cmis:object>
  100 + * <cmis:properties>
  101 + * <cmis:propertyString cmis:name="ObjectTypeId"><cmis:value>document</cmis:value></cmis:propertyString>
  102 + * </cmis:properties>
  103 + * </cmis:object>
  104 + * </atom:entry>
  105 + */
  106 +
  107 + $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']['cmis:object']
  108 + [0]['@children']['cmis:properties']
  109 + [0]['@children']);
  110 +
  111 + $ObjectService = new ObjectService();
  112 + $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
  113 + if ($type == 'folder')
  114 + $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId);
  115 + else
  116 + $newObjectId = $ObjectService->createDocument($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId, $content);
  117 +
  118 + // check if returned Object Id is a valid CMIS Object Id
  119 + $dummy = CMISUtil::decodeObjectId($newObjectId, $typeId);
  120 + if ($typeId != 'Unknown')
  121 + {
  122 + $this->setStatus(self::STATUS_CREATED);
  123 + if ($type == 'folder')
  124 + {
  125 + $feed = $this->getFolderFeed($ObjectService, $repositoryId, $newObjectId);
  126 + }
  127 + else
  128 + {
  129 + $NavigationService = new NavigationService();
  130 + $NavigationService->startSession(self::$authData['username'], self::$authData['password']);
  131 + $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false);
  132 + $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $cmisEntry['properties']['Name']['value']);
  133 + }
  134 + }
  135 + else
  136 + {
  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);
  141 + }
  142 +
  143 + //Expose the responseFeed
  144 + $this->responseFeed = $feed;
  145 + }
74 146  
75 147 /**
76 148 * Retrieves children/descendants of the specified folder
... ... @@ -81,7 +153,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
81 153 * @param string $feedType children or descendants
82 154 * @return string CMIS AtomPub feed
83 155 */
84   - private function getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $feedType)
  156 + private function getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $feedType = 'children')
85 157 {
86 158 if ($feedType == 'children')
87 159 {
... ... @@ -136,34 +208,6 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service
136 208  
137 209 return $feed;
138 210 }
139   -
140   - // FIXME change how the drupal module works so that we don't need this anymore
141   - private function getFolderData($query, &$folderName)
142   - {
143   - // FIXME really need to to avoid this!
144   - $ktapi = new KTAPI();
145   - $ktapi->start_session('admin', 'admin');
146   -
147   - $numQ = count($query);
148   - $numFolders = $numQ-3;
149   - $folderId = 1;
150   -
151   - if ($query[$numQ-1] == 'children' || $query[$numQ-1] == 'descendants')
152   - {
153   - $tree = $query[$numQ-1];
154   - }
155   -
156   - $start = 0;
157   - while($start < $numFolders-1)
158   - {
159   - $folderName = urldecode($query[$numQ-$numFolders+$start]);
160   - $folder = $ktapi->get_folder_by_name($folderName, $folderId);
161   - $folderId = $folder->get_folderid();
162   - ++$start;
163   - }
164   -
165   - return CMISUtil::encodeObjectId('Folder', $folderId);
166   - }
167 211 }
168 212  
169 213 /**
... ... @@ -176,11 +220,11 @@ class KT_cmis_atom_service_types extends KT_cmis_atom_service
176 220 {
177 221 public function GET_action()
178 222 {
179   - $username = $password = 'admin';
  223 +// $username = $password = 'admin';
180 224 $RepositoryService = new RepositoryService();
181 225 // technically do not need to log in to access this information
182 226 // TODO consider requiring authentication even to access basic repository information
183   - $RepositoryService->startSession($username, $password);
  227 + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
184 228  
185 229 // fetch repository id
186 230 $repositories = $RepositoryService->getRepositories();
... ... @@ -205,11 +249,11 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service
205 249 {
206 250 public function GET_action()
207 251 {
208   - $username = $password = 'admin';
  252 +// $username = $password = 'admin';
209 253 $RepositoryService = new RepositoryService();
210 254 // technically do not need to log in to access this information
211 255 // TODO consider requiring authentication even to access basic repository information
212   - $RepositoryService->startSession($username, $password);
  256 + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
213 257  
214 258 // fetch repository id
215 259 $repositories = $RepositoryService->getRepositories();
... ... @@ -303,11 +347,11 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service
303 347 {
304 348 public function GET_action()
305 349 {
306   - $username = $password = 'admin';
  350 +// $username = $password = 'admin';
307 351 $RepositoryService = new RepositoryService();
308 352 $NavigationService = new NavigationService();
309 353  
310   - $NavigationService->startSession($username, $password);
  354 + $NavigationService->startSession(self::$authData['username'], self::$authData['password']);
311 355  
312 356 $repositories = $RepositoryService->getRepositories();
313 357 $repositoryId = $repositories[0]['repositoryId'];
... ... @@ -354,11 +398,11 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service
354 398 {
355 399 public function GET_action()
356 400 {
357   - $username = $password = 'admin';
  401 +// $username = $password = 'admin';
358 402 $RepositoryService = new RepositoryService();
359 403  
360 404 $ObjectService = new ObjectService();
361   - $ObjectService->startSession($username, $password);
  405 + $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
362 406  
363 407 $repositories = $RepositoryService->getRepositories();
364 408 $repositoryId = $repositories[0]['repositoryId'];
... ...
webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php
... ... @@ -16,20 +16,22 @@ class KT_cmis_atom_service_helper {
16 16 // . strtolower($cmisEntry['properties']['ObjectTypeId']['value']), $entry);
17 17  
18 18 // echo $_SERVER['QUERY_STRING']."<BR>\n";
19   - preg_match('/^\/?[^\/]*\/folder\/(.*)\/[^\/]*\/?$/', trim($_SERVER['QUERY_STRING'], '/'), $matches);
20   - $path = $matches[1];
21   - $parent = preg_replace('/\/[^\/]*$/', '', $path);
22   - // TODO fix path to work on old method, after fixing drupal module to not require extended path
  19 +// preg_match('/^\/?[^\/]*\/folder\/(.*)\/[^\/]*\/?$/', trim($_SERVER['QUERY_STRING'], '/'), $matches);
  20 +// $path = $matches[1];
  21 +// $parent = preg_replace('/\/[^\/]*$/', '', $path);
  22 +// // TODO fix path to work on old method, after fixing drupal module to not require extended path
  23 +//
  24 +// $path = '';
23 25  
24 26 $id = $cmisEntry['properties']['ObjectId']['value'];
25 27 $entry = $feed->newEntry();
26 28 $feed->newField('id', 'urn:uuid:' . $id, $entry);
27   -
  29 +// print_r($cmisEntry);
28 30 // links
29 31 // TODO check parent link is correct, fix if needed
30 32 $link = $feed->newElement('link');
31 33 $link->appendChild($feed->newAttr('rel','cmis-parent'));
32   - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/folder/' . $path));
  34 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/folder/' . $cmisEntry['properties']['ParentId']['value']));
33 35 $entry->appendChild($link);
34 36  
35 37 if (strtolower($cmisEntry['properties']['ObjectTypeId']['value']) == 'folder')
... ... @@ -37,20 +39,20 @@ class KT_cmis_atom_service_helper {
37 39 // TODO check parent link is correct, fix if needed
38 40 $link = $feed->newElement('link');
39 41 $link->appendChild($feed->newAttr('rel','cmis-folderparent'));
40   - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/folder/' . $path));
  42 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/folder/' . $cmisEntry['properties']['ParentId']['value']));
41 43 $entry->appendChild($link);
42 44 $link = $feed->newElement('link');
43 45 $link->appendChild($feed->newAttr('rel','cmis-children'));
44 46 $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/'
45 47 . strtolower($cmisEntry['properties']['ObjectTypeId']['value'])
46   - . '/' . $path . '/' . rawurlencode($cmisEntry['properties']['Name']['value'])
  48 + . '/' . $cmisEntry['properties']['ObjectId']['value']
47 49 . '/children'));
48 50 $entry->appendChild($link);
49 51 $link = $feed->newElement('link');
50 52 $link->appendChild($feed->newAttr('rel','cmis-descendants'));
51 53 $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/'
52 54 . strtolower($cmisEntry['properties']['ObjectTypeId']['value'])
53   - . '/' . $path . '/' . rawurlencode($cmisEntry['properties']['Name']['value'])
  55 + . '/' . $cmisEntry['properties']['ObjectId']['value']
54 56 . '/descendants'));
55 57 $entry->appendChild($link);
56 58 }
... ... @@ -164,18 +166,12 @@ class KT_cmis_atom_service_helper {
164 166 // TODO make this much more efficient than this messy method
165 167 static public function getFolderId($path, &$ktapi)
166 168 {
167   -// static public function getFolderData($query, &$folderName, &$tree)
168   -// $ktapi = new KTAPI();
169   -// $ktapi->start_session('admin', 'admin');
170   -
171 169 // lose first item
172 170 array_shift($path);
173 171  
174 172 $numQ = count($path);
175   -// echo $numQ."<BR>";
176 173 $numFolders = $numQ;
177 174 $folderId = 1;
178   -// echo $numFolders."<BR>";
179 175  
180 176 $start = 0;
181 177 while($start < $numFolders)
... ... @@ -184,10 +180,7 @@ class KT_cmis_atom_service_helper {
184 180 // hack to fix drupal url encoding issue
185 181 $name = str_replace('%2520', '%20', $name);
186 182  
187   -// echo $name."<BR>";
188   -
189 183 $folderName = urldecode($name);
190   -// echo $folderName."<BR>";
191 184 $folder = $ktapi->get_folder_by_name($folderName, $folderId);
192 185 $folderId = $folder->get_folderid();
193 186 ++$start;
... ... @@ -196,6 +189,31 @@ class KT_cmis_atom_service_helper {
196 189 return CMISUtil::encodeObjectId('Folder', $folderId);
197 190 }
198 191  
  192 + static public function getCmisProperties($xmlArray)
  193 + {
  194 + $properties = array();
  195 +
  196 + foreach($xmlArray as $cmisPropertyDefinition)
  197 + {
  198 + foreach($cmisPropertyDefinition as $propertyType => $propertyDefinition)
  199 + {
  200 + $properties[$propertyDefinition['@attributes']['cmis:name']] = $propertyDefinition['@children']['cmis:value'][0]['@value'];
  201 + }
  202 + }
  203 +
  204 + return $properties;
  205 + }
  206 +
  207 + static public function getAtomValues($xmlArray, $tag)
  208 + {
  209 + if (!is_null($xmlArray['atom:'.$tag]))
  210 + return $xmlArray['atom:'.$tag][0]['@value'];
  211 + else if (!is_null($xmlArray[$tag]))
  212 + return $xmlArray[$tag][0]['@value'];
  213 +
  214 + return null;
  215 + }
  216 +
199 217 }
200 218  
201 219 ?>
... ...
webservice/atompub/cmis/index.php
... ... @@ -59,6 +59,7 @@ $password = $_SERVER[&#39;PHP_AUTH_PW&#39;];
59 59 /**
60 60 * Includes
61 61 */
  62 +include_once(KT_ATOM_LIB_FOLDER.'XMLns2array.inc.php');
62 63 include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_server.inc.php');
63 64 include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_baseDoc.inc.php');
64 65 include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_responseFeed.inc.php'); //Containing the response feed class allowing easy atom feed generation
... ... @@ -66,7 +67,6 @@ include_once(CMIS_ATOM_LIB_FOLDER.&#39;KT_cmis_atom_serviceDoc.inc.php&#39;); /
66 67 include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_service.inc.php'); //Containing the servicedoc class allowing easy ServiceDocument generation
67 68  
68 69 include_once('KT_cmis_atom_server.services.inc.php');
69   -
70 70 //Start the AtomPubProtocol Routing Engine
71 71 $APP = new KT_cmis_atom_server();
72 72  
... ... @@ -91,7 +91,6 @@ $APP-&gt;addWorkspaceTag(&#39;dms&#39;,&#39;atom:title&#39;,$APP-&gt;repositoryInfo[&#39;repositoryName&#39;])
91 91 * http://ktatompub/{folder/folder2/folder3/}service/param1/param2
92 92 */
93 93 // TODO consider a registerServices function which will, dependant on what is requested, register the appropriate services, keep the logic out of the index file
94   -// FIXME HACK! this should not happen every time, ONLY on a service doc request, except for request specific collection links
95 94 $APP->registerService('dms', 'folder', 'KT_cmis_atom_service_folder', 'Root Folder Children Collection',
96 95 array(rawurlencode($APP->repositoryInfo['rootFolderId']), 'children'), 'root-children');
97 96 $APP->registerService('dms', 'folder', 'KT_cmis_atom_service_folder', 'Root Folder Children Collection',
... ...
webservice/classes/atompub/KT_atom_server.inc.php
... ... @@ -21,11 +21,10 @@ class KT_atom_server{
21 21 *
22 22 */
23 23 public function execute(){
24   -// $_SERVER['QUERY_STRING'] = urldecode($_SERVER['QUERY_STRING']);
25 24 $reqMethod=trim(strtoupper($_SERVER['REQUEST_METHOD']));
26 25 $queryArray=split('/',trim($_SERVER['QUERY_STRING'],'/'));
27 26 $rawRequest=@file_get_contents('php://input');
28   -//echo "\n\n".rawurldecode($_SERVER['QUERY_STRING'])."<BR><BR>\n\n";
  27 +
29 28 $workspace=strtolower(trim($queryArray[0]));
30 29 $serviceName=strtolower(trim($queryArray[1]));
31 30 $requestParams=array_slice($queryArray,2);
... ... @@ -33,7 +32,7 @@ class KT_atom_server{
33 32 $this->serviceName=$serviceName;
34 33 $this->method=$reqMethod;
35 34 $this->workspace=$workspace;
36   -
  35 +
37 36 if($workspace=='servicedocument'){
38 37 $this->serviceDocument();
39 38 return;
... ...
webservice/classes/atompub/KT_atom_service.inc.php
1 1 <?php
2 2 class KT_atom_service{
3   - const STATUS_OK ='200 OK';
4   - const STATUS_NOT_FOUND ='204 No Content';
5   - const STATUS_NOT_ALLOWED ='204 Not Allowed';
6   - const STATUS_NOT_AUTHENTICATED ='204 Not Authenticated';
7   - const STATUS_CREATED ='201 Created';
8   - const STATUS_UPDATED ='200 Updated';
9   - const STATUS_NOT_MODIFIED ='304 Not Modified'; //For use with ETag & If-None-Match headers.
10   - 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
  3 + const STATUS_OK = '200 OK';
  4 + const STATUS_NOT_FOUND = '204 No Content';
  5 + const STATUS_NOT_ALLOWED = '204 Not Allowed';
  6 + const STATUS_NOT_AUTHENTICATED = '204 Not Authenticated';
  7 + const STATUS_CREATED = '201 Created';
  8 + const STATUS_UPDATED = '200 Updated';
  9 + 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
  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
11 13  
12 14 public $responseFeed=NULL;
13 15 public $responseHeader=NULL;
... ... @@ -59,11 +61,17 @@ class KT_atom_service{
59 61 return $this->responseFeed->render();
60 62 }
61 63  
62   - protected function xml2array($xml){
63   - if(class_exists('')){
  64 + protected function xml2array($xml)
  65 + {
  66 + if (trim($xml) == '') return array();
  67 +
  68 + if(class_exists('XMLns2array'))
  69 + {
64 70 $array=XMLns2array::parse($xml);
65   - }else{
66   - $array=json_decode(json_encode(@simplexml_load_string($xml)),true);
  71 + }
  72 + else
  73 + {
  74 + $array=json_decode(json_encode(@simplexml_load_string($xml)), true);
67 75 }
68 76 return $array;
69 77 }
... ...
webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php
... ... @@ -6,5 +6,31 @@ class KT_cmis_atom_service extends KT_atom_service {
6 6  
7 7 // override and extend as needed
8 8  
  9 + static protected $authData = array();
  10 +
  11 + protected function parseHeaders()
  12 + {
  13 +// echo "PARSE HEADERS\n";
  14 + 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
  19 + if (!empty($this->headers['Authorization']))
  20 + {
  21 + $auth = base64_decode(preg_replace('/Basic */', '', $this->headers['Authorization']));
  22 + $authData = explode(':', $auth);
  23 +// print_r($authData);
  24 + self::$authData['username'] = $authData[0];
  25 + self::$authData['password'] = $authData[1];
  26 + }
  27 + // if failed, attempt to fetch from $_SERVER array instead
  28 + else if (isset($_SERVER['PHP_AUTH_USER']))
  29 + {
  30 + self::$authData['username'] = $_SERVER['PHP_AUTH_USER'];
  31 + self::$authData['password'] = $_SERVER['PHP_AUTH_PW'];
  32 + }
  33 + }
  34 +
9 35 }
10 36 ?>
11 37 \ No newline at end of file
... ...
webservice/classes/atompub/cmis/ObjectService.inc.php
... ... @@ -32,6 +32,59 @@ class ObjectService extends KTObjectService {
32 32 }
33 33 }
34 34  
  35 + /**
  36 + * Creates a new folder within the repository
  37 + *
  38 + * @param string $repositoryId The repository to which the folder must be added
  39 + * @param string $typeId Object Type id for the folder object being created
  40 + * @param array $properties Array of properties which must be applied to the created folder object
  41 + * @param string $folderId The id of the folder which will be the parent of the created folder object
  42 + * @return string $objectId The id of the created folder object
  43 + */
  44 + function createFolder($repositoryId, $typeId, $properties, $folderId)
  45 + {
  46 + $result = parent::createFolder($repositoryId, $typeId, $properties, $folderId);
  47 +
  48 + if ($result['status_code'] == 0)
  49 + {
  50 + return $result['results'];
  51 + }
  52 + else
  53 + {
  54 + return $result;
  55 + }
  56 + }
  57 +
  58 + /**
  59 + * Creates a new document within the repository
  60 + *
  61 + * @param string $repositoryId The repository to which the document must be added
  62 + * @param string $typeId Object Type id for the document object being created
  63 + * @param array $properties Array of properties which must be applied to the created document object
  64 + * @param string $folderId The id of the folder which will be the parent of the created document object
  65 + * This parameter is optional IF unfilingCapability is supported
  66 + * @param contentStream $contentStream optional content stream data
  67 + * @param string $versioningState optional version state value: checkedout/major/minor
  68 + * @return string $objectId The id of the created folder object
  69 + */
  70 + // TODO throw ConstraintViolationException if:
  71 + // value of any of the properties violates the min/max/required/length constraints
  72 + // specified in the property definition in the Object-Type.
  73 + function createDocument($repositoryId, $typeId, $properties, $folderId = null,
  74 + $contentStream = null, $versioningState = null)
  75 + {
  76 + $result = parent::createDocument($repositoryId, $typeId, $properties, $folderId, $contentStream, $versioningState);
  77 +
  78 + if ($result['status_code'] == 0)
  79 + {
  80 + return $result['results'];
  81 + }
  82 + else
  83 + {
  84 + return $result;
  85 + }
  86 + }
  87 +
35 88 }
36 89  
37 90 ?>
... ...