Beispiel #1
0
/**
 * 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;])+/', '&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;
        }
    }
Beispiel #2
0
/**
 * 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;])+/', '&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;
}
Beispiel #3
0
    /**
     * 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);
    }