diff --git a/lib/api/ktcmis/config/repositories.xml b/lib/api/ktcmis/config/repositories.xml index 8f65088..71ed7ad 100644 --- a/lib/api/ktcmis/config/repositories.xml +++ b/lib/api/ktcmis/config/repositories.xml @@ -13,7 +13,7 @@ http://127.0.0.1/ 0ad7de04-7914-41b1-b5ee-be9f0b626437 - KnowledgeTree + KnowledgeTree DMS self KnowledgeTree Repository KnowledgeTree diff --git a/lib/api/ktcmis/ktcmis.inc.php b/lib/api/ktcmis/ktcmis.inc.php index 1c83cba..88fc291 100644 --- a/lib/api/ktcmis/ktcmis.inc.php +++ b/lib/api/ktcmis/ktcmis.inc.php @@ -62,27 +62,42 @@ require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); */ class KTCMISBase { - /** - * KnowledgeTree API instance - * - * @var object - */ - protected $ktapi; - /** - * KnowledgeTree API Session Identifier - * - * @var object - */ - protected $session; + // we want all child classes to share the ktapi and session instances, no matter where they are set from, + // so we declare them as static + static protected $ktapi; + static protected $session; + // TODO try to pick up existing session if possible, i.e. if the $session value is not empty public function startSession($username, $password) { - $this->session = null; +// echo $username." :: ".$password."
"; + // attempt to recover session if one exists + if (!is_null(self::$session) && !PEAR::isError(self::$session)) + { +// echo "ATTEMPT TO RECOVER SESSION: ".print_r(self::$session, true)."
\n"; + self::$session =& self::$ktapi->get_active_session(self::$session->get_sessionid()); + } + + // start new session if no existing session or problem getting existing session (expired, etc...) + if (is_null(self::$session) || PEAR::isError(self::$session)) + { +// echo "ATTEMPT TO START NEW SESSION
\n"; + self::$ktapi = new KTAPI(); + self::$session =& self::$ktapi->start_session($username, $password); + } + +// print_r(self::$ktapi); + return self::$session; + } - $this->ktapi = new KTAPI(); - $this->session =& $this->ktapi->start_session($username, $password); + public function getInterface() + { + return self::$ktapi; + } - return $this->session; + public function getSession() + { + return self::$session; } // TODO what about destroying sessions? only on logout (which is not offered by the CMIS clients tested so far) @@ -244,7 +259,13 @@ class KTNavigationService extends KTCMISBase { public function startSession($username, $password) { parent::startSession($username, $password); - $this->NavigationService->setInterface($this->ktapi); + $this->setInterface(); + return self::$session; + } + + public function setInterface() + { + $this->NavigationService->setInterface(self::$ktapi); } /** @@ -426,11 +447,17 @@ class KTObjectService extends KTCMISBase { // instantiate underlying CMIS service $this->ObjectService = new CMISObjectService(); } - + public function startSession($username, $password) { parent::startSession($username, $password); - $this->ObjectService->setInterface($this->ktapi); + $this->setInterface(); + return self::$session; + } + + public function setInterface() + { + $this->ObjectService->setInterface(self::$ktapi); } /** diff --git a/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php b/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php index cd9024e..6307e30 100644 --- a/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php +++ b/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php @@ -110,6 +110,7 @@ class CMISDocumentObject extends CMISBaseObject { } $objectProperties = $object->get_detail(); +// print_r($objectProperties); $this->_setPropertyInternal('ObjectId', CMISUtil::encodeObjectId($this->typeId, $objectProperties['document_id'])); // prevent doubled '/' chars @@ -131,6 +132,7 @@ class CMISDocumentObject extends CMISBaseObject { $this->_setPropertyInternal('LastModificationDate', $objectProperties['modified_date']); $this->_setPropertyInternal('ChangeToken', null); $this->_setPropertyInternal('Name', $objectProperties['title']); + $this->_setPropertyInternal('ParentId', $objectProperties['folder_id']); $this->_setPropertyInternal('IsImmutable', $objectProperties['is_immutable']); // NOTE if access to older versions is allowed, this will need to be checked, else just set to yes // see ktapi::get_document_version_history diff --git a/lib/api/ktcmis/services/CMISObjectService.inc.php b/lib/api/ktcmis/services/CMISObjectService.inc.php index 0a7f0e3..0ddab6f 100644 --- a/lib/api/ktcmis/services/CMISObjectService.inc.php +++ b/lib/api/ktcmis/services/CMISObjectService.inc.php @@ -262,6 +262,12 @@ class CMISObjectService { throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')'); } + // TODO if name is blank! throw another exception (check type) - using RuntimeException for now + if (trim($properties['name']) == '') + { + throw new RuntimeException('Refusing to create an un-named folder'); + } + $response = $this->ktapi->create_folder((int)$folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = ''); if ($response['status_code'] != 0) { diff --git a/lib/api/ktcmis/util/CMISUtil.inc.php b/lib/api/ktcmis/util/CMISUtil.inc.php index 8740f84..8506d54 100644 --- a/lib/api/ktcmis/util/CMISUtil.inc.php +++ b/lib/api/ktcmis/util/CMISUtil.inc.php @@ -86,6 +86,12 @@ class CMISUtil { */ static public function decodeObjectId($objectId, &$typeId = null) { + if (!is_string($objectId)) + { + $typeId = 'Unknown'; + return null; + } + $typeId = null; preg_match('/(\D)(\d*)/', $objectId, $matches); @@ -240,14 +246,11 @@ class CMISUtil { 'value' => $properties->getValue('Name')); $object['Author'] = array('value' => $properties->getValue('Author')); - if (strtolower($properties->getValue('ObjectTypeId')) == 'folder') - { - $object['properties']['ParentId'] = array('type' => $properties->getFieldType('ParentId'), - 'value' => CMISUtil::encodeObjectId('Folder', - $properties->getValue('ParentId'))); - } + $object['properties']['ParentId'] = array('type' => $properties->getFieldType('ParentId'), + 'value' => CMISUtil::encodeObjectId('Folder', + $properties->getValue('ParentId'))); // TODO should check for content stream data before filling these in - else //if () + if (strtolower($properties->getValue('ObjectTypeId')) == 'document') { $object['properties']['ContentStreamLength'] = array('type' => $properties->getFieldType('ContentStreamLength'), 'value' => $properties->getValue('ContentStreamLength')); diff --git a/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php b/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php new file mode 100644 index 0000000..dbbacf7 --- /dev/null +++ b/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php @@ -0,0 +1,886 @@ +startSession(self::$authData['username'], self::$authData['password']); + $repositories = $RepositoryService->getRepositories(); + $repositoryId = $repositories[0]['repositoryId']; + + // TODO implement full path/node separation as with Alfresco - i.e. path requests come in on path/ and node requests come in on node/ + // path request e.g.: Root Folder/DroppedDocuments + // node request e.g.: F1/children + // node request e.g.: F2 + if (urldecode($this->params[0]) == 'Root Folder') + { + $folderId = CMISUtil::encodeObjectId('Folder', 1); + $folderName = urldecode($this->params[0]); + } + // 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... + else if ($this->params[0] == 'path') + { + $ktapi =& $RepositoryService->getInterface(); + $folderId = KT_cmis_atom_service_helper::getFolderId($this->params, $ktapi); + } + else + { + $folderId = $this->params[0]; + $ObjectService = new ObjectService(); + $ObjectService->startSession(self::$authData['username'], self::$authData['password']); + $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false); + $folderName = $cmisEntry['properties']['Name']['value']; +// $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $newObjectId, $cmisEntry['properties']['Name']['value']); + } + + if (!empty($this->params[1]) && (($this->params[1] == 'children') || ($this->params[1] == 'descendants'))) + { + $NavigationService = new NavigationService(); + $NavigationService->startSession(self::$authData['username'], self::$authData['password']); + + $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $this->params[1]); + } + else + { + $ObjectService = new ObjectService(); + $ObjectService->startSession(self::$authData['username'], self::$authData['password']); + + $feed = $this->getFolderFeed($ObjectService, $repositoryId, $folderId); + } + + //Expose the responseFeed + $this->responseFeed = $feed; + } + + public function POST_action() + { +// $username = $password = 'admin'; + $RepositoryService = new RepositoryService(); + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']); + $repositories = $RepositoryService->getRepositories(); + $repositoryId = $repositories[0]['repositoryId']; + + $folderId = $this->params[0]; + $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title'); + $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary'); + + $properties = array('name' => $title, 'summary' => $summary); + + // determine whether this is a folder or a document create + // document create will have a content tag or containing base64 encoding of the document + $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content'); + if (is_null($content)) + $type = 'folder'; + else + $type = 'document'; + + // TODO what if mime-type is incorrect? CMISSpaces appears to be sending text/plain on an executable file. + // perhaps because the content is text/plain once base64 encoded? + // How to determine the actual content type? + /* + * + * setup.txt + * setup.txt + * dGhpcyBiZSBzb21lIHRlc3QgY29udGVudCBmb3IgYSBkb2N1bWVudCwgeWVzPw== + * + * + * document + * + * + * + */ + + $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']['cmis:object'] + [0]['@children']['cmis:properties'] + [0]['@children']); + + $ObjectService = new ObjectService(); + $ObjectService->startSession(self::$authData['username'], self::$authData['password']); + if ($type == 'folder') + $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId); + else + $newObjectId = $ObjectService->createDocument($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId, $content); + + // check if returned Object Id is a valid CMIS Object Id + $dummy = CMISUtil::decodeObjectId($newObjectId, $typeId); + if ($typeId != 'Unknown') + { + $this->setStatus(self::STATUS_CREATED); + if ($type == 'folder') + { + $feed = $this->getFolderFeed($ObjectService, $repositoryId, $newObjectId); + } + else + { + $NavigationService = new NavigationService(); + $NavigationService->startSession(self::$authData['username'], self::$authData['password']); + $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false); + $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $cmisEntry['properties']['Name']['value']); + } + } + else + { + $this->setStatus(self::STATUS_SERVER_ERROR); + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Error: ' . self::STATUS_SERVER_ERROR); + $entry = $feed->newEntry(); + $feed->newField('error', $newObjectId['message'], $entry); + } + + //Expose the responseFeed + $this->responseFeed = $feed; + } + + /** + * Retrieves children/descendants of the specified folder + * TODO this currently only works in children mode, add descendants + * + * @param string $repositoryId + * @param string $folderId folder id for which children/descendants are requested + * @param string $feedType children or descendants + * @return string CMIS AtomPub feed + */ + private function getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $feedType = 'children') + { + if ($feedType == 'children') + { + $entries = $NavigationService->getChildren($repositoryId, $folderId, false, false); + } + else if ($feedType == 'descendants') + { + $entries = $NavigationService->getDescendants($repositoryId, $folderId, false, false); + } + else + { + // error, we shouldn't be here, if we are then the wrong service/function was called + } + + // $baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $folderName . ' ' . ucwords($feedType), null, null, null, + 'urn:uuid:' . $folderName . '-' . $feedType); + + foreach($entries as $cmisEntry) + { + KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $folderName); + } + + // false + + // global $childrenFeed + // $output = $childrenFeed[0]; + // $output = $childrenFeed[1]; + + return $feed; + } + + /** + * Retrieves data about a specific folder + * + * @param object $ObjectService The CMIS service + * @param string $repositoryId + * @param string $folderId + * @return string CMIS AtomPub feed + */ + private function getFolderFeed($ObjectService, $repositoryId, $folderId) + { + $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false); + + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $cmisEntry['properties']['ObjectTypeId']['value'], null, null, null, + 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value']); + + KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $folderName); +// // false +// // global $folderFeed; +// // $outputs = + + return $feed; + } +} + +/** + * AtomPub Service: types + * + * Returns a list of supported object types + * + */ +class KT_cmis_atom_service_types extends KT_cmis_atom_service +{ + public function GET_action() + { +// $username = $password = 'admin'; + $RepositoryService = new RepositoryService(); + // technically do not need to log in to access this information + // TODO consider requiring authentication even to access basic repository information + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']); + + // fetch repository id + $repositories = $RepositoryService->getRepositories(); + $repositoryId = $repositories[0]['repositoryId']; + + $types = $RepositoryService->getTypes($repositoryId); + $type = ((empty($this->params[0])) ? 'all' : $this->params[0]); + $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types); + + //Expose the responseFeed + $this->responseFeed = $feed; + } +} + +/** + * AtomPub Service: type + * + * Returns the type defintion for the selected type + * + */ +class KT_cmis_atom_service_type extends KT_cmis_atom_service +{ + public function GET_action() + { +// $username = $password = 'admin'; + $RepositoryService = new RepositoryService(); + // technically do not need to log in to access this information + // TODO consider requiring authentication even to access basic repository information + $RepositoryService->startSession(self::$authData['username'], self::$authData['password']); + + // fetch repository id + $repositories = $RepositoryService->getRepositories(); + $repositoryId = $repositories[0]['repositoryId']; + + if (!isset($this->params[1])) + { + // For easier return in the wanted format, we call getTypes instead of getTypeDefinition. + // Calling this with a single type specified returns an array containing the definition of + // just the requested type. + // NOTE could maybe be more efficient to call getTypeDefinition direct and then place in + // an array on this side? or directly expose the individual entry response code and + // call directly from here rather than via getTypeFeed. + $type = ucwords($this->params[0]); + $types = $RepositoryService->getTypes($repositoryId, $type); + $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types); + } + else + { + // TODO dynamic dates, as needed everywhere + // NOTE children of types not yet implemented and we don't support any non-basic types at this time + $feed = $this->getTypeChildrenFeed($this->params[1]); + } + + //Expose the responseFeed + $this->responseFeed=$feed; + } + /** + * Retrieves a list of child types for the supplied type + * + * NOTE this currently returns a hard coded empty list, since we do not currently support child types + * TODO make dynamic if/when we support checking for child types (we don't actually need to support child types themselves) + * + * @param string $type + * @return string CMIS AtomPub feed + */ + private function getTypeChildrenFeed() + { + //Create a new response feed + // $baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Child Types of ' . ucwords($this->params[0]), null, null, null, + $this->params[0] . '-children'); + + // TODO actually fetch child types - to be implemented when we support child types in the API + + // id + + // links + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','first')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'type/' . $this->params[0] . '/' . $this->params[1] . '?pageNo=1&pageSize=0')); + $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=feed')); + + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','last')); + // TODO set page number correctly - to be done when we support paging the the API + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'type/' . $this->params[0] . '/' . $this->params[1] . '?pageNo=1&pageSize=0')); + $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=feed')); + + // TODO actual dynamic listing, currently we have no objects with which to test + + // TODO +// 2009-06-23T13:40:32.786+02:00 +// false +/* + // TODO need to create this dynamically now, will no longer work with static output + $output = ' + + urn:uuid:type-' . $type . '-children + + + + Child types of ' . $type . ' + 2009-06-23T13:40:32.786+02:00 + false + '; +*/ + return $feed; + } + +} + +/** + * AtomPub Service: checkedout + * + * Returns a list of checked out documents for the logged in user + * + */ +// NOTE this is always an empty document, underlying API code still to be implemented +class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service +{ + public function GET_action() + { +// $username = $password = 'admin'; + $RepositoryService = new RepositoryService(); + $NavigationService = new NavigationService(); + + $NavigationService->startSession(self::$authData['username'], self::$authData['password']); + + $repositories = $RepositoryService->getRepositories(); + $repositoryId = $repositories[0]['repositoryId']; + + $checkedout = $NavigationService->getCheckedoutDocs($repositoryId); + + //Create a new response feed + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Checked out Documents', null, null, null, 'urn:uuid:checkedout'); + + foreach($checkedout as $document) + { + $entry = $feed->newEntry(); + $objectElement = $feed->newElement('cmis:object'); + $propertiesElement = $feed->newElement('cmis:properties'); + + foreach($cmisEntry['properties'] as $propertyName => $property) + { + $propElement = $feed->newElement('cmis:' . $property['type']); + $propElement->appendChild($feed->newAttr('cmis:name', $propertyName)); + $feed->newField('cmis:value', CMISUtil::boolToString($property['value']), $propElement); + $propertiesElement->appendChild($propElement); + } + + $objectElement->appendChild($propertiesElement); + $entry->appendChild($objectElement); + } + + $entry = null; + $feed->newField('hasMoreItems', 'false', $entry, true); + + //Expose the responseFeed + $this->responseFeed = $feed; + } + +} + +/** + * AtomPub Service: document + * + * Returns detail on a particular document + * + */ +class KT_cmis_atom_service_document extends KT_cmis_atom_service +{ + public function GET_action() + { +// $username = $password = 'admin'; + $RepositoryService = new RepositoryService(); + + $ObjectService = new ObjectService(); + $ObjectService->startSession(self::$authData['username'], self::$authData['password']); + + $repositories = $RepositoryService->getRepositories(); + $repositoryId = $repositories[0]['repositoryId']; + + $cmisEntry = $ObjectService->getProperties($repositoryId, $this->params[0], false, false); + + //Create a new response feed + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $cmisEntry['properties']['ObjectTypeId']['value'], null, null, null, + 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value']); + + KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $cmisEntry['properties']['ParentId']['value']); + + // false + +// global $docFeed; +// $output = $docFeed; + + //Expose the responseFeed + $this->responseFeed=$feed; + } +} + +$childrenFeed[] = ' + + urn:uuid:28537649-8af2-4c74-aa92-5d8bbecac9ce-children + + Root Folder Children + + urn:uuid:86224486-b7ae-4074-a793-82cd259b0026-folder + + + + + + DroppedDocuments + DroppedDocuments + + + + + F2 + + + Folder + + + DroppedDocuments + + + + + + + urn:uuid:86224486-b7ae-4074-a793-82cd259b0026-folder + + + + + + Test KT Folder + Test KT Folder + + + + F4 + + + + Folder + + + Test KT Folder + + + + + + + admin + urn:uuid:2df9d676-f173-47bb-8ec1-41fa1186b66d + + + + + + + + + + 2009-06-23T09:40:47.889+02:00 + + h4555-cmis-so.pdf + 2009-06-23T09:40:58.524+02:00 + + + + workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d + document + document + admin + + 2009-06-23T09:40:47.889+02:00 + admin + 2009-06-23T09:40:58.524+02:00 + h4555-cmis-so.pdf + false + + true + false + false + + workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d + + false + + + + 343084 + application/pdf + h4555-cmis-so.pdf + + http://10.33.4.34:8080/alfresco/service/api/node/workspace/SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d/content.h4555-cmis-so.pdf + + + + + + '; + + $childrenFeed[] = ' + +System +Alfresco (Labs) +http://10.33.4.34:8080/alfresco/images/logo/AlfrescoLogo16.ico +urn:uuid:28537649-8af2-4c74-aa92-5d8bbecac9ce-children + + + + + +Company Home Children +2009-06-18T10:20:29.937+02:00 + +System +e98319fa-76e4-478f-8ce8-a3a0fd683e2c +urn:uuid:e98319fa-76e4-478f-8ce8-a3a0fd683e2c + + + + + + + + + + + +2009-06-18T10:20:37.788+02:00 +Site Collaboration Spaces +Sites +2009-06-18T10:20:37.874+02:00 + + + +workspace://SpacesStore/e98319fa-76e4-478f-8ce8-a3a0fd683e2c +folder +F/st_sites +System + +2009-06-18T10:20:37.788+02:00 +System +2009-06-18T10:20:37.874+02:00 +Sites +workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce + + + + +2009-06-18T10:20:37.874+02:00 +http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif + + +System +8c80a0f7-74b4-4bd8-bb76-a2464e4b2d10 +urn:uuid:8c80a0f7-74b4-4bd8-bb76-a2464e4b2d10 + + + + + + + + + + + +2009-06-18T10:20:29.939+02:00 +User managed definitions +Data Dictionary +2009-06-18T10:20:30.004+02:00 + + + +workspace://SpacesStore/8c80a0f7-74b4-4bd8-bb76-a2464e4b2d10 +folder +folder +System + +2009-06-18T10:20:29.939+02:00 +System +2009-06-18T10:20:30.004+02:00 +Data Dictionary +workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce + + + + +2009-06-18T10:20:30.004+02:00 +http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif + + +System +ba2524ef-7f3d-4ed4-84a0-8d99b6524737 +urn:uuid:ba2524ef-7f3d-4ed4-84a0-8d99b6524737 + + + + + + + + + + + +2009-06-18T10:20:30.312+02:00 +The guest root space +Guest Home + +2009-06-18T10:20:30.400+02:00 + + +workspace://SpacesStore/ba2524ef-7f3d-4ed4-84a0-8d99b6524737 +folder +folder +System + +2009-06-18T10:20:30.312+02:00 +System +2009-06-18T10:20:30.400+02:00 +Guest Home +workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce + + + + +2009-06-18T10:20:30.400+02:00 +http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif + + +System +86224486-b7ae-4074-a793-82cd259b0026 +urn:uuid:86224486-b7ae-4074-a793-82cd259b0026 + + + + + + + + + + + +2009-06-18T10:20:30.402+02:00 +User Homes +User Homes +2009-06-18T10:20:30.428+02:00 + + + +workspace://SpacesStore/86224486-b7ae-4074-a793-82cd259b0026 +folder +folder +System + +2009-06-18T10:20:30.402+02:00 +System +2009-06-18T10:20:30.428+02:00 +User Homes +workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce + + + + +2009-06-18T10:20:30.428+02:00 +http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif + + +System +0df9087f-e334-4890-a467-b60e3d6be92c +urn:uuid:0df9087f-e334-4890-a467-b60e3d6be92c + + + + + + + + + + + +2009-06-18T10:20:45.115+02:00 +Web Content Management Spaces +Web Projects +2009-06-18T10:20:45.137+02:00 + + + +workspace://SpacesStore/0df9087f-e334-4890-a467-b60e3d6be92c +folder +folder +System + +2009-06-18T10:20:45.115+02:00 +System +2009-06-18T10:20:45.137+02:00 +Web Projects +workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce + + + + +2009-06-18T10:20:45.137+02:00 +http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif + + +admin +urn:uuid:2df9d676-f173-47bb-8ec1-41fa1186b66d + + + + + + + + + +2009-06-23T09:40:47.889+02:00 + +h4555-cmis-so.pdf +2009-06-23T09:40:58.524+02:00 + + + +workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d +document +document +admin + +2009-06-23T09:40:47.889+02:00 +admin +2009-06-23T09:40:58.524+02:00 +h4555-cmis-so.pdf +false + +true +false +false + +workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d + +false + + + +343084 +application/pdf +h4555-cmis-so.pdf + +http://10.33.4.34:8080/alfresco/service/api/node/workspace/SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d/content.h4555-cmis-so.pdf + + + +2009-06-23T09:40:58.524+02:00 +http://10.33.4.34:8080/alfresco/images/filetypes/pdf.gif + +false +6 +0 + +0 +'; + +$folderFeed = ' + + +System +28537649-8af2-4c74-aa92-5d8bbecac9ce +urn:uuid:28537649-8af2-4c74-aa92-5d8bbecac9ce + + + + + + + + +2009-06-18T10:20:29.871+02:00 +The company root space +Company Home +2009-06-18T10:20:29.937+02:00 + + +workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce +folder +folder +System +2009-06-18T10:20:29.871+02:00 +System +2009-06-18T10:20:29.937+02:00 +Company Home + + + + +2009-06-18T10:20:29.937+02:00 +http://127.0.0.1:8080/alfresco/images/icons/space-icon-default-16.gif + +'; + +$docFeed = ' + + +admin +urn:uuid:2df9d676-f173-47bb-8ec1-41fa1186b66d + + + + + + + + +2009-06-23T09:40:47.889+02:00 + +h4555-cmis-so.pdf +2009-06-23T09:40:58.524+02:00 + + +workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d +document +document +admin +2009-06-23T09:40:47.889+02:00 +admin +2009-06-23T09:40:58.524+02:00 +h4555-cmis-so.pdf +false +true +false +false + +workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d +false + + + +343084 +application/pdf +h4555-cmis-so.pdf +http://127.0.0.1:8080/alfresco/service/api/node/workspace/SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d/content.h4555-cmis-so.pdf + + + +2009-06-23T09:40:58.524+02:00 +http://127.0.0.1:8080/alfresco/images/filetypes/pdf.gif + +'; +?> \ No newline at end of file diff --git a/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php b/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php new file mode 100644 index 0000000..aa8655d --- /dev/null +++ b/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php @@ -0,0 +1,219 @@ +newId('urn:uuid:' . $cmisEntry['properties']['Name']['value'] . '-' +// . strtolower($cmisEntry['properties']['ObjectTypeId']['value']), $entry); + +// echo $_SERVER['QUERY_STRING']."
\n"; +// preg_match('/^\/?[^\/]*\/folder\/(.*)\/[^\/]*\/?$/', trim($_SERVER['QUERY_STRING'], '/'), $matches); +// $path = $matches[1]; +// $parent = preg_replace('/\/[^\/]*$/', '', $path); +// // TODO fix path to work on old method, after fixing drupal module to not require extended path +// +// $path = ''; + + $id = $cmisEntry['properties']['ObjectId']['value']; + $entry = $feed->newEntry(); + $feed->newField('id', 'urn:uuid:' . $id, $entry); +// print_r($cmisEntry); + // links + // TODO check parent link is correct, fix if needed + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-parent')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/folder/' . $cmisEntry['properties']['ParentId']['value'])); + $entry->appendChild($link); + + if (strtolower($cmisEntry['properties']['ObjectTypeId']['value']) == 'folder') + { + // TODO check parent link is correct, fix if needed + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-folderparent')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/folder/' . $cmisEntry['properties']['ParentId']['value'])); + $entry->appendChild($link); + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-children')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/' + . strtolower($cmisEntry['properties']['ObjectTypeId']['value']) + . '/' . $cmisEntry['properties']['ObjectId']['value'] + . '/children')); + $entry->appendChild($link); + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-descendants')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/' + . strtolower($cmisEntry['properties']['ObjectTypeId']['value']) + . '/' . $cmisEntry['properties']['ObjectId']['value'] + . '/descendants')); + $entry->appendChild($link); + } + + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-type')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($cmisEntry['properties']['ObjectTypeId']['value']))); + $entry->appendChild($link); + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-repository')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/servicedocument')); + $entry->appendChild($link); + // end links + + $entry->appendChild($feed->newElement('summary', $cmisEntry['properties']['Name']['value'])); + $entry->appendChild($feed->newElement('title', $cmisEntry['properties']['Name']['value'])); + + // main CMIS entry + $objectElement = $feed->newElement('cmis:object'); + $propertiesElement = $feed->newElement('cmis:properties'); + + foreach($cmisEntry['properties'] as $propertyName => $property) + { + $propElement = $feed->newElement('cmis:' . $property['type']); + $propElement->appendChild($feed->newAttr('cmis:name', $propertyName)); + $feed->newField('cmis:value', CMISUtil::boolToString($property['value']), $propElement); + $propertiesElement->appendChild($propElement); + } + + $objectElement->appendChild($propertiesElement); + $entry->appendChild($objectElement); + } + + /** + * Retrieves the list of types|type definition as a CMIS AtomPub feed + * + * @param string $typeDef Type requested - 'All Types' indicates a listing, else only a specific type + * @param array $types The types found + * @return string CMIS AtomPub feed + */ + static public function getTypeFeed($typeDef, $types) + { + $typesString = ''; + $typesHeading = ''; + switch($typeDef) + { + case 'all': + case 'children': + case 'descendants': + $typesString = 'types-' . $typeDef; + $typesHeading = 'All Types'; + break; + default: + $typesString = 'type-' . $typeDef; + $typesHeading = $typeDef; + break; + } + + //Create a new response feed + $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $typesHeading, null, null, null, 'urn:uuid:' . $typesString); + + foreach($types as $type) + { + $entry = $feed->newEntry(); + $feed->newId('urn:uuid:type-' . strtolower($type['typeId']), $entry); + + // links + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','self')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($type['typeId']))); + $entry->appendChild($link); + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-type')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($type['typeId']))); + $entry->appendChild($link); + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-children')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($type['typeId']) . '/children')); + $entry->appendChild($link); + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-descendants')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($type['typeId']) . '/descendants')); + $entry->appendChild($link); + $link = $feed->newElement('link'); + $link->appendChild($feed->newAttr('rel','cmis-repository')); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/servicedocument')); + $entry->appendChild($link); + + $entry->appendChild($feed->newElement('summary', $type['typeId'] . ' Type')); + $entry->appendChild($feed->newElement('title', $type['typeId'])); + + // main CMIS entry + $feedElement = $feed->newElement('cmis:' . strtolower($type['typeId']) . 'Type'); + foreach($type as $property => $value) + { + $feed->newField($property, CMISUtil::boolToString($value), $feedElement); + } + + $entry->appendChild($feedElement); + } + + return $feed; + } + + /** + * Fetches the CMIS objectId based on the path + * + * @param array $path + * @param object $ktapi KTAPI instance + */ + // TODO make this much more efficient than this messy method + static public function getFolderId($path, &$ktapi) + { + // lose first item + array_shift($path); + + $numQ = count($path); + $numFolders = $numQ; + $folderId = 1; + + $start = 0; + while($start < $numFolders) + { + $name = $path[$numQ-$numFolders+$start]; + // hack to fix drupal url encoding issue + $name = str_replace('%2520', '%20', $name); + + $folderName = urldecode($name); + $folder = $ktapi->get_folder_by_name($folderName, $folderId); + $folderId = $folder->get_folderid(); + ++$start; + } + + return CMISUtil::encodeObjectId('Folder', $folderId); + } + + static public function getCmisProperties($xmlArray) + { + $properties = array(); + + foreach($xmlArray as $cmisPropertyDefinition) + { + foreach($cmisPropertyDefinition as $propertyType => $propertyDefinition) + { + $properties[$propertyDefinition['@attributes']['cmis:name']] = $propertyDefinition['@children']['cmis:value'][0]['@value']; + } + } + + return $properties; + } + + static public function getAtomValues($xmlArray, $tag) + { + if (!is_null($xmlArray['atom:'.$tag])) + return $xmlArray['atom:'.$tag][0]['@value']; + else if (!is_null($xmlArray[$tag])) + return $xmlArray[$tag][0]['@value']; + + return null; + } + +} + +?> diff --git a/webservice/atompub/cmis/index.php b/webservice/atompub/cmis/index.php new file mode 100644 index 0000000..b6c9570 --- /dev/null +++ b/webservice/atompub/cmis/index.php @@ -0,0 +1,117 @@ +. + * + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, + * California 94120-7775, or email info@knowledgetree.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU General Public License version 3. + * + * In accordance with Section 7(b) of the GNU General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices + * must display the words "Powered by KnowledgeTree" and retain the original + * copyright notice. + * Contributor( s): + * Mark Holtzhausen + * Paul Barrett + * + */ + +require_once('../../../config/dmsDefaults.php'); + +define('KT_APP_BASE_URI', "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/?/'); +define('KT_APP_SYSTEM_URI', "http://".$_SERVER['HTTP_HOST']); +define('KT_ATOM_LIB_FOLDER', '../../classes/atompub/'); + +// should make the "dms" part dynamic but right now this is needed fast +define('CMIS_APP_BASE_URI', trim(KT_APP_BASE_URI, '/')); +define('CMIS_APP_SYSTEM_URI', KT_APP_SYSTEM_URI); +define('CMIS_ATOM_LIB_FOLDER', trim(KT_ATOM_LIB_FOLDER, '/') . '/cmis/'); + +// fetch username and password for auth; note that this apparently only works when PHP is run as an apache module +// TODO method to fetch username and password when running PHP as CGI, if possible +// HTTP Basic Auth: +$username = $_SERVER['PHP_AUTH_USER']; +$password = $_SERVER['PHP_AUTH_PW']; + +/** + * Includes + */ +include_once(KT_ATOM_LIB_FOLDER.'XMLns2array.inc.php'); +include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_server.inc.php'); +include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_baseDoc.inc.php'); +include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_responseFeed.inc.php'); //Containing the response feed class allowing easy atom feed generation +include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_serviceDoc.inc.php'); //Containing the servicedoc class allowing easy ServiceDocument generation +include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_service.inc.php'); //Containing the servicedoc class allowing easy ServiceDocument generation + +include_once('KT_cmis_atom_server.services.inc.php'); +//Start the AtomPubProtocol Routing Engine +$APP = new KT_cmis_atom_server(); + +// FIXME HACK! this should not happen every time, ONLY on a service doc request +// CMIS service document setup +$APP->initServiceDocument(); +// FIXME HACK! this should not happen every time, ONLY on a service doc request +// User defined title tag +$APP->addWorkspaceTag('dms','atom:title',$APP->repositoryInfo['repositoryName']); + +/** + * Register Services + * + * Registered services are classes extended from KT_atom_service + * The registration process takes the following parameters + * Workspace :The workspace within which the service collection will be grouped + * ServiceName :This is the name by which the service/collection is exposed + * ServiceClass :This is the class name of the class to be instantiated when this service is accessed + * Title :This is the title given to the service/collection in the servicedocument + * http://ktatompub/index.php?/service/param1/param2 + * http://ktatompub/?/folder/children/whatfoldertolookat + * http://ktatompub/{folder/folder2/folder3/}service/param1/param2 +*/ +// TODO consider a registerServices function which will, dependant on what is requested, register the appropriate services, keep the logic out of the index file +$APP->registerService('dms', 'folder', 'KT_cmis_atom_service_folder', 'Root Folder Children Collection', + array(rawurlencode($APP->repositoryInfo['rootFolderId']), 'children'), 'root-children'); +$APP->registerService('dms', 'folder', 'KT_cmis_atom_service_folder', 'Root Folder Children Collection', + array(rawurlencode($APP->repositoryInfo['rootFolderId']), 'descendants'), 'root-descendants'); +$APP->registerService('dms', 'checkedout', 'KT_cmis_atom_service_checkedout', 'Checked Out Document Collection', null, 'checkedout'); +$APP->registerService('dms', 'types', 'KT_cmis_atom_service_types', 'Object Type Collection', null, 'types-children'); +$APP->registerService('dms', 'types', 'KT_cmis_atom_service_types', 'Object Type Collection', null, 'types-descendants'); + +// FIXME HACK! this should not happen every time, ONLY on a specific request, should NOT appear in service document as this is not definable at that time; +// SHOULD be appearing in types listing feed +// NOTE $requestParams is meaningless if not actually requesting this service, so not a good way to register the service really +$queryArray=split('/',trim($_SERVER['QUERY_STRING'],'/')); +$requestParams=array_slice($queryArray,2); +$APP->registerService('dms', 'type', 'KT_cmis_atom_service_type', 'Object Type Collection', explode('/', $requestParams), 'types-descendants'); +// FIXME HACK! see above, this one for documents +$APP->registerService('dms', 'document', 'KT_cmis_atom_service_document', 'Object Type Collection', explode('/', $requestParams), 'types-descendants'); + +//Execute the current url/header request +$APP->execute(); + +//Render the resulting feed response +$APP->render(); + +?> diff --git a/webservice/classes/atompub/KT_atom_responseFeed.inc.php b/webservice/classes/atompub/KT_atom_responseFeed.inc.php index d78ac00..98ccb0d 100644 --- a/webservice/classes/atompub/KT_atom_responseFeed.inc.php +++ b/webservice/classes/atompub/KT_atom_responseFeed.inc.php @@ -4,11 +4,10 @@ class KT_atom_responseFeed extends KT_atom_baseDoc { protected $baseURI=NULL; protected $feed=NULL; - - public function __construct($baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL){ + public function __construct($baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL, $workspace = null){ parent::__construct(); + $this->baseURI = $baseURI; $this->constructHeader(); - $this->baseURI=$baseURI; } protected function constructHeader(){ diff --git a/webservice/classes/atompub/KT_atom_server.inc.php b/webservice/classes/atompub/KT_atom_server.inc.php index 3a3e9d6..91bb1ca 100644 --- a/webservice/classes/atompub/KT_atom_server.inc.php +++ b/webservice/classes/atompub/KT_atom_server.inc.php @@ -3,7 +3,7 @@ class KT_atom_server{ protected $services=array(); protected $workspaceDetail=array(); protected $errors=array(); - protected $output=''; + public $output=''; protected $queryArray=array(); protected $serviceName=''; protected $method=''; @@ -13,6 +13,9 @@ class KT_atom_server{ public function __construct(){ } + protected function hook_beforeDocCreate($doc){return true;} + protected function hook_beforeDocRender($doc){return true;} + /** * Run the server switchboard - find the correct service class to instantiate, execute & render that class with the passed parameteres * @@ -22,23 +25,23 @@ class KT_atom_server{ $queryArray=split('/',trim($_SERVER['QUERY_STRING'],'/')); $rawRequest=@file_get_contents('php://input'); - $workspace=strtolower(trim($queryArray[0])); + $workspace=strtolower(trim($queryArray[0])); $serviceName=strtolower(trim($queryArray[1])); $requestParams=array_slice($queryArray,2); $this->queryArray=$queryArray; - $this->serviceName=$service; + $this->serviceName=$serviceName; $this->method=$reqMethod; $this->workspace=$workspace; - - if($workspace=='servicedocument'){ + + if($workspace=='servicedocument'){ $this->serviceDocument(); return; } - + $service=$this->getRegisteredService($workspace,$serviceName); if(is_array($service)){ $serviceClass=$service['serviceClass']; - echo 'made it'; +// echo 'made it'; $serviceObject=new $serviceClass($reqMethod,$requestParams,$rawRequest); $this->output=$serviceObject->render(); }else{ @@ -46,9 +49,10 @@ class KT_atom_server{ // return; $serviceObject=new KT_atom_service($requestParams,$rawRequest); $serviceObject->setStatus(KT_atom_service::STATUS_NOT_FOUND); - $this->output=$serviceObject->render(); + if($this->hook_beforeDocRender($serviceObject)) $this->output=$serviceObject->render(); } $this->serviceObject=$serviceObject; + return $serviceObject; } diff --git a/webservice/classes/atompub/KT_atom_service.inc.php b/webservice/classes/atompub/KT_atom_service.inc.php index 0e46afe..d59818c 100644 --- a/webservice/classes/atompub/KT_atom_service.inc.php +++ b/webservice/classes/atompub/KT_atom_service.inc.php @@ -1,13 +1,15 @@ responseFeed->render(); } - protected function xml2array($xml){ - if(class_exists('')){ + protected function xml2array($xml) + { + if (trim($xml) == '') return array(); + + if(class_exists('XMLns2array')) + { $array=XMLns2array::parse($xml); - }else{ - $array=json_decode(json_encode(@simplexml_load_string($xml)),true); + } + else + { + $array=json_decode(json_encode(@simplexml_load_string($xml)), true); } return $array; } diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_baseDoc.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_baseDoc.inc.php new file mode 100644 index 0000000..fc24e21 --- /dev/null +++ b/webservice/classes/atompub/cmis/KT_cmis_atom_baseDoc.inc.php @@ -0,0 +1,53 @@ +. + * + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, + * California 94120-7775, or email info@knowledgetree.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU General Public License version 3. + * + * In accordance with Section 7(b) of the GNU General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices + * must display the words "Powered by KnowledgeTree" and retain the original + * copyright notice. + * Contributor( s): + * Mark Holtzhausen + * Paul Barrett + * + */ + +/** + * Includes + */ + +include_once(KT_ATOM_LIB_FOLDER.'KT_atom_baseDoc.inc.php'); //Containing the parent class allowing easy XML manipulation + +class KT_cmis_atom_baseDoc extends KT_atom_baseDoc { + + // override and extend as needed + +} + +?> \ No newline at end of file diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_responseFeed.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_responseFeed.inc.php new file mode 100644 index 0000000..1aa8902 --- /dev/null +++ b/webservice/classes/atompub/cmis/KT_cmis_atom_responseFeed.inc.php @@ -0,0 +1,112 @@ +workspace = strtolower(trim($queryArray[0])); + $this->id = $id; + $this->title = $title; + + parent::__construct($baseURI, $title, $link, $updated, $author, $id); + } + + protected function constructHeader() + { + $feed = $this->newElement('feed'); +// $feed->appendChild($this->newAttr('xmlns','http://www.w3.org/2007/app')); +// $feed->appendChild($this->newAttr('xmlns:atom','http://www.w3.org/2005/Atom')); + $feed->appendChild($this->newAttr('xmlns','http://www.w3.org/2005/Atom')); + $feed->appendChild($this->newAttr('xmlns:cmis','http://www.cmis.org/2008/05')); + $this->feed = &$feed; + + if (!is_null($this->id)) + { + $this->newId($this->id, $this->feed); + } + + $link = $this->newElement('link'); + $link->appendChild($this->newAttr('rel','self')); + $link->appendChild($this->newAttr('href', $this->baseURI . trim($_SERVER['QUERY_STRING'], '/'))); + $feed->appendChild($link); + + if (!is_null($this->title)) + { + $this->feed->appendChild($this->newElement('title', $this->title)); + } + + $this->DOM->appendChild($this->feed); + } + + public function &newId($id, $entry = null) + { + $id = $this->newElement('id', $id); + if(isset($entry))$entry->appendChild($id); + return $id; + } + +// public function &newField($name = NULL, $value = NULL, &$entry = NULL) +// { +// $append = false; +// +// if(func_num_args() > 3) +// { +// $append = ((func_get_arg(3) === true) ? true : false); +// } +// +// $field = $this->newElement('cmis:' . $name, $value); +// +// if (isset($entry)) $entry->appendChild($field); +// else if ($append) $this->feed->appendChild($field); +// +// return $field; +// } + + /* + public function &newEntry() + { + $entry = $this->newElement('entry'); + $this->feed->appendChild($entry); + return $entry; + } + + public function &newId($id, $entry = null) + { + $id = $this->newElement('id', $id); + if(isset($entry))$entry->appendChild($id); + return $id; + } + + public function &newField($name = NULL, $value = NULL, &$entry = NULL) + { + $append = false; + + if(func_num_args() > 3) + { + $append = ((func_get_arg(3) === true) ? true : false); + } + + $field = $this->newElement('cmis:' . $name,$value); + + if (isset($entry)) $entry->appendChild($field); + else if ($append) $this->feed->appendChild($field); + + return $field; + } + */ + +} + +class KT_cmis_atom_ResponseFeed_GET extends KT_cmis_atom_responseFeed{} +class KT_cmis_atom_ResponseFeed_PUT extends KT_cmis_atom_responseFeed{} +class KT_cmis_atom_ResponseFeed_POST extends KT_cmis_atom_responseFeed{} +class KT_cmis_atom_ResponseFeed_DELETE extends KT_cmis_atom_responseFeed{} + +?> \ No newline at end of file diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php new file mode 100644 index 0000000..4b1f460 --- /dev/null +++ b/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php @@ -0,0 +1,124 @@ +getRepositories(); + // fetch for default first repo; NOTE that this will probably have to change at some point, quick and dirty for now + $this->repositoryInfo = $RepositoryService->getRepositoryInfo($repositories[0]['repositoryId']); + } + } + + public function serviceDocument() + { + $service = new KT_cmis_atom_serviceDoc(KT_APP_BASE_URI); + + foreach($this->services as $workspace => $collection) + { + //Creating the Default Workspace for use with standard atomPub Clients + $ws = $service->newWorkspace(); + + $hadDetail=false; + if(isset($this->workspaceDetail[$workspace])) + { + if(is_array($this->workspaceDetail[$workspace])) + { + foreach ($this->workspaceDetail[$workspace] as $wsTag=>$wsValue) + { + $ws->appendChild($service->newElement($wsTag,$wsValue)); + $hadDetail=true; + } + } + } + + if(!$hadDetail) { + $ws->appendChild($service->newElement('atom:title',$workspace)); + } + + $ws->appendChild($service->newAttr('cmis:repositoryRelationship', $this->repositoryInfo['repositoryRelationship'])); + + // repository information + $element = $service->newElement('cmis:repositoryInfo'); + foreach($this->repositoryInfo as $key => $repoData) + { + if ($key == 'rootFolderId') + { + $repoData = CMIS_APP_BASE_URI . $workspace . '/folder/' . rawurlencode($repoData); + } + + if (!is_array($repoData)) + { + $element->appendChild($service->newElement('cmis:' . $key, $repoData)); + } + else + { + $elementSub = $service->newElement('cmis:' . $key); + foreach($repoData as $key2 => $data) + { + $elementSub->appendChild($service->newElement('cmis:' . $key2, CMISUtil::boolToString($data))); + } + $element->appendChild($elementSub); + } + } + $ws->appendChild($element); + + foreach($collection as $serviceName => $serviceInstance) + { + foreach($serviceInstance as $instance) + { + $collectionStr = CMIS_APP_BASE_URI . $workspace . '/' . $serviceName . '/' + . (is_array($instance['parameters']) ? implode('/', $instance['parameters']).'/' : ''); + $col = $service->newCollection($collectionStr, $instance['title'], $instance['collectionType'], $ws); + } + } + } + + $this->output = $service->getAPPdoc(); + } + + public function registerService($workspace = NULL, $serviceName = NULL, $serviceClass = NULL, $title = NULL, + $serviceParameters = NULL, $collectionType = NULL) + { + $workspace = strtolower(trim($workspace)); + $serviceName = strtolower(trim($serviceName)); + + $serviceRecord = array( + 'fileName' => $fileName, + 'serviceClass' => $serviceClass, + 'title' => $title, + 'parameters' => $serviceParameters, + 'collectionType' => $collectionType + ); + + $this->services[$workspace][$serviceName][] = $serviceRecord; + } + + public function getRegisteredService($workspace, $serviceName = NULL) + { + $serviceName = strtolower(trim($serviceName)); + if(isset($this->services[$workspace][$serviceName])) + { + return $this->services[$workspace][$serviceName][0]; + } + + return false; + } + +} + +?> \ No newline at end of file diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php new file mode 100644 index 0000000..f136f3d --- /dev/null +++ b/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php @@ -0,0 +1,36 @@ +headers); +// print_r($_SERVER); + // attempt to fetch auth info from supplied headers + if (!empty($this->headers['Authorization'])) + { + $auth = base64_decode(preg_replace('/Basic */', '', $this->headers['Authorization'])); + $authData = explode(':', $auth); +// print_r($authData); + self::$authData['username'] = $authData[0]; + self::$authData['password'] = $authData[1]; + } + // if failed, attempt to fetch from $_SERVER array instead + else if (isset($_SERVER['PHP_AUTH_USER'])) + { + self::$authData['username'] = $_SERVER['PHP_AUTH_USER']; + self::$authData['password'] = $_SERVER['PHP_AUTH_PW']; + } + } + +} +?> \ No newline at end of file diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php new file mode 100644 index 0000000..082535e --- /dev/null +++ b/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php @@ -0,0 +1,125 @@ +. + * + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, + * California 94120-7775, or email info@knowledgetree.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU General Public License version 3. + * + * In accordance with Section 7(b) of the GNU General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices + * must display the words "Powered by KnowledgeTree" and retain the original + * copyright notice. + * Contributor( s): + * Mark Holtzhausen + * Paul Barrett + * + */ + + +/** + * Includes + */ +include_once(KT_ATOM_LIB_FOLDER.'KT_atom_serviceDoc.inc.php'); +//include_once('KT_atom_baseDoc.inc.php'); + +class KT_cmis_atom_serviceDoc extends KT_atom_serviceDoc { + + // override and extend as needed + + public $repositoryInfo = array(); + + public function __construct($baseURI = NULL) + { + parent::__construct(); + + // get repositoryInfo + // NOTE currently we only support one repository, which will be the first one found in the repositories.xml config + // TODO multiple repositories as individual workspaces + + include 'services/cmis/RepositoryService.inc.php'; + $RepositoryService = new RepositoryService(); + + // fetch data for response + $repositories = $RepositoryService->getRepositories(); + // fetch for default first repo; NOTE that this will probably have to change at some point, quick and dirty for now + $this->repositoryInfo = $RepositoryService->getRepositoryInfo($repositories[0]['repositoryId']); + } + + protected function constructServiceDocumentHeaders() + { + $service = $this->newElement('service'); + $service->appendChild($this->newAttr('xmlns', 'http://www.w3.org/2007/app')); + $service->appendChild($this->newAttr('xmlns:atom', 'http://www.w3.org/2005/Atom')); + $service->appendChild($this->newAttr('xmlns:cmis', 'http://www.cmis.org/2008/05')); + $this->service =& $service; + $this->DOM->appendChild($this->service); + } + + public function &newCollection($url = NULL, $title = NULL, $cmisCollectionType = NULL, &$ws = NULL) + { + $collection=$this->newElement('collection'); + $collection->appendChild($this->newAttr('href', $url)); + $collection->appendChild($this->newAttr('cmis:collectionType', $cmisCollectionType)); + $collection->appendChild($this->newElement('atom:title', $title)); + if(isset($ws))$ws->appendChild($collection); + return $collection; + } + +} + +/** + + + + Main Site + + My Blog Entries + + + + Pictures + image/png + image/jpeg + image/gif + + + + Sidebar Blog + + Remaindered Links + application/atom+xml;type=entry + + + + + + + + + */ + + +?> \ No newline at end of file diff --git a/webservice/classes/atompub/cmis/NavigationService.inc.php b/webservice/classes/atompub/cmis/NavigationService.inc.php new file mode 100644 index 0000000..fe47e18 --- /dev/null +++ b/webservice/classes/atompub/cmis/NavigationService.inc.php @@ -0,0 +1,124 @@ + diff --git a/webservice/classes/atompub/cmis/ObjectService.inc.php b/webservice/classes/atompub/cmis/ObjectService.inc.php new file mode 100644 index 0000000..90171e6 --- /dev/null +++ b/webservice/classes/atompub/cmis/ObjectService.inc.php @@ -0,0 +1,90 @@ + diff --git a/webservice/classes/atompub/cmis/RepositoryService.inc.php b/webservice/classes/atompub/cmis/RepositoryService.inc.php new file mode 100644 index 0000000..55a3a80 --- /dev/null +++ b/webservice/classes/atompub/cmis/RepositoryService.inc.php @@ -0,0 +1,85 @@ +