'Basic ' . base64_encode($user . ':' . $pass)); } /** * Utility function for getting alfresco ticket. * * $op Option for refreshing ticket or not. */ function cmis_alfresco_utils_get_ticket($op = 'norefresh') { $ticket = $_SESSION['cmis_alfresco_ticket']; if ($ticket == NULL || $op == 'refresh') { //drupal_set_message('Ticket not set, logging in'); $user = variable_get('cmis_alfresco_user', ''); $pass = base64_decode(variable_get('cmis_alfresco_password', '')); //authenticate and store the ticket $url = cmis_alfresco_utils_get_url('/api/login?u=' . $user . '&pw=' . $pass); $response = drupal_http_request($url); if ($response->code == 200 || $response->code == 201) { $ticketXml = new SimpleXMLElement($response->data); $ticket = (string) $ticketXml[0]; } else { form_set_error('', 'Error received from endpoint:' . $response->code); } if ($ticket == '') { form_set_error('', 'Unable to authenticate with endpoint'); } else { //drupal_set_message('Authentication with endpoint successful.'); } //drupal_set_message('Setting ticket:' . $ticket . ':'); $_SESSION['cmis_alfresco_ticket'] = $ticket; } else { //drupal_set_message('Using stored ticket.'); } return $ticket; } /** * Return service url for HTTP basic authentication. * */ function cmis_alfresco_utils_get_url($url) { $endpoint = variable_get('cmis_alfresco_endpoint', ''); return $endpoint . '/service' . $url; } /** * Return service url for ticket based authentication. * $op Option for refreshing ticket or not. */ function cmis_alfresco_utils_get_wc_url($url, $op = 'norefresh') { $endpoint = variable_get('cmis_alfresco_endpoint', ''); $wcendpoint = $endpoint . '/service'; $ticket = cmis_alfresco_utils_get_ticket($op); if (FALSE === strstr($url, '?')) { if ($url[0] == '/') { return $wcendpoint . $url . '?alf_ticket=' . $ticket; } else { return $url . '?alf_ticket=' . $ticket; } } return $wcendpoint . str_replace('?', '?alf_ticket=' . $ticket . '&', $url); } /** * Invoke Alfresco Webscript based Service. * $op Option for service authentication. * 'ticket' is for ticket based and 'basic' for http basic authentication. */ function cmis_alfresco_utils_invoke_service($serviceurl, $op = 'ticket', $headers = array (), $method = 'GET', $data = NULL, $retry = 3) { /* if($op=='basic'){ $url = cmis_alfresco_utils_get_url($serviceurl); $response = drupal_http_request($url, cmis_alfresco_utils_get_auth_headers()); $response = cmis_alfresco_utils_http_request ($url, 'basic'); }else{ $url = cmis_alfresco_utils_get_wc_url($serviceurl); $response = drupal_http_request($url); } */ $response = cmis_alfresco_utils_http_request($serviceurl, $op, $headers, $method, $data, $retry); if ($response->code == 200 || $response->code == 201) { $content = $response->data; if (false === strstr($content, 'Alfresco Web Client - Login')) { return $content; } else { //$url = cmis_alfresco_utils_get_wc_url($serviceurl,'refresh'); // $response2 = drupal_http_request($url); $response2 = cmis_alfresco_utils_http_request($serviceurl, 'refresh', $headers, $method, $data, $retry); if ($response2->code == 200 || $response->code == 201) { return $response2->data; } else { drupal_set_message(t('Failed to invoke service ' . $serviceurl . ' Code:' . $response2->code), 'error'); return false; } } } elseif ($response->code == 302 || $response->code == 505 || $response->code == 401) { //$url = cmis_alfresco_utils_get_wc_url($serviceurl,'refresh'); //$response2 = drupal_http_request($url); $response2 = cmis_alfresco_utils_http_request($serviceurl, 'refresh', $headers, $method, $data, $retry); if ($response2->code == 200 || $response->code == 201) { return $response2->data; } else { drupal_set_message(t('Failed to invoke service ' . $serviceurl . ' Code:' . $response2->code), 'error'); return false; } } else { drupal_set_message(t('Failed to invoke service ' . $serviceurl . ' Code:' . $response->code), 'error'); return false; } } /** * Invoke Webscript based Service using curl apis. * It is intended to be a utility function that handles authentication (basic, ticket), * http headers (if necessary) and custom post ( cmisquery+xml, atom+xml etc.). * * $serviceurl Alfreco webscript service url without /service or /wcservice prefix. * $auth Option for service authentication. * $headers Additional http headers for making the http call. * 'ticket' is for ticket based, 'basic' for http basic authentication, 'refresh' for ticket based but with ticket refresh. * $method * $data * $retry */ function cmis_alfresco_utils_http_request($serviceurl, $auth = 'ticket', $headers = array (), $method = 'GET', $data = NULL, $retry = 3) { if ($auth == 'basic') { $url = cmis_alfresco_utils_get_url($serviceurl); } elseif ($auth == 'refresh') { $url = cmis_alfresco_utils_get_wc_url($serviceurl, 'refresh'); } else { $url = cmis_alfresco_utils_get_wc_url($serviceurl); } // Prepare curl session $session = curl_init($url); curl_setopt($session, CURLOPT_VERBOSE, 1); // Add additonal headers curl_setopt($session, CURLOPT_HTTPHEADER, $headers); // Don't return HTTP headers. Do return the contents of the call curl_setopt($session, CURLOPT_HEADER, false); curl_setopt($session, CURLOPT_RETURNTRANSFER, true); if ($auth == 'basic') { $user = variable_get('cmis_alfresco_user', ''); $pass = base64_decode(variable_get('cmis_alfresco_password', '')); curl_setopt($session, CURLOPT_USERPWD, "$user:$pass"); } if ($method == 'CUSTOM-POST') { curl_setopt($session, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($session, CURLOPT_POSTFIELDS, $data); curl_setopt($session, CURLOPT_ERRORBUFFER, 1); } if ($method == 'CUSTOM-PUT') { curl_setopt($session, CURLOPT_CUSTOMREQUEST, 'PUT'); curl_setopt($session, CURLOPT_POSTFIELDS, $data); curl_setopt($session, CURLOPT_ERRORBUFFER, 1); } // Make the call $return_data = curl_exec($session); // Get return http status code $httpcode = curl_getinfo($session, CURLINFO_HTTP_CODE); // Close HTTP session curl_close($session); // Prepare return $result = new stdClass(); $result->code = $httpcode; $result->data = $return_data; return $result; } /** * Process CMIS XML. * $xml CMIS response XML. * $xpath xpath expression. */ function cmis_utils_process_CMIS_xml($xml, $xpath) { try { $cmis_service = new SimpleXMLElement($xml); } catch (Exception $e) { drupal_set_message("Bad XML return"); return false; } $cmis_service->registerXPathNamespace('cmis', 'http://www.cmis.org/2008/05'); $cmis_service->registerXPathNamespace('D', 'http://www.w3.org/2005/Atom'); $cmis_service->registerXPathNamespace('alf', 'http://www.alfresco.org'); $cmis_service->registerXPathNamespace('app', 'http://www.w3.org/2007/app'); $entry = $cmis_service->xpath($xpath); return $entry; } /** * Get XML node value. * $entry CMIS XML Node. * $xpath xpath expression. */ function cmis_utils_CMIS_xml_get_value($entry, $xpath) { if (is_null($entry)) { return null; } $value = $entry->xpath($xpath); return $value[0][0]; } /** * Resolves objectId from various formats. * * Known formats: * - url: http://localhost:8080/alfresco/service/api/path/workspace/SpacesStore/Company%20Home * - path: Company Home/path fo file * - noderef: workspace://SpacesStore/91298612309871e * - id: 91298612309871esdf * * @todo: Review objectId handling. * * @param $objectId * @return array */ function cmis_alfresco_objectId($objectId) { // probably is already resolved ("instanceof" would have been more appropriate) if (is_array($objectId)) { return $objectId; } // unable to resolve node if (!is_string($objectId)) { return false; } $parts = parse_url($objectId); if (substr($parts['scheme'], 0, 4) == 'http') { // @todo: lookup id by path $parts['url'] = $objectId; return $parts; } if (in_array($parts['scheme'], array ('workspace', 'archive', 'user', 'system', 'avm'))) { $parts['noderef'] = $objectId; $parts['noderef_url'] = $parts['scheme'] . '/' . $parts['host'] . $parts['path']; return $parts; } if ($parts['scheme'] == 'urn') { // Assuming that comes from workspace://SpacesStore/ // @todo: Review this assumption $tmp_parts = parse_url($parts['path']); $parts['path'] = $tmp_parts['path']; $parts['noderef'] = 'workspace://SpacesStore/' . $parts['path']; $parts['scheme'] = 'workspace'; $parts['host'] = 'SpacesStore'; $parts['noderef_url'] = 'workspace/SpacesStore/' . $parts['path']; return $parts; } if ($parts['path'][0] == '/' && empty ($parts['scheme'])) { // Assuming that id looks like "/Company Home/path/to/object" if (substr($parts['path'], -1) == '/') { $parts['path'] = substr_replace($parts['path'], '', -1); } $response = cmis_alfresco_utils_invoke_service('/api/path/workspace/SpacesStore' . $parts['path']); $object_info = cmis_utils_process_CMIS_xml($response, '//D:entry'); if (false != $object_info) { return cmis_alfresco_objectId((string) $object_info[0]->id); } else { return false; } } // unknown format watchdog(WATCHDOG_ERROR, "Unable to resolve objectId: " . $objectId); return false; } /** * Utility function for returning CMIS objects from cmis response(ie. getChildren, query, getDescendants) * @param $entries * @return array */ function cmis_alfresco_getEntries($entries) { $result = array (); foreach ($entries as $entry) { $cmis_object = new stdClass(); $tmp_objectId = cmis_alfresco_objectId((string) $entry->id); $cmis_object->id = $tmp_objectId['noderef']; $cmis_object->title = (string) $entry->title; $cmis_object->summary = (string) $entry->summary; $cmis_object->type = (string) cmis_utils_CMIS_xml_get_value($entry, 'cmis:object/cmis:properties/cmis:propertyString[@cmis:name="BaseType"]/cmis:value'); $cmis_object->updated = date_create($entry->updated); $cmis_object->author = $entry->author->name; if ($cmis_object->type == 'document') { $cmis_object->size = cmis_utils_CMIS_xml_get_value($entry, 'cmis:object/cmis:properties/cmis:propertyInteger[@cmis:name="ContentStreamLength"]/cmis:value'); $cmis_object->contentMimeType = cmis_utils_CMIS_xml_get_value($entry, 'cmis:object/cmis:properties/cmis:propertyString[@cmis:name="ContentStreamMimeType"]/cmis:value'); $cmis_object->versionSeriesCheckedOutBy = cmis_utils_CMIS_xml_get_value($entry, 'cmis:object/cmis:properties/cmis:propertyString[@cmis:name="VersionSeriesCheckedOutBy"]/cmis:value'); } $result[] = $cmis_object; } return $result; }