1<?php
2
3namespace Sabre\DAV\FSExt;
4
5use Sabre\DAV;
6use Sabre\DAV\FS\Node;
7
8/**
9 * File class
10 *
11 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
12 * @author Evert Pot (http://evertpot.com/)
13 * @license http://sabre.io/license/ Modified BSD License
14 */
15class File extends Node implements DAV\PartialUpdate\IPatchSupport {
16
17    /**
18     * Updates the data
19     *
20     * Data is a readable stream resource.
21     *
22     * @param resource|string $data
23     * @return string
24     */
25    function put($data) {
26
27        file_put_contents($this->path, $data);
28        clearstatcache(true, $this->path);
29        return $this->getETag();
30
31    }
32
33    /**
34     * Updates the file based on a range specification.
35     *
36     * The first argument is the data, which is either a readable stream
37     * resource or a string.
38     *
39     * The second argument is the type of update we're doing.
40     * This is either:
41     * * 1. append
42     * * 2. update based on a start byte
43     * * 3. update based on an end byte
44     *;
45     * The third argument is the start or end byte.
46     *
47     * After a successful put operation, you may choose to return an ETag. The
48     * ETAG must always be surrounded by double-quotes. These quotes must
49     * appear in the actual string you're returning.
50     *
51     * Clients may use the ETag from a PUT request to later on make sure that
52     * when they update the file, the contents haven't changed in the mean
53     * time.
54     *
55     * @param resource|string $data
56     * @param int $rangeType
57     * @param int $offset
58     * @return string|null
59     */
60    function patch($data, $rangeType, $offset = null) {
61
62        switch ($rangeType) {
63            case 1 :
64                $f = fopen($this->path, 'a');
65                break;
66            case 2 :
67                $f = fopen($this->path, 'c');
68                fseek($f, $offset);
69                break;
70            case 3 :
71                $f = fopen($this->path, 'c');
72                fseek($f, $offset, SEEK_END);
73                break;
74        }
75        if (is_string($data)) {
76            fwrite($f, $data);
77        } else {
78            stream_copy_to_stream($data, $f);
79        }
80        fclose($f);
81        clearstatcache(true, $this->path);
82        return $this->getETag();
83
84    }
85
86    /**
87     * Returns the data
88     *
89     * @return resource
90     */
91    function get() {
92
93        return fopen($this->path, 'r');
94
95    }
96
97    /**
98     * Delete the current file
99     *
100     * @return bool
101     */
102    function delete() {
103
104        return unlink($this->path);
105
106    }
107
108    /**
109     * Returns the ETag for a file
110     *
111     * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change.
112     * The ETag is an arbitrary string, but MUST be surrounded by double-quotes.
113     *
114     * Return null if the ETag can not effectively be determined
115     *
116     * @return string|null
117     */
118    function getETag() {
119
120        return '"' . sha1(
121            fileinode($this->path) .
122            filesize($this->path) .
123            filemtime($this->path)
124        ) . '"';
125
126    }
127
128    /**
129     * Returns the mime-type for a file
130     *
131     * If null is returned, we'll assume application/octet-stream
132     *
133     * @return string|null
134     */
135    function getContentType() {
136
137        return null;
138
139    }
140
141    /**
142     * Returns the size of the file, in bytes
143     *
144     * @return int
145     */
146    function getSize() {
147
148        return filesize($this->path);
149
150    }
151
152}
153