/** * Process an uploaded file and send it into the repository. * * @uses $CFG * @uses $USER * @param string $upload The array index for the uploaded file in the $_FILES superglobal. * @param string $uuid The parent folder UUID value. * @param bool $useadmin Set to false to make sure that the administrative user configured in * the plug-in is not used for this operation (default: true). * @return string|bool The new node's UUID value or, False on error. */ function upload_file($upload = '', $path = '', $uuid = '', $useadmin = true) { global $CFG, $USER; // TODO: Remove this method as it seems that it is not necessary anymore? return false; if (ELIS_FILES_DEBUG_TRACE) mtrace('upload_file(' . $upload . ', ' . $path . ', ' . $uuid . ')'); if (ELIS_FILES_DEBUG_TIME) $start = microtime(true); require_once($CFG->libdir . '/filelib.php'); if (self::is_version('3.2')) { if ($node = elis_files_upload_file($upload, $path, $uuid)) { if (ELIS_FILES_DEBUG_TIME) { $end = microtime(true); $time = $end - $start; mtrace("upload_file('$upload', '$path', '$uuid'): $time"); } return $node->uuid; } return false; } else if (self::is_version('3.4')) { if (!empty($upload)) { if (!isset($_FILES[$upload]) || !empty($_FILES[$upload]->error)) { return false; } $filename = $_FILES[$upload]['name']; $filepath = $_FILES[$upload]['tmp_name']; $filemime = $_FILES[$upload]['type']; $filesize = $_FILES[$upload]['size']; } else if (!empty($path)) { if (!is_file($path)) { return false; } $filename = basename($path); $filepath = $path; $filemime = mimeinfo('type', $filename); $filesize = filesize($path); } else { return false; } $chunksize = 8192; $data1 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <atom:entry xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/" xmlns:cmism="http://docs.oasis-open.org/ns/cmis/messaging/200908/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/"> <atom:title>' . $filename . '</atom:title> <atom:summary>' . get_string('uploadedbymoodle', 'repository_elisfiles') . '</atom:summary> <cmisra:content> <cmisra:mediatype>' . $filemime . '</cmisra:mediatype> <cmisra:base64>'; $data2 = '</cmisra:base64> </cmisra:content> <cmisra:object> <cmis:properties> <cmis:propertyId propertyDefinitionId="cmis:objectTypeId"> <cmis:value>cmis:document</cmis:value> </cmis:propertyId> </cmis:properties> </cmisra:object> </atom:entry>'; $encodedbytes = 0; // Use a stream filter to base64 encode the file contents to a temporary file. if ($fi = fopen($filepath, 'r')) { if ($fo = tmpfile()) { stream_filter_append($fi, 'convert.base64-encode'); // Write the beginning of the XML document to the temporary file. $encodedbytes += fwrite($fo, $data1, strlen($data1)); // Copy the uploaded file into the temporary file (usng the base64 encode stream filter) // in 8K chunks to conserve memory. while(($encbytes = stream_copy_to_stream($fi, $fo, $chunksize)) !== 0) { $encodedbytes += $encbytes; } fclose($fi); // Write the end of the XML document to the temporary file. $encodedbytes += fwrite($fo, $data2, strlen($data2)); } } rewind($fo); // Force the usage of the configured Alfresco admin account, if requested. if ($useadmin) { $username = ''; } else { $username = $USER->username; } $serviceuri = '/cmis/s/workspace://SpacesStore/i/' . $uuid . '/children'; $url = elis_files_utils_get_wc_url($serviceuri, 'refresh', $username); $uri = parse_url($url); switch ($uri['scheme']) { case 'http': $port = isset($uri['port']) ? $uri['port'] : 80; $host = $uri['host'] . ($port != 80 ? ':'. $port : ''); $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15); break; case 'https': /// Note: Only works for PHP 4.3 compiled with OpenSSL. $port = isset($uri['port']) ? $uri['port'] : 443; $host = $uri['host'] . ($port != 443 ? ':'. $port : ''); $fp = @fsockopen('ssl://'. $uri['host'], $port, $errno, $errstr, 20); break; default: $result->error = 'invalid schema '. $uri['scheme']; return $result; } // Make sure the socket opened properly. if (!$fp) { $result->error = trim($errno .' '. $errstr); return $result; } // Construct the path to act on. $path = isset($uri['path']) ? $uri['path'] : '/'; if (isset($uri['query'])) { $path .= '?'. $uri['query']; } // Create HTTP request. $headers = array( // RFC 2616: "non-standard ports MUST, default ports MAY be included". // We don't add the port to prevent from breaking rewrite rules checking // the host that do not take into account the port number. 'Host' => "Host: $host", 'Content-type' => 'Content-type: application/atom+xml;type=entry', 'User-Agent' => 'User-Agent: Moodle (+http://moodle.org/)', 'Content-Length' => 'Content-Length: ' . $encodedbytes, 'MIME-Version' => 'MIME-Version: 1.0' ); $request = 'POST '. $path . " HTTP/1.0\r\n"; $request .= implode("\r\n", $headers); $request .= "\r\n\r\n"; fwrite($fp, $request); // Write the XML request (which contains the base64-encoded uploaded file contents) into the socket. stream_copy_to_stream($fo, $fp); fclose($fo); fwrite($fp, "\r\n"); // Fetch response. $response = ''; while (!feof($fp) && $chunk = fread($fp, 1024)) { $response .= $chunk; } fclose($fp); // Parse response. list($split, $result->data) = explode("\r\n\r\n", $response, 2); $split = preg_split("/\r\n|\n|\r/", $split); list($protocol, $code, $text) = explode(' ', trim(array_shift($split)), 3); $result->headers = array(); // Parse headers. while ($line = trim(array_shift($split))) { list($header, $value) = explode(':', $line, 2); if (isset($result->headers[$header]) && $header == 'Set-Cookie') { // RFC 2109: the Set-Cookie response header comprises the token Set- // Cookie:, followed by a comma-separated list of one or more cookies. $result->headers[$header] .= ','. trim($value); } else { $result->headers[$header] = trim($value); } } $responses = array( 100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported' ); // RFC 2616 states that all unknown HTTP codes must be treated the same as // the base code in their class. if (!isset($responses[$code])) { $code = floor($code / 100) * 100; } //TODO: check for $code 500 and add menu to replace copy or cancel the uploaded file with the same name as an existing file // if($code == 500) { // // } else if ($code != 200 && $code != 201 && $code != 304) { debugging(get_string('couldnotaccessserviceat', 'repository_elisfiles', $serviceuri), DEBUG_DEVELOPER); return false; } $response = preg_replace('/(&[^amp;])+/', '&', $response); $dom = new DOMDocument(); $dom->preserveWhiteSpace = false; $dom->loadXML($result->data); $nodes = $dom->getElementsByTagName('entry'); if (!$nodes->length) { return false; } $type = ''; $properties = elis_files_process_node($dom, $nodes->item(0), $type); // Ensure that we set the current user to be the owner of the newly created directory. if (!empty($properties->uuid)) { $username = elis_files_transform_username($USER->username); // We're not going to check the response for this right now. elis_files_request('/moodle/nodeowner/' . $properties->uuid . '?username=' . $username); } return $properties; } }
/** * Create a directory on the repository. * * @uses $USER * @param string $name The name of the directory we're checking for. * @param string $uuid The UUID of the parent directory we're checking for a name in. * @param string $description An optional description of the directory being created. * @param bool $useadmin Set to false to make sure that the administrative user configured in * the plug-in is not used for this operation (default: true). * @return object|bool Node information structure on the new folder or, False on error. */ function elis_files_create_dir($name, $uuid, $description = '', $useadmin = true) { global $CFG, $USER; $properties = elis_files_node_properties($uuid); if (!(ELIS_files::$version = elis_files_get_repository_version())) { return false; } //error_log("elis_files_create_dir('$name', '$uuid', '$description', $useadmin): version = ". ELIS_files::$version); if (ELIS_files::is_version('3.2')) { $data = '<?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200901" xmlns:alf="http://www.alfresco.org"> <link rel="type" href="' . elis_files_base_url() . '/api/type/folder"/> <link rel="repository" href="' . elis_files_base_url() . '/api/repository"/> <title>' . $name . '</title> <summary>' . $description . '</summary> <cmis:object> <cmis:properties> <cmis:propertyString cmis:name="ObjectTypeId"> <cmis:value>'.ELIS_files::$type_folder.'</cmis:value> </cmis:propertyString> </cmis:properties> </cmis:object> </entry>'; $uri = '/api/node/workspace/SpacesStore/' . $uuid . '/descendants'; } else if (ELIS_files::is_version('3.4')) { $uri = '/cmis/i/' . $uuid . '/children'; $data = '<?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/" xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/"> <link rel="type" href="' . elis_files_base_url() . '/api/type/folder"/> <link rel="repository" href="' . elis_files_base_url() . '/api/repository"/> <title>' . $name . '</title> <summary>' . $description . '</summary> <cmisra:object> <cmis:properties> <cmis:propertyId propertyDefinitionId="cmis:objectTypeId"> <cmis:value>'.ELIS_files::$type_folder.'</cmis:value> </cmis:propertyId> </cmis:properties> </cmisra:object> </entry>'; } $header[] = 'Content-type: application/atom+xml;type=entry'; $header[] = 'Content-length: ' . strlen($data); $header[] = 'MIME-Version: 1.0'; // Force the usage of the configured Alfresco admin account, if requested. if ($useadmin) { $username = ''; } else { $username = $USER->username; } $response = elis_files_utils_invoke_service($uri, 'basic', $header, 'CUSTOM-POST', $data, $username); if ($response === false) { // debugging(get_string('couldnotaccessserviceat', 'repository_elisfiles', $uri), DEBUG_DEVELOPER); // error_log('elis_files_create_dir(): '. get_string('couldnotaccessserviceat', 'repository_elisfiles', $uri)); return false; } $response = preg_replace('/(&[^amp;])+/', '&', $response); $dom = new DOMDocument(); $dom->preserveWhiteSpace = false; $dom->loadXML($response); $nodes = $dom->getElementsByTagName('entry'); if (!$nodes->length) { // error_log('elis_files_create_dir(): empty nodes->length'); return false; } $type = ''; $properties = elis_files_process_node($dom, $nodes->item(0), $type); // Ensure that we set the current user to be the owner of the newly created directory. if (!empty($properties->uuid)) { $username = elis_files_transform_username($USER->username); // We're not going to check the response for this right now. elis_files_request('/moodle/nodeowner/' . $properties->uuid . '?username=' . $username); } return $properties; }
/** * Test the elis_files_process_node function with no nodevalue for the cmis property. */ public function test_process_node_no_node_value() { $dom = new DOMDocument(); libxml_use_internal_errors(true); $string = '<feed xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200901" xmlns:alf="http://www.alfresco.org" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">'. '<author><name>admin</name></author>'. '<generator version="3.2.1 (.2 3)">Alfresco (Enterprise)</generator>'. '<icon>http://localhost:8080/alfresco/images/logo/AlfrescoLogo16.ico</icon>'. '<id>urn:uuid:fff6c376-bf63-4475-a25d-383251dcb3fb-parent</id>'. '<link rel="self" href="http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/fff6c376-bf63-4475-a25d-383251dcb3fb/parent?alf_ticket=TICKET_edd0417f8ba654b6c4ac3f7c4317fbae31b648e9"></link>'. '<link rel="source" href="http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/fff6c376-bf63-4475-a25d-383251dcb3fb"></link>'. '<title>Import_questions.txt Parent</title>'. '<updated>2012-03-02T15:52:24.790-05:00</updated>'. '<entry>'. '<author><name>System</name></author>'. '<content>d60de32a-9e4d-40c5-888a-08607fedf9f5</content>'. '<id>urn:uuid:d60de32a-9e4d-40c5-888a-08607fedf9f5</id>'. '<link rel="self" href="http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/d60de32a-9e4d-40c5-888a-08607fedf9f5"></link>'. '<link rel="edit" href="http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/d60de32a-9e4d-40c5-888a-08607fedf9f5"></link>'. '<link rel="allowableactions" href="http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/d60de32a-9e4d-40c5-888a-08607fedf9f5/permissions"></link>'. '<link rel="relationships" href="http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/d60de32a-9e4d-40c5-888a-08607fedf9f5/rels"></link>'. '<link rel="parents" href="http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/d60de32a-9e4d-40c5-888a-08607fedf9f5/parent"></link>'. '<link rel="children" href="http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/d60de32a-9e4d-40c5-888a-08607fedf9f5/children"></link>'. '<link rel="descendants" href="http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/d60de32a-9e4d-40c5-888a-08607fedf9f5/descendants"></link>'. '<link rel="type" href="http://localhost:8080/alfresco/s/api/type/folder"></link>'. '<link rel="repository" href="http://localhost:8080/alfresco/s/api/repository"></link>'. '<published>2012-02-17T10:49:07.215-05:00</published>'. '<summary>User Homes</summary><title>User Homes</title>'. '<updated>2012-02-17T10:49:07.230-05:00</updated>'. '<cmis:object>'. '<cmis:properties>'. '<cmis:propertyString cmis:name="BaseType"></cmis:propertyString>'. '</cmis:properties>'. '</cmis:object>'. '<cmis:terminator></cmis:terminator>'. '</entry>'. '<cmis:hasMoreItems>false</cmis:hasMoreItems>'. '</feed>'; $dom->loadXML($string); libxml_clear_errors(); $nodes = $dom->getElementsByTagName('entry'); $contentnode = elis_files_process_node($dom, $nodes->item(0), $type); $this->assertNotEmpty($contentnode); }