Completed
Pull Request — stable10 (#5732)
by Morris
14:18
created
lib/public/SystemTag/ISystemTagManager.php 2 patches
Doc Comments   +7 added lines, -4 removed lines patch added patch discarded remove patch
@@ -102,17 +102,19 @@  discard block
 block discarded – undo
102 102
 	 * with the same attributes
103 103
 	 *
104 104
 	 * @since 9.0.0
105
+	 * @return void
105 106
 	 */
106 107
 	public function updateTag($tagId, $newName, $userVisible, $userAssignable);
107 108
 
108 109
 	/**
109 110
 	 * Delete the given tags from the database and all their relationships.
110 111
 	 *
111
-	 * @param string|array $tagIds array of tag ids
112
+	 * @param string $tagIds array of tag ids
112 113
 	 *
113 114
 	 * @throws \OCP\SystemTag\TagNotFoundException if at least one tag did not exist
114 115
 	 *
115 116
 	 * @since 9.0.0
117
+	 * @return void
116 118
 	 */
117 119
 	public function deleteTags($tagIds);
118 120
 
@@ -123,7 +125,7 @@  discard block
 block discarded – undo
123 125
 	 * @param ISystemTag $tag tag to check permission for
124 126
 	 * @param IUser $user user to check permission for
125 127
 	 *
126
-	 * @return true if the user is allowed to assign/unassign the tag, false otherwise
128
+	 * @return boolean if the user is allowed to assign/unassign the tag, false otherwise
127 129
 	 *
128 130
 	 * @since 9.1.0
129 131
 	 */
@@ -133,9 +135,9 @@  discard block
 block discarded – undo
133 135
 	 * Checks whether the given user is allowed to see the tag with the given id.
134 136
 	 *
135 137
 	 * @param ISystemTag $tag tag to check permission for
136
-	 * @param IUser $user user to check permission for
138
+	 * @param IUser $userId user to check permission for
137 139
 	 *
138
-	 * @return true if the user can see the tag, false otherwise
140
+	 * @return boolean if the user can see the tag, false otherwise
139 141
 	 *
140 142
 	 * @since 9.1.0
141 143
 	 */
@@ -148,6 +150,7 @@  discard block
 block discarded – undo
148 150
 	 * @param string[] $groupIds group ids of groups that can assign/unassign the tag
149 151
 	 *
150 152
 	 * @since 9.1.0
153
+	 * @return void
151 154
 	 */
152 155
 	public function setTagGroups(ISystemTag $tag, $groupIds);
153 156
 
Please login to merge, or discard this patch.
Indentation   +120 added lines, -120 removed lines patch added patch discarded remove patch
@@ -33,133 +33,133 @@
 block discarded – undo
33 33
  */
34 34
 interface ISystemTagManager {
35 35
 
36
-	/**
37
-	 * Returns the tag objects matching the given tag ids.
38
-	 *
39
-	 * @param array|string $tagIds id or array of unique ids of the tag to retrieve
40
-	 *
41
-	 * @return \OCP\SystemTag\ISystemTag[] array of system tags with tag id as key
42
-	 *
43
-	 * @throws \InvalidArgumentException if at least one given tag ids is invalid (string instead of integer, etc.)
44
-	 * @throws \OCP\SystemTag\TagNotFoundException if at least one given tag ids did no exist
45
-	 * 			The message contains a json_encoded array of the ids that could not be found
46
-	 *
47
-	 * @since 9.0.0
48
-	 */
49
-	public function getTagsByIds($tagIds);
36
+    /**
37
+     * Returns the tag objects matching the given tag ids.
38
+     *
39
+     * @param array|string $tagIds id or array of unique ids of the tag to retrieve
40
+     *
41
+     * @return \OCP\SystemTag\ISystemTag[] array of system tags with tag id as key
42
+     *
43
+     * @throws \InvalidArgumentException if at least one given tag ids is invalid (string instead of integer, etc.)
44
+     * @throws \OCP\SystemTag\TagNotFoundException if at least one given tag ids did no exist
45
+     * 			The message contains a json_encoded array of the ids that could not be found
46
+     *
47
+     * @since 9.0.0
48
+     */
49
+    public function getTagsByIds($tagIds);
50 50
 
51
-	/**
52
-	 * Returns the tag object matching the given attributes.
53
-	 *
54
-	 * @param string $tagName tag name
55
-	 * @param bool $userVisible whether the tag is visible by users
56
-	 * @param bool $userAssignable whether the tag is assignable by users
57
-	 *
58
-	 * @return \OCP\SystemTag\ISystemTag system tag
59
-	 *
60
-	 * @throws \OCP\SystemTag\TagNotFoundException if tag does not exist
61
-	 *
62
-	 * @since 9.0.0
63
-	 */
64
-	public function getTag($tagName, $userVisible, $userAssignable);
51
+    /**
52
+     * Returns the tag object matching the given attributes.
53
+     *
54
+     * @param string $tagName tag name
55
+     * @param bool $userVisible whether the tag is visible by users
56
+     * @param bool $userAssignable whether the tag is assignable by users
57
+     *
58
+     * @return \OCP\SystemTag\ISystemTag system tag
59
+     *
60
+     * @throws \OCP\SystemTag\TagNotFoundException if tag does not exist
61
+     *
62
+     * @since 9.0.0
63
+     */
64
+    public function getTag($tagName, $userVisible, $userAssignable);
65 65
 
66
-	/**
67
-	 * Creates the tag object using the given attributes.
68
-	 *
69
-	 * @param string $tagName tag name
70
-	 * @param bool $userVisible whether the tag is visible by users
71
-	 * @param bool $userAssignable whether the tag is assignable by users
72
-	 *
73
-	 * @return \OCP\SystemTag\ISystemTag system tag
74
-	 *
75
-	 * @throws \OCP\SystemTag\TagAlreadyExistsException if tag already exists
76
-	 *
77
-	 * @since 9.0.0
78
-	 */
79
-	public function createTag($tagName, $userVisible, $userAssignable);
66
+    /**
67
+     * Creates the tag object using the given attributes.
68
+     *
69
+     * @param string $tagName tag name
70
+     * @param bool $userVisible whether the tag is visible by users
71
+     * @param bool $userAssignable whether the tag is assignable by users
72
+     *
73
+     * @return \OCP\SystemTag\ISystemTag system tag
74
+     *
75
+     * @throws \OCP\SystemTag\TagAlreadyExistsException if tag already exists
76
+     *
77
+     * @since 9.0.0
78
+     */
79
+    public function createTag($tagName, $userVisible, $userAssignable);
80 80
 
81
-	/**
82
-	 * Returns all known tags, optionally filtered by visibility.
83
-	 *
84
-	 * @param bool|null $visibilityFilter filter by visibility if non-null
85
-	 * @param string $nameSearchPattern optional search pattern for the tag name
86
-	 *
87
-	 * @return \OCP\SystemTag\ISystemTag[] array of system tags or empty array if none found
88
-	 *
89
-	 * @since 9.0.0
90
-	 */
91
-	public function getAllTags($visibilityFilter = null, $nameSearchPattern = null);
81
+    /**
82
+     * Returns all known tags, optionally filtered by visibility.
83
+     *
84
+     * @param bool|null $visibilityFilter filter by visibility if non-null
85
+     * @param string $nameSearchPattern optional search pattern for the tag name
86
+     *
87
+     * @return \OCP\SystemTag\ISystemTag[] array of system tags or empty array if none found
88
+     *
89
+     * @since 9.0.0
90
+     */
91
+    public function getAllTags($visibilityFilter = null, $nameSearchPattern = null);
92 92
 
93
-	/**
94
-	 * Updates the given tag
95
-	 *
96
-	 * @param string $tagId tag id
97
-	 * @param string $newName the new tag name
98
-	 * @param bool $userVisible whether the tag is visible by users
99
-	 * @param bool $userAssignable whether the tag is assignable by users
100
-	 *
101
-	 * @throws \OCP\SystemTag\TagNotFoundException if tag with the given id does not exist
102
-	 * @throws \OCP\SystemTag\TagAlreadyExistsException if there is already another tag
103
-	 * with the same attributes
104
-	 *
105
-	 * @since 9.0.0
106
-	 */
107
-	public function updateTag($tagId, $newName, $userVisible, $userAssignable);
93
+    /**
94
+     * Updates the given tag
95
+     *
96
+     * @param string $tagId tag id
97
+     * @param string $newName the new tag name
98
+     * @param bool $userVisible whether the tag is visible by users
99
+     * @param bool $userAssignable whether the tag is assignable by users
100
+     *
101
+     * @throws \OCP\SystemTag\TagNotFoundException if tag with the given id does not exist
102
+     * @throws \OCP\SystemTag\TagAlreadyExistsException if there is already another tag
103
+     * with the same attributes
104
+     *
105
+     * @since 9.0.0
106
+     */
107
+    public function updateTag($tagId, $newName, $userVisible, $userAssignable);
108 108
 
109
-	/**
110
-	 * Delete the given tags from the database and all their relationships.
111
-	 *
112
-	 * @param string|array $tagIds array of tag ids
113
-	 *
114
-	 * @throws \OCP\SystemTag\TagNotFoundException if at least one tag did not exist
115
-	 *
116
-	 * @since 9.0.0
117
-	 */
118
-	public function deleteTags($tagIds);
109
+    /**
110
+     * Delete the given tags from the database and all their relationships.
111
+     *
112
+     * @param string|array $tagIds array of tag ids
113
+     *
114
+     * @throws \OCP\SystemTag\TagNotFoundException if at least one tag did not exist
115
+     *
116
+     * @since 9.0.0
117
+     */
118
+    public function deleteTags($tagIds);
119 119
 
120
-	/**
121
-	 * Checks whether the given user is allowed to assign/unassign the tag with the
122
-	 * given id.
123
-	 *
124
-	 * @param ISystemTag $tag tag to check permission for
125
-	 * @param IUser $user user to check permission for
126
-	 *
127
-	 * @return true if the user is allowed to assign/unassign the tag, false otherwise
128
-	 *
129
-	 * @since 9.1.0
130
-	 */
131
-	public function canUserAssignTag(ISystemTag $tag, IUser $user);
120
+    /**
121
+     * Checks whether the given user is allowed to assign/unassign the tag with the
122
+     * given id.
123
+     *
124
+     * @param ISystemTag $tag tag to check permission for
125
+     * @param IUser $user user to check permission for
126
+     *
127
+     * @return true if the user is allowed to assign/unassign the tag, false otherwise
128
+     *
129
+     * @since 9.1.0
130
+     */
131
+    public function canUserAssignTag(ISystemTag $tag, IUser $user);
132 132
 
133
-	/**
134
-	 * Checks whether the given user is allowed to see the tag with the given id.
135
-	 *
136
-	 * @param ISystemTag $tag tag to check permission for
137
-	 * @param IUser $user user to check permission for
138
-	 *
139
-	 * @return true if the user can see the tag, false otherwise
140
-	 *
141
-	 * @since 9.1.0
142
-	 */
143
-	public function canUserSeeTag(ISystemTag $tag, IUser $userId);
133
+    /**
134
+     * Checks whether the given user is allowed to see the tag with the given id.
135
+     *
136
+     * @param ISystemTag $tag tag to check permission for
137
+     * @param IUser $user user to check permission for
138
+     *
139
+     * @return true if the user can see the tag, false otherwise
140
+     *
141
+     * @since 9.1.0
142
+     */
143
+    public function canUserSeeTag(ISystemTag $tag, IUser $userId);
144 144
 
145
-	/**
146
-	 * Set groups that can assign a given tag.
147
-	 *
148
-	 * @param ISystemTag $tag tag for group assignment
149
-	 * @param string[] $groupIds group ids of groups that can assign/unassign the tag
150
-	 *
151
-	 * @since 9.1.0
152
-	 */
153
-	public function setTagGroups(ISystemTag $tag, $groupIds);
145
+    /**
146
+     * Set groups that can assign a given tag.
147
+     *
148
+     * @param ISystemTag $tag tag for group assignment
149
+     * @param string[] $groupIds group ids of groups that can assign/unassign the tag
150
+     *
151
+     * @since 9.1.0
152
+     */
153
+    public function setTagGroups(ISystemTag $tag, $groupIds);
154 154
 
155
-	/**
156
-	 * Get groups that can assign a given tag.
157
-	 *
158
-	 * @param ISystemTag $tag tag for group assignment
159
-	 *
160
-	 * @return string[] group ids of groups that can assign/unassign the tag
161
-	 *
162
-	 * @since 9.1.0
163
-	 */
164
-	public function getTagGroups(ISystemTag $tag);
155
+    /**
156
+     * Get groups that can assign a given tag.
157
+     *
158
+     * @param ISystemTag $tag tag for group assignment
159
+     *
160
+     * @return string[] group ids of groups that can assign/unassign the tag
161
+     *
162
+     * @since 9.1.0
163
+     */
164
+    public function getTagGroups(ISystemTag $tag);
165 165
 }
Please login to merge, or discard this patch.
lib/public/Template.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -100,8 +100,8 @@
 block discarded – undo
100 100
 /**
101 101
  * Return the relative date in relation to today. Returns something like "last hour" or "two month ago"
102 102
  * @param int $timestamp unix timestamp
103
- * @param boolean $dateOnly
104
- * @return \OC_L10N_String human readable interpretation of the timestamp
103
+ * @param integer $dateOnly
104
+ * @return string human readable interpretation of the timestamp
105 105
  *
106 106
  * @deprecated 8.0.0 Use \OCP\Template::relative_modified_date() instead
107 107
  */
Please login to merge, or discard this patch.
Indentation   +94 added lines, -94 removed lines patch added patch discarded remove patch
@@ -50,7 +50,7 @@  discard block
 block discarded – undo
50 50
  * @deprecated 8.0.0 Use \OCP\Template::image_path() instead
51 51
  */
52 52
 function image_path( $app, $image ) {
53
-	return(\image_path( $app, $image ));
53
+    return(\image_path( $app, $image ));
54 54
 }
55 55
 
56 56
 
@@ -61,7 +61,7 @@  discard block
 block discarded – undo
61 61
  * @deprecated 8.0.0 Use \OCP\Template::mimetype_icon() instead
62 62
  */
63 63
 function mimetype_icon( $mimetype ) {
64
-	return(\mimetype_icon( $mimetype ));
64
+    return(\mimetype_icon( $mimetype ));
65 65
 }
66 66
 
67 67
 /**
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
  * @deprecated 8.0.0 Use \OCP\Template::preview_icon() instead
72 72
  */
73 73
 function preview_icon( $path ) {
74
-	return(\preview_icon( $path ));
74
+    return(\preview_icon( $path ));
75 75
 }
76 76
 
77 77
 /**
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
  * @deprecated 8.0.0 Use \OCP\Template::publicPreview_icon() instead
84 84
  */
85 85
 function publicPreview_icon ( $path, $token ) {
86
-	return(\publicPreview_icon( $path, $token ));
86
+    return(\publicPreview_icon( $path, $token ));
87 87
 }
88 88
 
89 89
 /**
@@ -94,7 +94,7 @@  discard block
 block discarded – undo
94 94
  * @deprecated 8.0.0 Use \OCP\Template::human_file_size() instead
95 95
  */
96 96
 function human_file_size( $bytes ) {
97
-	return(\human_file_size( $bytes ));
97
+    return(\human_file_size( $bytes ));
98 98
 }
99 99
 
100 100
 
@@ -107,7 +107,7 @@  discard block
 block discarded – undo
107 107
  * @deprecated 8.0.0 Use \OCP\Template::relative_modified_date() instead
108 108
  */
109 109
 function relative_modified_date( $timestamp, $dateOnly = false ) {
110
-	return(\relative_modified_date($timestamp, null, $dateOnly));
110
+    return(\relative_modified_date($timestamp, null, $dateOnly));
111 111
 }
112 112
 
113 113
 
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
  * @deprecated 8.0.0 Use \OCP\Template::human_file_size() instead
119 119
  */
120 120
 function simple_file_size($bytes) {
121
-	return(\human_file_size($bytes));
121
+    return(\human_file_size($bytes));
122 122
 }
123 123
 
124 124
 
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
  * @deprecated 8.0.0 Use \OCP\Template::html_select_options() instead
132 132
  */
133 133
 function html_select_options($options, $selected, $params=array()) {
134
-	return(\html_select_options($options, $selected, $params));
134
+    return(\html_select_options($options, $selected, $params));
135 135
 }
136 136
 
137 137
 
@@ -142,90 +142,90 @@  discard block
 block discarded – undo
142 142
  * @since 8.0.0
143 143
  */
144 144
 class Template extends \OC_Template {
145
-	/**
146
-	 * Make OC_Helper::imagePath available as a simple function
147
-	 *
148
-	 * @see \OCP\IURLGenerator::imagePath
149
-	 *
150
-	 * @param string $app
151
-	 * @param string $image
152
-	 * @return string to the image
153
-	 * @since 8.0.0
154
-	 */
155
-	public static function image_path($app, $image) {
156
-		return \image_path($app, $image);
157
-	}
158
-
159
-
160
-	/**
161
-	 * Make OC_Helper::mimetypeIcon available as a simple function
162
-	 *
163
-	 * @param string $mimetype
164
-	 * @return string to the image of this file type.
165
-	 * @since 8.0.0
166
-	 */
167
-	public static function mimetype_icon($mimetype) {
168
-		return \mimetype_icon($mimetype);
169
-	}
170
-
171
-	/**
172
-	 * Make preview_icon available as a simple function
173
-	 *
174
-	 * @param string $path path to file
175
-	 * @return string to the preview of the image
176
-	 * @since 8.0.0
177
-	 */
178
-	public static function preview_icon($path) {
179
-		return \preview_icon($path);
180
-	}
181
-
182
-	/**
183
-	 * Make publicpreview_icon available as a simple function
184
-	 * Returns the path to the preview of the image.
185
-	 *
186
-	 * @param string $path of file
187
-	 * @param string $token
188
-	 * @return string link to the preview
189
-	 * @since 8.0.0
190
-	 */
191
-	public static function publicPreview_icon($path, $token) {
192
-		return \publicPreview_icon($path, $token);
193
-	}
194
-
195
-	/**
196
-	 * Make OC_Helper::humanFileSize available as a simple function
197
-	 * Example: 2048 to 2 kB.
198
-	 *
199
-	 * @param int $bytes in bytes
200
-	 * @return string size as string
201
-	 * @since 8.0.0
202
-	 */
203
-	public static function human_file_size($bytes) {
204
-		return \human_file_size($bytes);
205
-	}
206
-
207
-	/**
208
-	 * Return the relative date in relation to today. Returns something like "last hour" or "two month ago"
209
-	 *
210
-	 * @param int $timestamp unix timestamp
211
-	 * @param boolean $dateOnly
212
-	 * @return string human readable interpretation of the timestamp
213
-	 * @since 8.0.0
214
-	 */
215
-	public static function relative_modified_date($timestamp, $dateOnly = false) {
216
-		return \relative_modified_date($timestamp, null, $dateOnly);
217
-	}
218
-
219
-	/**
220
-	 * Generate html code for an options block.
221
-	 *
222
-	 * @param array $options the options
223
-	 * @param mixed $selected which one is selected?
224
-	 * @param array $params the parameters
225
-	 * @return string html options
226
-	 * @since 8.0.0
227
-	 */
228
-	public static function html_select_options($options, $selected, $params=array()) {
229
-		return \html_select_options($options, $selected, $params);
230
-	}
145
+    /**
146
+     * Make OC_Helper::imagePath available as a simple function
147
+     *
148
+     * @see \OCP\IURLGenerator::imagePath
149
+     *
150
+     * @param string $app
151
+     * @param string $image
152
+     * @return string to the image
153
+     * @since 8.0.0
154
+     */
155
+    public static function image_path($app, $image) {
156
+        return \image_path($app, $image);
157
+    }
158
+
159
+
160
+    /**
161
+     * Make OC_Helper::mimetypeIcon available as a simple function
162
+     *
163
+     * @param string $mimetype
164
+     * @return string to the image of this file type.
165
+     * @since 8.0.0
166
+     */
167
+    public static function mimetype_icon($mimetype) {
168
+        return \mimetype_icon($mimetype);
169
+    }
170
+
171
+    /**
172
+     * Make preview_icon available as a simple function
173
+     *
174
+     * @param string $path path to file
175
+     * @return string to the preview of the image
176
+     * @since 8.0.0
177
+     */
178
+    public static function preview_icon($path) {
179
+        return \preview_icon($path);
180
+    }
181
+
182
+    /**
183
+     * Make publicpreview_icon available as a simple function
184
+     * Returns the path to the preview of the image.
185
+     *
186
+     * @param string $path of file
187
+     * @param string $token
188
+     * @return string link to the preview
189
+     * @since 8.0.0
190
+     */
191
+    public static function publicPreview_icon($path, $token) {
192
+        return \publicPreview_icon($path, $token);
193
+    }
194
+
195
+    /**
196
+     * Make OC_Helper::humanFileSize available as a simple function
197
+     * Example: 2048 to 2 kB.
198
+     *
199
+     * @param int $bytes in bytes
200
+     * @return string size as string
201
+     * @since 8.0.0
202
+     */
203
+    public static function human_file_size($bytes) {
204
+        return \human_file_size($bytes);
205
+    }
206
+
207
+    /**
208
+     * Return the relative date in relation to today. Returns something like "last hour" or "two month ago"
209
+     *
210
+     * @param int $timestamp unix timestamp
211
+     * @param boolean $dateOnly
212
+     * @return string human readable interpretation of the timestamp
213
+     * @since 8.0.0
214
+     */
215
+    public static function relative_modified_date($timestamp, $dateOnly = false) {
216
+        return \relative_modified_date($timestamp, null, $dateOnly);
217
+    }
218
+
219
+    /**
220
+     * Generate html code for an options block.
221
+     *
222
+     * @param array $options the options
223
+     * @param mixed $selected which one is selected?
224
+     * @param array $params the parameters
225
+     * @return string html options
226
+     * @since 8.0.0
227
+     */
228
+    public static function html_select_options($options, $selected, $params=array()) {
229
+        return \html_select_options($options, $selected, $params);
230
+    }
231 231
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -49,8 +49,8 @@  discard block
 block discarded – undo
49 49
  * @see \OCP\IURLGenerator::imagePath
50 50
  * @deprecated 8.0.0 Use \OCP\Template::image_path() instead
51 51
  */
52
-function image_path( $app, $image ) {
53
-	return(\image_path( $app, $image ));
52
+function image_path($app, $image) {
53
+	return(\image_path($app, $image));
54 54
 }
55 55
 
56 56
 
@@ -60,8 +60,8 @@  discard block
 block discarded – undo
60 60
  * @return string to the image of this file type.
61 61
  * @deprecated 8.0.0 Use \OCP\Template::mimetype_icon() instead
62 62
  */
63
-function mimetype_icon( $mimetype ) {
64
-	return(\mimetype_icon( $mimetype ));
63
+function mimetype_icon($mimetype) {
64
+	return(\mimetype_icon($mimetype));
65 65
 }
66 66
 
67 67
 /**
@@ -70,8 +70,8 @@  discard block
 block discarded – undo
70 70
  * @return string to the preview of the image
71 71
  * @deprecated 8.0.0 Use \OCP\Template::preview_icon() instead
72 72
  */
73
-function preview_icon( $path ) {
74
-	return(\preview_icon( $path ));
73
+function preview_icon($path) {
74
+	return(\preview_icon($path));
75 75
 }
76 76
 
77 77
 /**
@@ -82,8 +82,8 @@  discard block
 block discarded – undo
82 82
  * @return string link to the preview
83 83
  * @deprecated 8.0.0 Use \OCP\Template::publicPreview_icon() instead
84 84
  */
85
-function publicPreview_icon ( $path, $token ) {
86
-	return(\publicPreview_icon( $path, $token ));
85
+function publicPreview_icon($path, $token) {
86
+	return(\publicPreview_icon($path, $token));
87 87
 }
88 88
 
89 89
 /**
@@ -93,8 +93,8 @@  discard block
 block discarded – undo
93 93
  * @return string size as string
94 94
  * @deprecated 8.0.0 Use \OCP\Template::human_file_size() instead
95 95
  */
96
-function human_file_size( $bytes ) {
97
-	return(\human_file_size( $bytes ));
96
+function human_file_size($bytes) {
97
+	return(\human_file_size($bytes));
98 98
 }
99 99
 
100 100
 
@@ -106,7 +106,7 @@  discard block
 block discarded – undo
106 106
  *
107 107
  * @deprecated 8.0.0 Use \OCP\Template::relative_modified_date() instead
108 108
  */
109
-function relative_modified_date( $timestamp, $dateOnly = false ) {
109
+function relative_modified_date($timestamp, $dateOnly = false) {
110 110
 	return(\relative_modified_date($timestamp, null, $dateOnly));
111 111
 }
112 112
 
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
  * @return string html options
131 131
  * @deprecated 8.0.0 Use \OCP\Template::html_select_options() instead
132 132
  */
133
-function html_select_options($options, $selected, $params=array()) {
133
+function html_select_options($options, $selected, $params = array()) {
134 134
 	return(\html_select_options($options, $selected, $params));
135 135
 }
136 136
 
@@ -225,7 +225,7 @@  discard block
 block discarded – undo
225 225
 	 * @return string html options
226 226
 	 * @since 8.0.0
227 227
 	 */
228
-	public static function html_select_options($options, $selected, $params=array()) {
228
+	public static function html_select_options($options, $selected, $params = array()) {
229 229
 		return \html_select_options($options, $selected, $params);
230 230
 	}
231 231
 }
Please login to merge, or discard this patch.
lib/public/Util.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -544,7 +544,7 @@
 block discarded – undo
544 544
 	 * @param array $input The array to work on
545 545
 	 * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
546 546
 	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
547
-	 * @return array
547
+	 * @return string
548 548
 	 * @since 4.5.0
549 549
 	 */
550 550
 	public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -58,11 +58,11 @@  discard block
 block discarded – undo
58 58
  */
59 59
 class Util {
60 60
 	// consts for Logging
61
-	const DEBUG=0;
62
-	const INFO=1;
63
-	const WARN=2;
64
-	const ERROR=3;
65
-	const FATAL=4;
61
+	const DEBUG = 0;
62
+	const INFO = 1;
63
+	const WARN = 2;
64
+	const ERROR = 3;
65
+	const FATAL = 4;
66 66
 
67 67
 	/** \OCP\Share\IManager */
68 68
 	private static $shareManager;
@@ -118,11 +118,11 @@  discard block
 block discarded – undo
118 118
 		$message->setSubject($subject);
119 119
 		$message->setPlainBody($mailtext);
120 120
 		$message->setFrom([$fromaddress => $fromname]);
121
-		if($html === 1) {
121
+		if ($html === 1) {
122 122
 			$message->setHTMLBody($altbody);
123 123
 		}
124 124
 
125
-		if($altbody === '') {
125
+		if ($altbody === '') {
126 126
 			$message->setHTMLBody($mailtext);
127 127
 			$message->setPlainBody('');
128 128
 		} else {
@@ -130,14 +130,14 @@  discard block
 block discarded – undo
130 130
 			$message->setPlainBody($altbody);
131 131
 		}
132 132
 
133
-		if(!empty($ccaddress)) {
134
-			if(!empty($ccname)) {
133
+		if (!empty($ccaddress)) {
134
+			if (!empty($ccname)) {
135 135
 				$message->setCc([$ccaddress => $ccname]);
136 136
 			} else {
137 137
 				$message->setCc([$ccaddress]);
138 138
 			}
139 139
 		}
140
-		if(!empty($bcc)) {
140
+		if (!empty($bcc)) {
141 141
 			$message->setBcc([$bcc]);
142 142
 		}
143 143
 
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
 	 * @param int $level
152 152
 	 * @since 4.0.0
153 153
 	 */
154
-	public static function writeLog( $app, $message, $level ) {
154
+	public static function writeLog($app, $message, $level) {
155 155
 		$context = ['app' => $app];
156 156
 		\OC::$server->getLogger()->log($level, $message, $context);
157 157
 	}
@@ -164,7 +164,7 @@  discard block
 block discarded – undo
164 164
 	 * @since ....0.0 - parameter $level was added in 7.0.0
165 165
 	 * @deprecated 8.2.0 use logException of \OCP\ILogger
166 166
 	 */
167
-	public static function logException( $app, \Exception $ex, $level = \OCP\Util::FATAL ) {
167
+	public static function logException($app, \Exception $ex, $level = \OCP\Util::FATAL) {
168 168
 		\OC::$server->getLogger()->logException($ex, ['app' => $app]);
169 169
 	}
170 170
 
@@ -205,8 +205,8 @@  discard block
 block discarded – undo
205 205
 	 * @param string $file
206 206
 	 * @since 4.0.0
207 207
 	 */
208
-	public static function addStyle( $application, $file = null ) {
209
-		\OC_Util::addStyle( $application, $file );
208
+	public static function addStyle($application, $file = null) {
209
+		\OC_Util::addStyle($application, $file);
210 210
 	}
211 211
 
212 212
 	/**
@@ -215,8 +215,8 @@  discard block
 block discarded – undo
215 215
 	 * @param string $file
216 216
 	 * @since 4.0.0
217 217
 	 */
218
-	public static function addScript( $application, $file = null ) {
219
-		\OC_Util::addScript( $application, $file );
218
+	public static function addScript($application, $file = null) {
219
+		\OC_Util::addScript($application, $file);
220 220
 	}
221 221
 
222 222
 	/**
@@ -238,7 +238,7 @@  discard block
 block discarded – undo
238 238
 	 * @param string $text the text content for the element
239 239
 	 * @since 4.0.0
240 240
 	 */
241
-	public static function addHeader($tag, $attributes, $text=null) {
241
+	public static function addHeader($tag, $attributes, $text = null) {
242 242
 		\OC_Util::addHeader($tag, $attributes, $text);
243 243
 	}
244 244
 
@@ -252,7 +252,7 @@  discard block
 block discarded – undo
252 252
 	 * @deprecated 8.0.0 Use \OC::$server->query('DateTimeFormatter') instead
253 253
 	 * @since 4.0.0
254 254
 	 */
255
-	public static function formatDate($timestamp, $dateOnly=false, $timeZone = null) {
255
+	public static function formatDate($timestamp, $dateOnly = false, $timeZone = null) {
256 256
 		return(\OC_Util::formatDate($timestamp, $dateOnly, $timeZone));
257 257
 	}
258 258
 
@@ -276,7 +276,7 @@  discard block
 block discarded – undo
276 276
 	 * @return string the url
277 277
 	 * @since 4.0.0 - parameter $args was added in 4.5.0
278 278
 	 */
279
-	public static function linkToAbsolute( $app, $file, $args = array() ) {
279
+	public static function linkToAbsolute($app, $file, $args = array()) {
280 280
 		$urlGenerator = \OC::$server->getURLGenerator();
281 281
 		return $urlGenerator->getAbsoluteURL(
282 282
 			$urlGenerator->linkTo($app, $file, $args)
@@ -289,11 +289,11 @@  discard block
 block discarded – undo
289 289
 	 * @return string the url
290 290
 	 * @since 4.0.0
291 291
 	 */
292
-	public static function linkToRemote( $service ) {
292
+	public static function linkToRemote($service) {
293 293
 		$urlGenerator = \OC::$server->getURLGenerator();
294
-		$remoteBase = $urlGenerator->linkTo('', 'remote.php') . '/' . $service;
294
+		$remoteBase = $urlGenerator->linkTo('', 'remote.php').'/'.$service;
295 295
 		return $urlGenerator->getAbsoluteURL(
296
-			$remoteBase . (($service[strlen($service) - 1] != '/') ? '/' : '')
296
+			$remoteBase.(($service[strlen($service) - 1] != '/') ? '/' : '')
297 297
 		);
298 298
 	}
299 299
 
@@ -316,7 +316,7 @@  discard block
 block discarded – undo
316 316
 	 * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->linkToRoute($route, $parameters)
317 317
 	 * @since 5.0.0
318 318
 	 */
319
-	public static function linkToRoute( $route, $parameters = array() ) {
319
+	public static function linkToRoute($route, $parameters = array()) {
320 320
 		return \OC::$server->getURLGenerator()->linkToRoute($route, $parameters);
321 321
 	}
322 322
 
@@ -330,7 +330,7 @@  discard block
 block discarded – undo
330 330
 	 * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->linkTo($app, $file, $args)
331 331
 	 * @since 4.0.0 - parameter $args was added in 4.5.0
332 332
 	 */
333
-	public static function linkTo( $app, $file, $args = array() ) {
333
+	public static function linkTo($app, $file, $args = array()) {
334 334
 		return \OC::$server->getURLGenerator()->linkTo($app, $file, $args);
335 335
 	}
336 336
 
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
 	 * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->imagePath($app, $image)
430 430
 	 * @since 4.0.0
431 431
 	 */
432
-	public static function imagePath( $app, $image ) {
432
+	public static function imagePath($app, $image) {
433 433
 		return \OC::$server->getURLGenerator()->imagePath($app, $image);
434 434
 	}
435 435
 
@@ -439,8 +439,8 @@  discard block
 block discarded – undo
439 439
 	 * @return string a human readable file size
440 440
 	 * @since 4.0.0
441 441
 	 */
442
-	public static function humanFileSize( $bytes ) {
443
-		return(\OC_Helper::humanFileSize( $bytes ));
442
+	public static function humanFileSize($bytes) {
443
+		return(\OC_Helper::humanFileSize($bytes));
444 444
 	}
445 445
 
446 446
 	/**
@@ -451,8 +451,8 @@  discard block
 block discarded – undo
451 451
 	 * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
452 452
 	 * @since 4.0.0
453 453
 	 */
454
-	public static function computerFileSize( $str ) {
455
-		return(\OC_Helper::computerFileSize( $str ));
454
+	public static function computerFileSize($str) {
455
+		return(\OC_Helper::computerFileSize($str));
456 456
 	}
457 457
 
458 458
 	/**
@@ -469,8 +469,8 @@  discard block
 block discarded – undo
469 469
 	 * TODO: write example
470 470
 	 * @since 4.0.0
471 471
 	 */
472
-	static public function connectHook($signalClass, $signalName, $slotClass, $slotName ) {
473
-		return(\OC_Hook::connect($signalClass, $signalName, $slotClass, $slotName ));
472
+	static public function connectHook($signalClass, $signalName, $slotClass, $slotName) {
473
+		return(\OC_Hook::connect($signalClass, $signalName, $slotClass, $slotName));
474 474
 	}
475 475
 
476 476
 	/**
@@ -483,8 +483,8 @@  discard block
 block discarded – undo
483 483
 	 * TODO: write example
484 484
 	 * @since 4.0.0
485 485
 	 */
486
-	static public function emitHook( $signalclass, $signalname, $params = array()) {
487
-		return(\OC_Hook::emit( $signalclass, $signalname, $params ));
486
+	static public function emitHook($signalclass, $signalname, $params = array()) {
487
+		return(\OC_Hook::emit($signalclass, $signalname, $params));
488 488
 	}
489 489
 
490 490
 	/**
@@ -500,7 +500,7 @@  discard block
 block discarded – undo
500 500
 	 * @since 4.5.0
501 501
 	 */
502 502
 	public static function callRegister() {
503
-		if(self::$token === '') {
503
+		if (self::$token === '') {
504 504
 			self::$token = \OC::$server->getCsrfTokenManager()->getToken()->getEncryptedValue();
505 505
 		}
506 506
 		return self::$token;
@@ -512,7 +512,7 @@  discard block
 block discarded – undo
512 512
 	 * @deprecated 9.0.0 Use annotations based on the app framework.
513 513
 	 */
514 514
 	public static function callCheck() {
515
-		if(!\OC::$server->getRequest()->passesStrictCookieCheck()) {
515
+		if (!\OC::$server->getRequest()->passesStrictCookieCheck()) {
516 516
 			header('Location: '.\OC::$WEBROOT);
517 517
 			exit();
518 518
 		}
@@ -703,7 +703,7 @@  discard block
 block discarded – undo
703 703
 	 */
704 704
 	public static function needUpgrade() {
705 705
 		if (!isset(self::$needUpgradeCache)) {
706
-			self::$needUpgradeCache=\OC_Util::needUpgrade(\OC::$server->getConfig());
706
+			self::$needUpgradeCache = \OC_Util::needUpgrade(\OC::$server->getConfig());
707 707
 		}		
708 708
 		return self::$needUpgradeCache;
709 709
 	}
Please login to merge, or discard this patch.
Indentation   +651 added lines, -651 removed lines patch added patch discarded remove patch
@@ -57,657 +57,657 @@
 block discarded – undo
57 57
  * @since 4.0.0
58 58
  */
59 59
 class Util {
60
-	// consts for Logging
61
-	const DEBUG=0;
62
-	const INFO=1;
63
-	const WARN=2;
64
-	const ERROR=3;
65
-	const FATAL=4;
66
-
67
-	/** \OCP\Share\IManager */
68
-	private static $shareManager;
69
-
70
-	/**
71
-	 * get the current installed version of ownCloud
72
-	 * @return array
73
-	 * @since 4.0.0
74
-	 */
75
-	public static function getVersion() {
76
-		return(\OC_Util::getVersion());
77
-	}
60
+    // consts for Logging
61
+    const DEBUG=0;
62
+    const INFO=1;
63
+    const WARN=2;
64
+    const ERROR=3;
65
+    const FATAL=4;
66
+
67
+    /** \OCP\Share\IManager */
68
+    private static $shareManager;
69
+
70
+    /**
71
+     * get the current installed version of ownCloud
72
+     * @return array
73
+     * @since 4.0.0
74
+     */
75
+    public static function getVersion() {
76
+        return(\OC_Util::getVersion());
77
+    }
78 78
 	
79
-	/**
80
-	 * Set current update channel
81
-	 * @param string $channel
82
-	 * @since 8.1.0
83
-	 */
84
-	public static function setChannel($channel) {
85
-		//Flush timestamp to reload version.php
86
-		\OC::$server->getSession()->set('OC_Version_Timestamp', 0);
87
-		\OC::$server->getAppConfig()->setValue('core', 'OC_Channel', $channel);
88
-		\OC::$server->getConfig()->setSystemValue('updater.release.channel', $channel);
89
-	}
79
+    /**
80
+     * Set current update channel
81
+     * @param string $channel
82
+     * @since 8.1.0
83
+     */
84
+    public static function setChannel($channel) {
85
+        //Flush timestamp to reload version.php
86
+        \OC::$server->getSession()->set('OC_Version_Timestamp', 0);
87
+        \OC::$server->getAppConfig()->setValue('core', 'OC_Channel', $channel);
88
+        \OC::$server->getConfig()->setSystemValue('updater.release.channel', $channel);
89
+    }
90 90
 	
91
-	/**
92
-	 * Get current update channel
93
-	 * @return string
94
-	 * @since 8.1.0
95
-	 */
96
-	public static function getChannel() {
97
-		return \OC_Util::getChannel();
98
-	}
99
-
100
-	/**
101
-	 * send an email
102
-	 * @param string $toaddress
103
-	 * @param string $toname
104
-	 * @param string $subject
105
-	 * @param string $mailtext
106
-	 * @param string $fromaddress
107
-	 * @param string $fromname
108
-	 * @param int $html
109
-	 * @param string $altbody
110
-	 * @param string $ccaddress
111
-	 * @param string $ccname
112
-	 * @param string $bcc
113
-	 * @deprecated 8.1.0 Use \OCP\Mail\IMailer instead
114
-	 * @since 4.0.0
115
-	 */
116
-	public static function sendMail($toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname,
117
-		$html = 0, $altbody = '', $ccaddress = '', $ccname = '', $bcc = '') {
118
-		$mailer = \OC::$server->getMailer();
119
-		$message = $mailer->createMessage();
120
-		$message->setTo([$toaddress => $toname]);
121
-		$message->setSubject($subject);
122
-		$message->setPlainBody($mailtext);
123
-		$message->setFrom([$fromaddress => $fromname]);
124
-		if($html === 1) {
125
-			$message->setHTMLBody($altbody);
126
-		}
127
-
128
-		if($altbody === '') {
129
-			$message->setHTMLBody($mailtext);
130
-			$message->setPlainBody('');
131
-		} else {
132
-			$message->setHtmlBody($mailtext);
133
-			$message->setPlainBody($altbody);
134
-		}
135
-
136
-		if(!empty($ccaddress)) {
137
-			if(!empty($ccname)) {
138
-				$message->setCc([$ccaddress => $ccname]);
139
-			} else {
140
-				$message->setCc([$ccaddress]);
141
-			}
142
-		}
143
-		if(!empty($bcc)) {
144
-			$message->setBcc([$bcc]);
145
-		}
146
-
147
-		$mailer->send($message);
148
-	}
149
-
150
-	/**
151
-	 * write a message in the log
152
-	 * @param string $app
153
-	 * @param string $message
154
-	 * @param int $level
155
-	 * @since 4.0.0
156
-	 */
157
-	public static function writeLog( $app, $message, $level ) {
158
-		$context = ['app' => $app];
159
-		\OC::$server->getLogger()->log($level, $message, $context);
160
-	}
161
-
162
-	/**
163
-	 * write exception into the log
164
-	 * @param string $app app name
165
-	 * @param \Exception $ex exception to log
166
-	 * @param int $level log level, defaults to \OCP\Util::FATAL
167
-	 * @since ....0.0 - parameter $level was added in 7.0.0
168
-	 * @deprecated 8.2.0 use logException of \OCP\ILogger
169
-	 */
170
-	public static function logException( $app, \Exception $ex, $level = \OCP\Util::FATAL ) {
171
-		\OC::$server->getLogger()->logException($ex, ['app' => $app]);
172
-	}
173
-
174
-	/**
175
-	 * check if sharing is disabled for the current user
176
-	 *
177
-	 * @return boolean
178
-	 * @since 7.0.0
179
-	 * @deprecated 9.1.0 Use \OC::$server->getShareManager()->sharingDisabledForUser
180
-	 */
181
-	public static function isSharingDisabledForUser() {
182
-		if (self::$shareManager === null) {
183
-			self::$shareManager = \OC::$server->getShareManager();
184
-		}
185
-
186
-		$user = \OC::$server->getUserSession()->getUser();
187
-		if ($user !== null) {
188
-			$user = $user->getUID();
189
-		}
190
-
191
-		return self::$shareManager->sharingDisabledForUser($user);
192
-	}
193
-
194
-	/**
195
-	 * get l10n object
196
-	 * @param string $application
197
-	 * @param string|null $language
198
-	 * @return \OC_L10N
199
-	 * @since 6.0.0 - parameter $language was added in 8.0.0
200
-	 */
201
-	public static function getL10N($application, $language = null) {
202
-		return \OC::$server->getL10N($application, $language);
203
-	}
204
-
205
-	/**
206
-	 * add a css file
207
-	 * @param string $application
208
-	 * @param string $file
209
-	 * @since 4.0.0
210
-	 */
211
-	public static function addStyle( $application, $file = null ) {
212
-		\OC_Util::addStyle( $application, $file );
213
-	}
214
-
215
-	/**
216
-	 * add a javascript file
217
-	 * @param string $application
218
-	 * @param string $file
219
-	 * @since 4.0.0
220
-	 */
221
-	public static function addScript( $application, $file = null ) {
222
-		\OC_Util::addScript( $application, $file );
223
-	}
224
-
225
-	/**
226
-	 * Add a translation JS file
227
-	 * @param string $application application id
228
-	 * @param string $languageCode language code, defaults to the current locale
229
-	 * @since 8.0.0
230
-	 */
231
-	public static function addTranslations($application, $languageCode = null) {
232
-		\OC_Util::addTranslations($application, $languageCode);
233
-	}
234
-
235
-	/**
236
-	 * Add a custom element to the header
237
-	 * If $text is null then the element will be written as empty element.
238
-	 * So use "" to get a closing tag.
239
-	 * @param string $tag tag name of the element
240
-	 * @param array $attributes array of attributes for the element
241
-	 * @param string $text the text content for the element
242
-	 * @since 4.0.0
243
-	 */
244
-	public static function addHeader($tag, $attributes, $text=null) {
245
-		\OC_Util::addHeader($tag, $attributes, $text);
246
-	}
247
-
248
-	/**
249
-	 * formats a timestamp in the "right" way
250
-	 * @param int $timestamp $timestamp
251
-	 * @param bool $dateOnly option to omit time from the result
252
-	 * @param DateTimeZone|string $timeZone where the given timestamp shall be converted to
253
-	 * @return string timestamp
254
-	 *
255
-	 * @deprecated 8.0.0 Use \OC::$server->query('DateTimeFormatter') instead
256
-	 * @since 4.0.0
257
-	 */
258
-	public static function formatDate($timestamp, $dateOnly=false, $timeZone = null) {
259
-		return(\OC_Util::formatDate($timestamp, $dateOnly, $timeZone));
260
-	}
261
-
262
-	/**
263
-	 * check if some encrypted files are stored
264
-	 * @return bool
265
-	 *
266
-	 * @deprecated 8.1.0 No longer required
267
-	 * @since 6.0.0
268
-	 */
269
-	public static function encryptedFiles() {
270
-		return false;
271
-	}
272
-
273
-	/**
274
-	 * Creates an absolute url to the given app and file.
275
-	 * @param string $app app
276
-	 * @param string $file file
277
-	 * @param array $args array with param=>value, will be appended to the returned url
278
-	 * 	The value of $args will be urlencoded
279
-	 * @return string the url
280
-	 * @since 4.0.0 - parameter $args was added in 4.5.0
281
-	 */
282
-	public static function linkToAbsolute( $app, $file, $args = array() ) {
283
-		$urlGenerator = \OC::$server->getURLGenerator();
284
-		return $urlGenerator->getAbsoluteURL(
285
-			$urlGenerator->linkTo($app, $file, $args)
286
-		);
287
-	}
288
-
289
-	/**
290
-	 * Creates an absolute url for remote use.
291
-	 * @param string $service id
292
-	 * @return string the url
293
-	 * @since 4.0.0
294
-	 */
295
-	public static function linkToRemote( $service ) {
296
-		$urlGenerator = \OC::$server->getURLGenerator();
297
-		$remoteBase = $urlGenerator->linkTo('', 'remote.php') . '/' . $service;
298
-		return $urlGenerator->getAbsoluteURL(
299
-			$remoteBase . (($service[strlen($service) - 1] != '/') ? '/' : '')
300
-		);
301
-	}
302
-
303
-	/**
304
-	 * Creates an absolute url for public use
305
-	 * @param string $service id
306
-	 * @return string the url
307
-	 * @since 4.5.0
308
-	 */
309
-	public static function linkToPublic($service) {
310
-		return \OC_Helper::linkToPublic($service);
311
-	}
312
-
313
-	/**
314
-	 * Creates an url using a defined route
315
-	 * @param string $route
316
-	 * @param array $parameters
317
-	 * @internal param array $args with param=>value, will be appended to the returned url
318
-	 * @return string the url
319
-	 * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->linkToRoute($route, $parameters)
320
-	 * @since 5.0.0
321
-	 */
322
-	public static function linkToRoute( $route, $parameters = array() ) {
323
-		return \OC::$server->getURLGenerator()->linkToRoute($route, $parameters);
324
-	}
325
-
326
-	/**
327
-	 * Creates an url to the given app and file
328
-	 * @param string $app app
329
-	 * @param string $file file
330
-	 * @param array $args array with param=>value, will be appended to the returned url
331
-	 * 	The value of $args will be urlencoded
332
-	 * @return string the url
333
-	 * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->linkTo($app, $file, $args)
334
-	 * @since 4.0.0 - parameter $args was added in 4.5.0
335
-	 */
336
-	public static function linkTo( $app, $file, $args = array() ) {
337
-		return \OC::$server->getURLGenerator()->linkTo($app, $file, $args);
338
-	}
339
-
340
-	/**
341
-	 * Returns the server host, even if the website uses one or more reverse proxy
342
-	 * @return string the server host
343
-	 * @deprecated 8.1.0 Use \OCP\IRequest::getServerHost
344
-	 * @since 4.0.0
345
-	 */
346
-	public static function getServerHost() {
347
-		return \OC::$server->getRequest()->getServerHost();
348
-	}
349
-
350
-	/**
351
-	 * Returns the server host name without an eventual port number
352
-	 * @return string the server hostname
353
-	 * @since 5.0.0
354
-	 */
355
-	public static function getServerHostName() {
356
-		$host_name = self::getServerHost();
357
-		// strip away port number (if existing)
358
-		$colon_pos = strpos($host_name, ':');
359
-		if ($colon_pos != FALSE) {
360
-			$host_name = substr($host_name, 0, $colon_pos);
361
-		}
362
-		return $host_name;
363
-	}
364
-
365
-	/**
366
-	 * Returns the default email address
367
-	 * @param string $user_part the user part of the address
368
-	 * @return string the default email address
369
-	 *
370
-	 * Assembles a default email address (using the server hostname
371
-	 * and the given user part, and returns it
372
-	 * Example: when given lostpassword-noreply as $user_part param,
373
-	 *     and is currently accessed via http(s)://example.com/,
374
-	 *     it would return '[email protected]'
375
-	 *
376
-	 * If the configuration value 'mail_from_address' is set in
377
-	 * config.php, this value will override the $user_part that
378
-	 * is passed to this function
379
-	 * @since 5.0.0
380
-	 */
381
-	public static function getDefaultEmailAddress($user_part) {
382
-		$config = \OC::$server->getConfig();
383
-		$user_part = $config->getSystemValue('mail_from_address', $user_part);
384
-		$host_name = self::getServerHostName();
385
-		$host_name = $config->getSystemValue('mail_domain', $host_name);
386
-		$defaultEmailAddress = $user_part.'@'.$host_name;
387
-
388
-		$mailer = \OC::$server->getMailer();
389
-		if ($mailer->validateMailAddress($defaultEmailAddress)) {
390
-			return $defaultEmailAddress;
391
-		}
392
-
393
-		// in case we cannot build a valid email address from the hostname let's fallback to 'localhost.localdomain'
394
-		return $user_part.'@localhost.localdomain';
395
-	}
396
-
397
-	/**
398
-	 * Returns the server protocol. It respects reverse proxy servers and load balancers
399
-	 * @return string the server protocol
400
-	 * @deprecated 8.1.0 Use \OCP\IRequest::getServerProtocol
401
-	 * @since 4.5.0
402
-	 */
403
-	public static function getServerProtocol() {
404
-		return \OC::$server->getRequest()->getServerProtocol();
405
-	}
406
-
407
-	/**
408
-	 * Returns the request uri, even if the website uses one or more reverse proxies
409
-	 * @return string the request uri
410
-	 * @deprecated 8.1.0 Use \OCP\IRequest::getRequestUri
411
-	 * @since 5.0.0
412
-	 */
413
-	public static function getRequestUri() {
414
-		return \OC::$server->getRequest()->getRequestUri();
415
-	}
416
-
417
-	/**
418
-	 * Returns the script name, even if the website uses one or more reverse proxies
419
-	 * @return string the script name
420
-	 * @deprecated 8.1.0 Use \OCP\IRequest::getScriptName
421
-	 * @since 5.0.0
422
-	 */
423
-	public static function getScriptName() {
424
-		return \OC::$server->getRequest()->getScriptName();
425
-	}
426
-
427
-	/**
428
-	 * Creates path to an image
429
-	 * @param string $app app
430
-	 * @param string $image image name
431
-	 * @return string the url
432
-	 * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->imagePath($app, $image)
433
-	 * @since 4.0.0
434
-	 */
435
-	public static function imagePath( $app, $image ) {
436
-		return \OC::$server->getURLGenerator()->imagePath($app, $image);
437
-	}
438
-
439
-	/**
440
-	 * Make a human file size (2048 to 2 kB)
441
-	 * @param int $bytes file size in bytes
442
-	 * @return string a human readable file size
443
-	 * @since 4.0.0
444
-	 */
445
-	public static function humanFileSize( $bytes ) {
446
-		return(\OC_Helper::humanFileSize( $bytes ));
447
-	}
448
-
449
-	/**
450
-	 * Make a computer file size (2 kB to 2048)
451
-	 * @param string $str file size in a fancy format
452
-	 * @return int a file size in bytes
453
-	 *
454
-	 * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
455
-	 * @since 4.0.0
456
-	 */
457
-	public static function computerFileSize( $str ) {
458
-		return(\OC_Helper::computerFileSize( $str ));
459
-	}
460
-
461
-	/**
462
-	 * connects a function to a hook
463
-	 *
464
-	 * @param string $signalClass class name of emitter
465
-	 * @param string $signalName name of signal
466
-	 * @param string|object $slotClass class name of slot
467
-	 * @param string $slotName name of slot
468
-	 * @return bool
469
-	 *
470
-	 * This function makes it very easy to connect to use hooks.
471
-	 *
472
-	 * TODO: write example
473
-	 * @since 4.0.0
474
-	 */
475
-	static public function connectHook($signalClass, $signalName, $slotClass, $slotName ) {
476
-		return(\OC_Hook::connect($signalClass, $signalName, $slotClass, $slotName ));
477
-	}
478
-
479
-	/**
480
-	 * Emits a signal. To get data from the slot use references!
481
-	 * @param string $signalclass class name of emitter
482
-	 * @param string $signalname name of signal
483
-	 * @param array $params default: array() array with additional data
484
-	 * @return bool true if slots exists or false if not
485
-	 *
486
-	 * TODO: write example
487
-	 * @since 4.0.0
488
-	 */
489
-	static public function emitHook( $signalclass, $signalname, $params = array()) {
490
-		return(\OC_Hook::emit( $signalclass, $signalname, $params ));
491
-	}
492
-
493
-	/**
494
-	 * Cached encrypted CSRF token. Some static unit-tests of ownCloud compare
495
-	 * multiple OC_Template elements which invoke `callRegister`. If the value
496
-	 * would not be cached these unit-tests would fail.
497
-	 * @var string
498
-	 */
499
-	private static $token = '';
500
-
501
-	/**
502
-	 * Register an get/post call. This is important to prevent CSRF attacks
503
-	 * @since 4.5.0
504
-	 */
505
-	public static function callRegister() {
506
-		if(self::$token === '') {
507
-			self::$token = \OC::$server->getCsrfTokenManager()->getToken()->getEncryptedValue();
508
-		}
509
-		return self::$token;
510
-	}
511
-
512
-	/**
513
-	 * Check an ajax get/post call if the request token is valid. exit if not.
514
-	 * @since 4.5.0
515
-	 * @deprecated 9.0.0 Use annotations based on the app framework.
516
-	 */
517
-	public static function callCheck() {
518
-		if(!\OC::$server->getRequest()->passesStrictCookieCheck()) {
519
-			header('Location: '.\OC::$WEBROOT);
520
-			exit();
521
-		}
522
-
523
-		if (!(\OC::$server->getRequest()->passesCSRFCheck())) {
524
-			exit();
525
-		}
526
-	}
527
-
528
-	/**
529
-	 * Used to sanitize HTML
530
-	 *
531
-	 * This function is used to sanitize HTML and should be applied on any
532
-	 * string or array of strings before displaying it on a web page.
533
-	 *
534
-	 * @param string|array $value
535
-	 * @return string|array an array of sanitized strings or a single sanitized string, depends on the input parameter.
536
-	 * @since 4.5.0
537
-	 */
538
-	public static function sanitizeHTML($value) {
539
-		return \OC_Util::sanitizeHTML($value);
540
-	}
541
-
542
-	/**
543
-	 * Public function to encode url parameters
544
-	 *
545
-	 * This function is used to encode path to file before output.
546
-	 * Encoding is done according to RFC 3986 with one exception:
547
-	 * Character '/' is preserved as is.
548
-	 *
549
-	 * @param string $component part of URI to encode
550
-	 * @return string
551
-	 * @since 6.0.0
552
-	 */
553
-	public static function encodePath($component) {
554
-		return(\OC_Util::encodePath($component));
555
-	}
556
-
557
-	/**
558
-	 * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
559
-	 *
560
-	 * @param array $input The array to work on
561
-	 * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
562
-	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
563
-	 * @return array
564
-	 * @since 4.5.0
565
-	 */
566
-	public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
567
-		return(\OC_Helper::mb_array_change_key_case($input, $case, $encoding));
568
-	}
569
-
570
-	/**
571
-	 * replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement.
572
-	 *
573
-	 * @param string $string The input string. Opposite to the PHP build-in function does not accept an array.
574
-	 * @param string $replacement The replacement string.
575
-	 * @param int $start If start is positive, the replacing will begin at the start'th offset into string. If start is negative, the replacing will begin at the start'th character from the end of string.
576
-	 * @param int $length Length of the part to be replaced
577
-	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
578
-	 * @return string
579
-	 * @since 4.5.0
580
-	 * @deprecated 8.2.0 Use substr_replace() instead.
581
-	 */
582
-	public static function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = 'UTF-8') {
583
-		return substr_replace($string, $replacement, $start, $length);
584
-	}
585
-
586
-	/**
587
-	 * Replace all occurrences of the search string with the replacement string
588
-	 *
589
-	 * @param string $search The value being searched for, otherwise known as the needle. String.
590
-	 * @param string $replace The replacement string.
591
-	 * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack.
592
-	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
593
-	 * @param int $count If passed, this will be set to the number of replacements performed.
594
-	 * @return string
595
-	 * @since 4.5.0
596
-	 * @deprecated 8.2.0 Use str_replace() instead.
597
-	 */
598
-	public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) {
599
-		return str_replace($search, $replace, $subject, $count);
600
-	}
601
-
602
-	/**
603
-	 * performs a search in a nested array
604
-	 *
605
-	 * @param array $haystack the array to be searched
606
-	 * @param string $needle the search string
607
-	 * @param int $index optional, only search this key name
608
-	 * @return mixed the key of the matching field, otherwise false
609
-	 * @since 4.5.0
610
-	 */
611
-	public static function recursiveArraySearch($haystack, $needle, $index = null) {
612
-		return(\OC_Helper::recursiveArraySearch($haystack, $needle, $index));
613
-	}
614
-
615
-	/**
616
-	 * calculates the maximum upload size respecting system settings, free space and user quota
617
-	 *
618
-	 * @param string $dir the current folder where the user currently operates
619
-	 * @param int $free the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly
620
-	 * @return int number of bytes representing
621
-	 * @since 5.0.0
622
-	 */
623
-	public static function maxUploadFilesize($dir, $free = null) {
624
-		return \OC_Helper::maxUploadFilesize($dir, $free);
625
-	}
626
-
627
-	/**
628
-	 * Calculate free space left within user quota
629
-	 * @param string $dir the current folder where the user currently operates
630
-	 * @return int number of bytes representing
631
-	 * @since 7.0.0
632
-	 */
633
-	public static function freeSpace($dir) {
634
-		return \OC_Helper::freeSpace($dir);
635
-	}
636
-
637
-	/**
638
-	 * Calculate PHP upload limit
639
-	 *
640
-	 * @return int number of bytes representing
641
-	 * @since 7.0.0
642
-	 */
643
-	public static function uploadLimit() {
644
-		return \OC_Helper::uploadLimit();
645
-	}
646
-
647
-	/**
648
-	 * Returns whether the given file name is valid
649
-	 * @param string $file file name to check
650
-	 * @return bool true if the file name is valid, false otherwise
651
-	 * @deprecated 8.1.0 use \OC\Files\View::verifyPath()
652
-	 * @since 7.0.0
653
-	 */
654
-	public static function isValidFileName($file) {
655
-		return \OC_Util::isValidFileName($file);
656
-	}
657
-
658
-	/**
659
-	 * Generates a cryptographic secure pseudo-random string
660
-	 * @param int $length of the random string
661
-	 * @return string
662
-	 * @deprecated 8.0.0 Use \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate($length); instead
663
-	 * @since 7.0.0
664
-	 */
665
-	public static function generateRandomBytes($length = 30) {
666
-		return \OC::$server->getSecureRandom()->generate($length, \OCP\Security\ISecureRandom::CHAR_LOWER.\OCP\Security\ISecureRandom::CHAR_DIGITS);
667
-	}
668
-
669
-	/**
670
-	 * Compare two strings to provide a natural sort
671
-	 * @param string $a first string to compare
672
-	 * @param string $b second string to compare
673
-	 * @return -1 if $b comes before $a, 1 if $a comes before $b
674
-	 * or 0 if the strings are identical
675
-	 * @since 7.0.0
676
-	 */
677
-	public static function naturalSortCompare($a, $b) {
678
-		return \OC\NaturalSort::getInstance()->compare($a, $b);
679
-	}
680
-
681
-	/**
682
-	 * check if a password is required for each public link
683
-	 * @return boolean
684
-	 * @since 7.0.0
685
-	 */
686
-	public static function isPublicLinkPasswordRequired() {
687
-		return \OC_Util::isPublicLinkPasswordRequired();
688
-	}
689
-
690
-	/**
691
-	 * check if share API enforces a default expire date
692
-	 * @return boolean
693
-	 * @since 8.0.0
694
-	 */
695
-	public static function isDefaultExpireDateEnforced() {
696
-		return \OC_Util::isDefaultExpireDateEnforced();
697
-	}
698
-
699
-	protected static $needUpgradeCache = null;
700
-
701
-	/**
702
-	 * Checks whether the current version needs upgrade.
703
-	 *
704
-	 * @return bool true if upgrade is needed, false otherwise
705
-	 * @since 7.0.0
706
-	 */
707
-	public static function needUpgrade() {
708
-		if (!isset(self::$needUpgradeCache)) {
709
-			self::$needUpgradeCache=\OC_Util::needUpgrade(\OC::$server->getConfig());
710
-		}		
711
-		return self::$needUpgradeCache;
712
-	}
91
+    /**
92
+     * Get current update channel
93
+     * @return string
94
+     * @since 8.1.0
95
+     */
96
+    public static function getChannel() {
97
+        return \OC_Util::getChannel();
98
+    }
99
+
100
+    /**
101
+     * send an email
102
+     * @param string $toaddress
103
+     * @param string $toname
104
+     * @param string $subject
105
+     * @param string $mailtext
106
+     * @param string $fromaddress
107
+     * @param string $fromname
108
+     * @param int $html
109
+     * @param string $altbody
110
+     * @param string $ccaddress
111
+     * @param string $ccname
112
+     * @param string $bcc
113
+     * @deprecated 8.1.0 Use \OCP\Mail\IMailer instead
114
+     * @since 4.0.0
115
+     */
116
+    public static function sendMail($toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname,
117
+        $html = 0, $altbody = '', $ccaddress = '', $ccname = '', $bcc = '') {
118
+        $mailer = \OC::$server->getMailer();
119
+        $message = $mailer->createMessage();
120
+        $message->setTo([$toaddress => $toname]);
121
+        $message->setSubject($subject);
122
+        $message->setPlainBody($mailtext);
123
+        $message->setFrom([$fromaddress => $fromname]);
124
+        if($html === 1) {
125
+            $message->setHTMLBody($altbody);
126
+        }
127
+
128
+        if($altbody === '') {
129
+            $message->setHTMLBody($mailtext);
130
+            $message->setPlainBody('');
131
+        } else {
132
+            $message->setHtmlBody($mailtext);
133
+            $message->setPlainBody($altbody);
134
+        }
135
+
136
+        if(!empty($ccaddress)) {
137
+            if(!empty($ccname)) {
138
+                $message->setCc([$ccaddress => $ccname]);
139
+            } else {
140
+                $message->setCc([$ccaddress]);
141
+            }
142
+        }
143
+        if(!empty($bcc)) {
144
+            $message->setBcc([$bcc]);
145
+        }
146
+
147
+        $mailer->send($message);
148
+    }
149
+
150
+    /**
151
+     * write a message in the log
152
+     * @param string $app
153
+     * @param string $message
154
+     * @param int $level
155
+     * @since 4.0.0
156
+     */
157
+    public static function writeLog( $app, $message, $level ) {
158
+        $context = ['app' => $app];
159
+        \OC::$server->getLogger()->log($level, $message, $context);
160
+    }
161
+
162
+    /**
163
+     * write exception into the log
164
+     * @param string $app app name
165
+     * @param \Exception $ex exception to log
166
+     * @param int $level log level, defaults to \OCP\Util::FATAL
167
+     * @since ....0.0 - parameter $level was added in 7.0.0
168
+     * @deprecated 8.2.0 use logException of \OCP\ILogger
169
+     */
170
+    public static function logException( $app, \Exception $ex, $level = \OCP\Util::FATAL ) {
171
+        \OC::$server->getLogger()->logException($ex, ['app' => $app]);
172
+    }
173
+
174
+    /**
175
+     * check if sharing is disabled for the current user
176
+     *
177
+     * @return boolean
178
+     * @since 7.0.0
179
+     * @deprecated 9.1.0 Use \OC::$server->getShareManager()->sharingDisabledForUser
180
+     */
181
+    public static function isSharingDisabledForUser() {
182
+        if (self::$shareManager === null) {
183
+            self::$shareManager = \OC::$server->getShareManager();
184
+        }
185
+
186
+        $user = \OC::$server->getUserSession()->getUser();
187
+        if ($user !== null) {
188
+            $user = $user->getUID();
189
+        }
190
+
191
+        return self::$shareManager->sharingDisabledForUser($user);
192
+    }
193
+
194
+    /**
195
+     * get l10n object
196
+     * @param string $application
197
+     * @param string|null $language
198
+     * @return \OC_L10N
199
+     * @since 6.0.0 - parameter $language was added in 8.0.0
200
+     */
201
+    public static function getL10N($application, $language = null) {
202
+        return \OC::$server->getL10N($application, $language);
203
+    }
204
+
205
+    /**
206
+     * add a css file
207
+     * @param string $application
208
+     * @param string $file
209
+     * @since 4.0.0
210
+     */
211
+    public static function addStyle( $application, $file = null ) {
212
+        \OC_Util::addStyle( $application, $file );
213
+    }
214
+
215
+    /**
216
+     * add a javascript file
217
+     * @param string $application
218
+     * @param string $file
219
+     * @since 4.0.0
220
+     */
221
+    public static function addScript( $application, $file = null ) {
222
+        \OC_Util::addScript( $application, $file );
223
+    }
224
+
225
+    /**
226
+     * Add a translation JS file
227
+     * @param string $application application id
228
+     * @param string $languageCode language code, defaults to the current locale
229
+     * @since 8.0.0
230
+     */
231
+    public static function addTranslations($application, $languageCode = null) {
232
+        \OC_Util::addTranslations($application, $languageCode);
233
+    }
234
+
235
+    /**
236
+     * Add a custom element to the header
237
+     * If $text is null then the element will be written as empty element.
238
+     * So use "" to get a closing tag.
239
+     * @param string $tag tag name of the element
240
+     * @param array $attributes array of attributes for the element
241
+     * @param string $text the text content for the element
242
+     * @since 4.0.0
243
+     */
244
+    public static function addHeader($tag, $attributes, $text=null) {
245
+        \OC_Util::addHeader($tag, $attributes, $text);
246
+    }
247
+
248
+    /**
249
+     * formats a timestamp in the "right" way
250
+     * @param int $timestamp $timestamp
251
+     * @param bool $dateOnly option to omit time from the result
252
+     * @param DateTimeZone|string $timeZone where the given timestamp shall be converted to
253
+     * @return string timestamp
254
+     *
255
+     * @deprecated 8.0.0 Use \OC::$server->query('DateTimeFormatter') instead
256
+     * @since 4.0.0
257
+     */
258
+    public static function formatDate($timestamp, $dateOnly=false, $timeZone = null) {
259
+        return(\OC_Util::formatDate($timestamp, $dateOnly, $timeZone));
260
+    }
261
+
262
+    /**
263
+     * check if some encrypted files are stored
264
+     * @return bool
265
+     *
266
+     * @deprecated 8.1.0 No longer required
267
+     * @since 6.0.0
268
+     */
269
+    public static function encryptedFiles() {
270
+        return false;
271
+    }
272
+
273
+    /**
274
+     * Creates an absolute url to the given app and file.
275
+     * @param string $app app
276
+     * @param string $file file
277
+     * @param array $args array with param=>value, will be appended to the returned url
278
+     * 	The value of $args will be urlencoded
279
+     * @return string the url
280
+     * @since 4.0.0 - parameter $args was added in 4.5.0
281
+     */
282
+    public static function linkToAbsolute( $app, $file, $args = array() ) {
283
+        $urlGenerator = \OC::$server->getURLGenerator();
284
+        return $urlGenerator->getAbsoluteURL(
285
+            $urlGenerator->linkTo($app, $file, $args)
286
+        );
287
+    }
288
+
289
+    /**
290
+     * Creates an absolute url for remote use.
291
+     * @param string $service id
292
+     * @return string the url
293
+     * @since 4.0.0
294
+     */
295
+    public static function linkToRemote( $service ) {
296
+        $urlGenerator = \OC::$server->getURLGenerator();
297
+        $remoteBase = $urlGenerator->linkTo('', 'remote.php') . '/' . $service;
298
+        return $urlGenerator->getAbsoluteURL(
299
+            $remoteBase . (($service[strlen($service) - 1] != '/') ? '/' : '')
300
+        );
301
+    }
302
+
303
+    /**
304
+     * Creates an absolute url for public use
305
+     * @param string $service id
306
+     * @return string the url
307
+     * @since 4.5.0
308
+     */
309
+    public static function linkToPublic($service) {
310
+        return \OC_Helper::linkToPublic($service);
311
+    }
312
+
313
+    /**
314
+     * Creates an url using a defined route
315
+     * @param string $route
316
+     * @param array $parameters
317
+     * @internal param array $args with param=>value, will be appended to the returned url
318
+     * @return string the url
319
+     * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->linkToRoute($route, $parameters)
320
+     * @since 5.0.0
321
+     */
322
+    public static function linkToRoute( $route, $parameters = array() ) {
323
+        return \OC::$server->getURLGenerator()->linkToRoute($route, $parameters);
324
+    }
325
+
326
+    /**
327
+     * Creates an url to the given app and file
328
+     * @param string $app app
329
+     * @param string $file file
330
+     * @param array $args array with param=>value, will be appended to the returned url
331
+     * 	The value of $args will be urlencoded
332
+     * @return string the url
333
+     * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->linkTo($app, $file, $args)
334
+     * @since 4.0.0 - parameter $args was added in 4.5.0
335
+     */
336
+    public static function linkTo( $app, $file, $args = array() ) {
337
+        return \OC::$server->getURLGenerator()->linkTo($app, $file, $args);
338
+    }
339
+
340
+    /**
341
+     * Returns the server host, even if the website uses one or more reverse proxy
342
+     * @return string the server host
343
+     * @deprecated 8.1.0 Use \OCP\IRequest::getServerHost
344
+     * @since 4.0.0
345
+     */
346
+    public static function getServerHost() {
347
+        return \OC::$server->getRequest()->getServerHost();
348
+    }
349
+
350
+    /**
351
+     * Returns the server host name without an eventual port number
352
+     * @return string the server hostname
353
+     * @since 5.0.0
354
+     */
355
+    public static function getServerHostName() {
356
+        $host_name = self::getServerHost();
357
+        // strip away port number (if existing)
358
+        $colon_pos = strpos($host_name, ':');
359
+        if ($colon_pos != FALSE) {
360
+            $host_name = substr($host_name, 0, $colon_pos);
361
+        }
362
+        return $host_name;
363
+    }
364
+
365
+    /**
366
+     * Returns the default email address
367
+     * @param string $user_part the user part of the address
368
+     * @return string the default email address
369
+     *
370
+     * Assembles a default email address (using the server hostname
371
+     * and the given user part, and returns it
372
+     * Example: when given lostpassword-noreply as $user_part param,
373
+     *     and is currently accessed via http(s)://example.com/,
374
+     *     it would return '[email protected]'
375
+     *
376
+     * If the configuration value 'mail_from_address' is set in
377
+     * config.php, this value will override the $user_part that
378
+     * is passed to this function
379
+     * @since 5.0.0
380
+     */
381
+    public static function getDefaultEmailAddress($user_part) {
382
+        $config = \OC::$server->getConfig();
383
+        $user_part = $config->getSystemValue('mail_from_address', $user_part);
384
+        $host_name = self::getServerHostName();
385
+        $host_name = $config->getSystemValue('mail_domain', $host_name);
386
+        $defaultEmailAddress = $user_part.'@'.$host_name;
387
+
388
+        $mailer = \OC::$server->getMailer();
389
+        if ($mailer->validateMailAddress($defaultEmailAddress)) {
390
+            return $defaultEmailAddress;
391
+        }
392
+
393
+        // in case we cannot build a valid email address from the hostname let's fallback to 'localhost.localdomain'
394
+        return $user_part.'@localhost.localdomain';
395
+    }
396
+
397
+    /**
398
+     * Returns the server protocol. It respects reverse proxy servers and load balancers
399
+     * @return string the server protocol
400
+     * @deprecated 8.1.0 Use \OCP\IRequest::getServerProtocol
401
+     * @since 4.5.0
402
+     */
403
+    public static function getServerProtocol() {
404
+        return \OC::$server->getRequest()->getServerProtocol();
405
+    }
406
+
407
+    /**
408
+     * Returns the request uri, even if the website uses one or more reverse proxies
409
+     * @return string the request uri
410
+     * @deprecated 8.1.0 Use \OCP\IRequest::getRequestUri
411
+     * @since 5.0.0
412
+     */
413
+    public static function getRequestUri() {
414
+        return \OC::$server->getRequest()->getRequestUri();
415
+    }
416
+
417
+    /**
418
+     * Returns the script name, even if the website uses one or more reverse proxies
419
+     * @return string the script name
420
+     * @deprecated 8.1.0 Use \OCP\IRequest::getScriptName
421
+     * @since 5.0.0
422
+     */
423
+    public static function getScriptName() {
424
+        return \OC::$server->getRequest()->getScriptName();
425
+    }
426
+
427
+    /**
428
+     * Creates path to an image
429
+     * @param string $app app
430
+     * @param string $image image name
431
+     * @return string the url
432
+     * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->imagePath($app, $image)
433
+     * @since 4.0.0
434
+     */
435
+    public static function imagePath( $app, $image ) {
436
+        return \OC::$server->getURLGenerator()->imagePath($app, $image);
437
+    }
438
+
439
+    /**
440
+     * Make a human file size (2048 to 2 kB)
441
+     * @param int $bytes file size in bytes
442
+     * @return string a human readable file size
443
+     * @since 4.0.0
444
+     */
445
+    public static function humanFileSize( $bytes ) {
446
+        return(\OC_Helper::humanFileSize( $bytes ));
447
+    }
448
+
449
+    /**
450
+     * Make a computer file size (2 kB to 2048)
451
+     * @param string $str file size in a fancy format
452
+     * @return int a file size in bytes
453
+     *
454
+     * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
455
+     * @since 4.0.0
456
+     */
457
+    public static function computerFileSize( $str ) {
458
+        return(\OC_Helper::computerFileSize( $str ));
459
+    }
460
+
461
+    /**
462
+     * connects a function to a hook
463
+     *
464
+     * @param string $signalClass class name of emitter
465
+     * @param string $signalName name of signal
466
+     * @param string|object $slotClass class name of slot
467
+     * @param string $slotName name of slot
468
+     * @return bool
469
+     *
470
+     * This function makes it very easy to connect to use hooks.
471
+     *
472
+     * TODO: write example
473
+     * @since 4.0.0
474
+     */
475
+    static public function connectHook($signalClass, $signalName, $slotClass, $slotName ) {
476
+        return(\OC_Hook::connect($signalClass, $signalName, $slotClass, $slotName ));
477
+    }
478
+
479
+    /**
480
+     * Emits a signal. To get data from the slot use references!
481
+     * @param string $signalclass class name of emitter
482
+     * @param string $signalname name of signal
483
+     * @param array $params default: array() array with additional data
484
+     * @return bool true if slots exists or false if not
485
+     *
486
+     * TODO: write example
487
+     * @since 4.0.0
488
+     */
489
+    static public function emitHook( $signalclass, $signalname, $params = array()) {
490
+        return(\OC_Hook::emit( $signalclass, $signalname, $params ));
491
+    }
492
+
493
+    /**
494
+     * Cached encrypted CSRF token. Some static unit-tests of ownCloud compare
495
+     * multiple OC_Template elements which invoke `callRegister`. If the value
496
+     * would not be cached these unit-tests would fail.
497
+     * @var string
498
+     */
499
+    private static $token = '';
500
+
501
+    /**
502
+     * Register an get/post call. This is important to prevent CSRF attacks
503
+     * @since 4.5.0
504
+     */
505
+    public static function callRegister() {
506
+        if(self::$token === '') {
507
+            self::$token = \OC::$server->getCsrfTokenManager()->getToken()->getEncryptedValue();
508
+        }
509
+        return self::$token;
510
+    }
511
+
512
+    /**
513
+     * Check an ajax get/post call if the request token is valid. exit if not.
514
+     * @since 4.5.0
515
+     * @deprecated 9.0.0 Use annotations based on the app framework.
516
+     */
517
+    public static function callCheck() {
518
+        if(!\OC::$server->getRequest()->passesStrictCookieCheck()) {
519
+            header('Location: '.\OC::$WEBROOT);
520
+            exit();
521
+        }
522
+
523
+        if (!(\OC::$server->getRequest()->passesCSRFCheck())) {
524
+            exit();
525
+        }
526
+    }
527
+
528
+    /**
529
+     * Used to sanitize HTML
530
+     *
531
+     * This function is used to sanitize HTML and should be applied on any
532
+     * string or array of strings before displaying it on a web page.
533
+     *
534
+     * @param string|array $value
535
+     * @return string|array an array of sanitized strings or a single sanitized string, depends on the input parameter.
536
+     * @since 4.5.0
537
+     */
538
+    public static function sanitizeHTML($value) {
539
+        return \OC_Util::sanitizeHTML($value);
540
+    }
541
+
542
+    /**
543
+     * Public function to encode url parameters
544
+     *
545
+     * This function is used to encode path to file before output.
546
+     * Encoding is done according to RFC 3986 with one exception:
547
+     * Character '/' is preserved as is.
548
+     *
549
+     * @param string $component part of URI to encode
550
+     * @return string
551
+     * @since 6.0.0
552
+     */
553
+    public static function encodePath($component) {
554
+        return(\OC_Util::encodePath($component));
555
+    }
556
+
557
+    /**
558
+     * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
559
+     *
560
+     * @param array $input The array to work on
561
+     * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
562
+     * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
563
+     * @return array
564
+     * @since 4.5.0
565
+     */
566
+    public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
567
+        return(\OC_Helper::mb_array_change_key_case($input, $case, $encoding));
568
+    }
569
+
570
+    /**
571
+     * replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement.
572
+     *
573
+     * @param string $string The input string. Opposite to the PHP build-in function does not accept an array.
574
+     * @param string $replacement The replacement string.
575
+     * @param int $start If start is positive, the replacing will begin at the start'th offset into string. If start is negative, the replacing will begin at the start'th character from the end of string.
576
+     * @param int $length Length of the part to be replaced
577
+     * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
578
+     * @return string
579
+     * @since 4.5.0
580
+     * @deprecated 8.2.0 Use substr_replace() instead.
581
+     */
582
+    public static function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = 'UTF-8') {
583
+        return substr_replace($string, $replacement, $start, $length);
584
+    }
585
+
586
+    /**
587
+     * Replace all occurrences of the search string with the replacement string
588
+     *
589
+     * @param string $search The value being searched for, otherwise known as the needle. String.
590
+     * @param string $replace The replacement string.
591
+     * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack.
592
+     * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
593
+     * @param int $count If passed, this will be set to the number of replacements performed.
594
+     * @return string
595
+     * @since 4.5.0
596
+     * @deprecated 8.2.0 Use str_replace() instead.
597
+     */
598
+    public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) {
599
+        return str_replace($search, $replace, $subject, $count);
600
+    }
601
+
602
+    /**
603
+     * performs a search in a nested array
604
+     *
605
+     * @param array $haystack the array to be searched
606
+     * @param string $needle the search string
607
+     * @param int $index optional, only search this key name
608
+     * @return mixed the key of the matching field, otherwise false
609
+     * @since 4.5.0
610
+     */
611
+    public static function recursiveArraySearch($haystack, $needle, $index = null) {
612
+        return(\OC_Helper::recursiveArraySearch($haystack, $needle, $index));
613
+    }
614
+
615
+    /**
616
+     * calculates the maximum upload size respecting system settings, free space and user quota
617
+     *
618
+     * @param string $dir the current folder where the user currently operates
619
+     * @param int $free the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly
620
+     * @return int number of bytes representing
621
+     * @since 5.0.0
622
+     */
623
+    public static function maxUploadFilesize($dir, $free = null) {
624
+        return \OC_Helper::maxUploadFilesize($dir, $free);
625
+    }
626
+
627
+    /**
628
+     * Calculate free space left within user quota
629
+     * @param string $dir the current folder where the user currently operates
630
+     * @return int number of bytes representing
631
+     * @since 7.0.0
632
+     */
633
+    public static function freeSpace($dir) {
634
+        return \OC_Helper::freeSpace($dir);
635
+    }
636
+
637
+    /**
638
+     * Calculate PHP upload limit
639
+     *
640
+     * @return int number of bytes representing
641
+     * @since 7.0.0
642
+     */
643
+    public static function uploadLimit() {
644
+        return \OC_Helper::uploadLimit();
645
+    }
646
+
647
+    /**
648
+     * Returns whether the given file name is valid
649
+     * @param string $file file name to check
650
+     * @return bool true if the file name is valid, false otherwise
651
+     * @deprecated 8.1.0 use \OC\Files\View::verifyPath()
652
+     * @since 7.0.0
653
+     */
654
+    public static function isValidFileName($file) {
655
+        return \OC_Util::isValidFileName($file);
656
+    }
657
+
658
+    /**
659
+     * Generates a cryptographic secure pseudo-random string
660
+     * @param int $length of the random string
661
+     * @return string
662
+     * @deprecated 8.0.0 Use \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate($length); instead
663
+     * @since 7.0.0
664
+     */
665
+    public static function generateRandomBytes($length = 30) {
666
+        return \OC::$server->getSecureRandom()->generate($length, \OCP\Security\ISecureRandom::CHAR_LOWER.\OCP\Security\ISecureRandom::CHAR_DIGITS);
667
+    }
668
+
669
+    /**
670
+     * Compare two strings to provide a natural sort
671
+     * @param string $a first string to compare
672
+     * @param string $b second string to compare
673
+     * @return -1 if $b comes before $a, 1 if $a comes before $b
674
+     * or 0 if the strings are identical
675
+     * @since 7.0.0
676
+     */
677
+    public static function naturalSortCompare($a, $b) {
678
+        return \OC\NaturalSort::getInstance()->compare($a, $b);
679
+    }
680
+
681
+    /**
682
+     * check if a password is required for each public link
683
+     * @return boolean
684
+     * @since 7.0.0
685
+     */
686
+    public static function isPublicLinkPasswordRequired() {
687
+        return \OC_Util::isPublicLinkPasswordRequired();
688
+    }
689
+
690
+    /**
691
+     * check if share API enforces a default expire date
692
+     * @return boolean
693
+     * @since 8.0.0
694
+     */
695
+    public static function isDefaultExpireDateEnforced() {
696
+        return \OC_Util::isDefaultExpireDateEnforced();
697
+    }
698
+
699
+    protected static $needUpgradeCache = null;
700
+
701
+    /**
702
+     * Checks whether the current version needs upgrade.
703
+     *
704
+     * @return bool true if upgrade is needed, false otherwise
705
+     * @since 7.0.0
706
+     */
707
+    public static function needUpgrade() {
708
+        if (!isset(self::$needUpgradeCache)) {
709
+            self::$needUpgradeCache=\OC_Util::needUpgrade(\OC::$server->getConfig());
710
+        }		
711
+        return self::$needUpgradeCache;
712
+    }
713 713
 }
Please login to merge, or discard this patch.
settings/Controller/AppSettingsController.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -98,7 +98,7 @@
 block discarded – undo
98 98
 	}
99 99
 
100 100
 	/**
101
-	 * @param string|int $category
101
+	 * @param string $category
102 102
 	 * @return int
103 103
 	 */
104 104
 	protected function getCategory($category) {
Please login to merge, or discard this patch.
Indentation   +301 added lines, -301 removed lines patch added patch discarded remove patch
@@ -44,306 +44,306 @@
 block discarded – undo
44 44
  * @package OC\Settings\Controller
45 45
  */
46 46
 class AppSettingsController extends Controller {
47
-	const CAT_ENABLED = 0;
48
-	const CAT_DISABLED = 1;
49
-
50
-	/** @var \OCP\IL10N */
51
-	private $l10n;
52
-	/** @var IConfig */
53
-	private $config;
54
-	/** @var \OCP\ICache */
55
-	private $cache;
56
-	/** @var INavigationManager */
57
-	private $navigationManager;
58
-	/** @var IAppManager */
59
-	private $appManager;
60
-	/** @var OCSClient */
61
-	private $ocsClient;
62
-
63
-	/**
64
-	 * @param string $appName
65
-	 * @param IRequest $request
66
-	 * @param IL10N $l10n
67
-	 * @param IConfig $config
68
-	 * @param ICacheFactory $cache
69
-	 * @param INavigationManager $navigationManager
70
-	 * @param IAppManager $appManager
71
-	 * @param OCSClient $ocsClient
72
-	 */
73
-	public function __construct($appName,
74
-								IRequest $request,
75
-								IL10N $l10n,
76
-								IConfig $config,
77
-								ICacheFactory $cache,
78
-								INavigationManager $navigationManager,
79
-								IAppManager $appManager,
80
-								OCSClient $ocsClient) {
81
-		parent::__construct($appName, $request);
82
-		$this->l10n = $l10n;
83
-		$this->config = $config;
84
-		$this->cache = $cache->create($appName);
85
-		$this->navigationManager = $navigationManager;
86
-		$this->appManager = $appManager;
87
-		$this->ocsClient = $ocsClient;
88
-	}
89
-
90
-	/**
91
-	 * Enables or disables the display of experimental apps
92
-	 * @param bool $state
93
-	 * @return DataResponse
94
-	 */
95
-	public function changeExperimentalConfigState($state) {
96
-		$this->config->setSystemValue('appstore.experimental.enabled', $state);
97
-		$this->appManager->clearAppsCache();
98
-		return new DataResponse();
99
-	}
100
-
101
-	/**
102
-	 * @param string|int $category
103
-	 * @return int
104
-	 */
105
-	protected function getCategory($category) {
106
-		if (is_string($category)) {
107
-			foreach ($this->listCategories() as $cat) {
108
-				if (isset($cat['ident']) && $cat['ident'] === $category) {
109
-					$category = (int) $cat['id'];
110
-					break;
111
-				}
112
-			}
113
-
114
-			// Didn't find the category, falling back to enabled
115
-			if (is_string($category)) {
116
-				$category = self::CAT_ENABLED;
117
-			}
118
-		}
119
-		return (int) $category;
120
-	}
121
-
122
-	/**
123
-	 * @NoCSRFRequired
124
-	 * @param string $category
125
-	 * @return TemplateResponse
126
-	 */
127
-	public function viewApps($category = '') {
128
-		$categoryId = $this->getCategory($category);
129
-		if ($categoryId === self::CAT_ENABLED) {
130
-			// Do not use an arbitrary input string, because we put the category in html
131
-			$category = 'enabled';
132
-		}
133
-
134
-		$params = [];
135
-		$params['experimentalEnabled'] = $this->config->getSystemValue('appstore.experimental.enabled', false);
136
-		$params['category'] = $category;
137
-		$params['appstoreEnabled'] = $this->config->getSystemValue('appstoreenabled', true) === true;
138
-		$this->navigationManager->setActiveEntry('core_apps');
139
-
140
-		$templateResponse = new TemplateResponse($this->appName, 'apps', $params, 'user');
141
-		$policy = new ContentSecurityPolicy();
142
-		$policy->addAllowedImageDomain('https://apps.owncloud.com');
143
-		$templateResponse->setContentSecurityPolicy($policy);
144
-
145
-		return $templateResponse;
146
-	}
147
-
148
-	/**
149
-	 * Get all available categories
150
-	 * @return array
151
-	 */
152
-	public function listCategories() {
153
-
154
-		if(!is_null($this->cache->get('listCategories'))) {
155
-			return $this->cache->get('listCategories');
156
-		}
157
-		$categories = [
158
-			['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string)$this->l10n->t('Enabled')],
159
-			['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string)$this->l10n->t('Not enabled')],
160
-		];
161
-
162
-		if($this->ocsClient->isAppStoreEnabled()) {
163
-			// apps from external repo via OCS
164
-			$ocs = $this->ocsClient->getCategories(\OCP\Util::getVersion());
165
-			if ($ocs) {
166
-				foreach($ocs as $k => $v) {
167
-					$name = str_replace('ownCloud ', '', $v);
168
-					$ident = str_replace(' ', '-', urlencode(strtolower($name)));
169
-					$categories[] = [
170
-						'id' => $k,
171
-						'ident' => $ident,
172
-						'displayName' => $name,
173
-					];
174
-				}
175
-			}
176
-		}
177
-
178
-		$this->cache->set('listCategories', $categories, 3600);
179
-
180
-		return $categories;
181
-	}
182
-
183
-	/**
184
-	 * Get all available apps in a category
185
-	 *
186
-	 * @param string $category
187
-	 * @param bool $includeUpdateInfo Should we check whether there is an update
188
-	 *                                in the app store?
189
-	 * @return array
190
-	 */
191
-	public function listApps($category = '', $includeUpdateInfo = true) {
192
-		$category = $this->getCategory($category);
193
-		$cacheName = 'listApps-' . $category . '-' . (int) $includeUpdateInfo;
194
-
195
-		if(!is_null($this->cache->get($cacheName))) {
196
-			$apps = $this->cache->get($cacheName);
197
-		} else {
198
-			switch ($category) {
199
-				// installed apps
200
-				case 0:
201
-					$apps = $this->getInstalledApps($includeUpdateInfo);
202
-					usort($apps, function ($a, $b) {
203
-						$a = (string)$a['name'];
204
-						$b = (string)$b['name'];
205
-						if ($a === $b) {
206
-							return 0;
207
-						}
208
-						return ($a < $b) ? -1 : 1;
209
-					});
210
-					$version = \OCP\Util::getVersion();
211
-					foreach($apps as $key => $app) {
212
-						if(!array_key_exists('level', $app) && array_key_exists('ocsid', $app)) {
213
-							$remoteAppEntry = $this->ocsClient->getApplication($app['ocsid'], $version);
214
-
215
-							if(is_array($remoteAppEntry) && array_key_exists('level', $remoteAppEntry)) {
216
-								$apps[$key]['level'] = $remoteAppEntry['level'];
217
-							}
218
-						}
219
-					}
220
-					break;
221
-				// not-installed apps
222
-				case 1:
223
-					$apps = \OC_App::listAllApps(true, $includeUpdateInfo, $this->ocsClient);
224
-					$apps = array_filter($apps, function ($app) {
225
-						return !$app['active'];
226
-					});
227
-					$version = \OCP\Util::getVersion();
228
-					foreach($apps as $key => $app) {
229
-						if(!array_key_exists('level', $app) && array_key_exists('ocsid', $app)) {
230
-							$remoteAppEntry = $this->ocsClient->getApplication($app['ocsid'], $version);
231
-
232
-							if(is_array($remoteAppEntry) && array_key_exists('level', $remoteAppEntry)) {
233
-								$apps[$key]['level'] = $remoteAppEntry['level'];
234
-							}
235
-						}
236
-					}
237
-					usort($apps, function ($a, $b) {
238
-						$a = (string)$a['name'];
239
-						$b = (string)$b['name'];
240
-						if ($a === $b) {
241
-							return 0;
242
-						}
243
-						return ($a < $b) ? -1 : 1;
244
-					});
245
-					break;
246
-				default:
247
-					$filter = $this->config->getSystemValue('appstore.experimental.enabled', false) ? 'all' : 'approved';
248
-
249
-					$apps = \OC_App::getAppstoreApps($filter, $category, $this->ocsClient);
250
-					if (!$apps) {
251
-						$apps = array();
252
-					} else {
253
-						// don't list installed apps
254
-						$installedApps = $this->getInstalledApps(false);
255
-						$installedApps = array_map(function ($app) {
256
-							if (isset($app['ocsid'])) {
257
-								return $app['ocsid'];
258
-							}
259
-							return $app['id'];
260
-						}, $installedApps);
261
-						$apps = array_filter($apps, function ($app) use ($installedApps) {
262
-							return !in_array($app['id'], $installedApps);
263
-						});
264
-
265
-						// show tooltip if app is downloaded from remote server
266
-						$inactiveApps = $this->getInactiveApps();
267
-						foreach ($apps as &$app) {
268
-							$app['needsDownload'] = !in_array($app['id'], $inactiveApps);
269
-						}
270
-					}
271
-
272
-					// sort by score
273
-					usort($apps, function ($a, $b) {
274
-						$a = (int)$a['score'];
275
-						$b = (int)$b['score'];
276
-						if ($a === $b) {
277
-							return 0;
278
-						}
279
-						return ($a > $b) ? -1 : 1;
280
-					});
281
-					break;
282
-			}
283
-		}
284
-
285
-		// fix groups to be an array
286
-		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($this->config), $this->l10n);
287
-		$apps = array_map(function($app) use ($dependencyAnalyzer) {
288
-
289
-			// fix groups
290
-			$groups = array();
291
-			if (is_string($app['groups'])) {
292
-				$groups = json_decode($app['groups']);
293
-			}
294
-			$app['groups'] = $groups;
295
-			$app['canUnInstall'] = !$app['active'] && $app['removable'];
296
-
297
-			// fix licence vs license
298
-			if (isset($app['license']) && !isset($app['licence'])) {
299
-				$app['licence'] = $app['license'];
300
-			}
301
-
302
-			// analyse dependencies
303
-			$missing = $dependencyAnalyzer->analyze($app);
304
-			$app['canInstall'] = empty($missing);
305
-			$app['missingDependencies'] = $missing;
306
-
307
-			$app['missingMinOwnCloudVersion'] = !isset($app['dependencies']['owncloud']['@attributes']['min-version']);
308
-			$app['missingMaxOwnCloudVersion'] = !isset($app['dependencies']['owncloud']['@attributes']['max-version']);
309
-
310
-			return $app;
311
-		}, $apps);
312
-
313
-		$this->cache->set($cacheName, $apps, 300);
314
-
315
-		return ['apps' => $apps, 'status' => 'success'];
316
-	}
317
-
318
-	/**
319
-	 * @param bool $includeUpdateInfo Should we check whether there is an update
320
-	 *                                in the app store?
321
-	 * @return array
322
-	 */
323
-	private function getInstalledApps($includeUpdateInfo = true) {
324
-		$apps = \OC_App::listAllApps(true, $includeUpdateInfo, $this->ocsClient);
325
-		$apps = array_filter($apps, function ($app) {
326
-			return $app['active'];
327
-		});
328
-		return $apps;
329
-	}
330
-
331
-	/**
332
-	 * @return array
333
-	 */
334
-	private function getInactiveApps() {
335
-		$inactiveApps = \OC_App::listAllApps(true, false, $this->ocsClient);
336
-		$inactiveApps = array_filter($inactiveApps,
337
-			function ($app) {
338
-			return !$app['active'];
339
-		});
340
-		$inactiveApps = array_map(function($app) {
341
-			if (isset($app['ocsid'])) {
342
-				return $app['ocsid'];
343
-			}
344
-			return $app['id'];
345
-		}, $inactiveApps);
346
-		return $inactiveApps;
347
-	}
47
+    const CAT_ENABLED = 0;
48
+    const CAT_DISABLED = 1;
49
+
50
+    /** @var \OCP\IL10N */
51
+    private $l10n;
52
+    /** @var IConfig */
53
+    private $config;
54
+    /** @var \OCP\ICache */
55
+    private $cache;
56
+    /** @var INavigationManager */
57
+    private $navigationManager;
58
+    /** @var IAppManager */
59
+    private $appManager;
60
+    /** @var OCSClient */
61
+    private $ocsClient;
62
+
63
+    /**
64
+     * @param string $appName
65
+     * @param IRequest $request
66
+     * @param IL10N $l10n
67
+     * @param IConfig $config
68
+     * @param ICacheFactory $cache
69
+     * @param INavigationManager $navigationManager
70
+     * @param IAppManager $appManager
71
+     * @param OCSClient $ocsClient
72
+     */
73
+    public function __construct($appName,
74
+                                IRequest $request,
75
+                                IL10N $l10n,
76
+                                IConfig $config,
77
+                                ICacheFactory $cache,
78
+                                INavigationManager $navigationManager,
79
+                                IAppManager $appManager,
80
+                                OCSClient $ocsClient) {
81
+        parent::__construct($appName, $request);
82
+        $this->l10n = $l10n;
83
+        $this->config = $config;
84
+        $this->cache = $cache->create($appName);
85
+        $this->navigationManager = $navigationManager;
86
+        $this->appManager = $appManager;
87
+        $this->ocsClient = $ocsClient;
88
+    }
89
+
90
+    /**
91
+     * Enables or disables the display of experimental apps
92
+     * @param bool $state
93
+     * @return DataResponse
94
+     */
95
+    public function changeExperimentalConfigState($state) {
96
+        $this->config->setSystemValue('appstore.experimental.enabled', $state);
97
+        $this->appManager->clearAppsCache();
98
+        return new DataResponse();
99
+    }
100
+
101
+    /**
102
+     * @param string|int $category
103
+     * @return int
104
+     */
105
+    protected function getCategory($category) {
106
+        if (is_string($category)) {
107
+            foreach ($this->listCategories() as $cat) {
108
+                if (isset($cat['ident']) && $cat['ident'] === $category) {
109
+                    $category = (int) $cat['id'];
110
+                    break;
111
+                }
112
+            }
113
+
114
+            // Didn't find the category, falling back to enabled
115
+            if (is_string($category)) {
116
+                $category = self::CAT_ENABLED;
117
+            }
118
+        }
119
+        return (int) $category;
120
+    }
121
+
122
+    /**
123
+     * @NoCSRFRequired
124
+     * @param string $category
125
+     * @return TemplateResponse
126
+     */
127
+    public function viewApps($category = '') {
128
+        $categoryId = $this->getCategory($category);
129
+        if ($categoryId === self::CAT_ENABLED) {
130
+            // Do not use an arbitrary input string, because we put the category in html
131
+            $category = 'enabled';
132
+        }
133
+
134
+        $params = [];
135
+        $params['experimentalEnabled'] = $this->config->getSystemValue('appstore.experimental.enabled', false);
136
+        $params['category'] = $category;
137
+        $params['appstoreEnabled'] = $this->config->getSystemValue('appstoreenabled', true) === true;
138
+        $this->navigationManager->setActiveEntry('core_apps');
139
+
140
+        $templateResponse = new TemplateResponse($this->appName, 'apps', $params, 'user');
141
+        $policy = new ContentSecurityPolicy();
142
+        $policy->addAllowedImageDomain('https://apps.owncloud.com');
143
+        $templateResponse->setContentSecurityPolicy($policy);
144
+
145
+        return $templateResponse;
146
+    }
147
+
148
+    /**
149
+     * Get all available categories
150
+     * @return array
151
+     */
152
+    public function listCategories() {
153
+
154
+        if(!is_null($this->cache->get('listCategories'))) {
155
+            return $this->cache->get('listCategories');
156
+        }
157
+        $categories = [
158
+            ['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string)$this->l10n->t('Enabled')],
159
+            ['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string)$this->l10n->t('Not enabled')],
160
+        ];
161
+
162
+        if($this->ocsClient->isAppStoreEnabled()) {
163
+            // apps from external repo via OCS
164
+            $ocs = $this->ocsClient->getCategories(\OCP\Util::getVersion());
165
+            if ($ocs) {
166
+                foreach($ocs as $k => $v) {
167
+                    $name = str_replace('ownCloud ', '', $v);
168
+                    $ident = str_replace(' ', '-', urlencode(strtolower($name)));
169
+                    $categories[] = [
170
+                        'id' => $k,
171
+                        'ident' => $ident,
172
+                        'displayName' => $name,
173
+                    ];
174
+                }
175
+            }
176
+        }
177
+
178
+        $this->cache->set('listCategories', $categories, 3600);
179
+
180
+        return $categories;
181
+    }
182
+
183
+    /**
184
+     * Get all available apps in a category
185
+     *
186
+     * @param string $category
187
+     * @param bool $includeUpdateInfo Should we check whether there is an update
188
+     *                                in the app store?
189
+     * @return array
190
+     */
191
+    public function listApps($category = '', $includeUpdateInfo = true) {
192
+        $category = $this->getCategory($category);
193
+        $cacheName = 'listApps-' . $category . '-' . (int) $includeUpdateInfo;
194
+
195
+        if(!is_null($this->cache->get($cacheName))) {
196
+            $apps = $this->cache->get($cacheName);
197
+        } else {
198
+            switch ($category) {
199
+                // installed apps
200
+                case 0:
201
+                    $apps = $this->getInstalledApps($includeUpdateInfo);
202
+                    usort($apps, function ($a, $b) {
203
+                        $a = (string)$a['name'];
204
+                        $b = (string)$b['name'];
205
+                        if ($a === $b) {
206
+                            return 0;
207
+                        }
208
+                        return ($a < $b) ? -1 : 1;
209
+                    });
210
+                    $version = \OCP\Util::getVersion();
211
+                    foreach($apps as $key => $app) {
212
+                        if(!array_key_exists('level', $app) && array_key_exists('ocsid', $app)) {
213
+                            $remoteAppEntry = $this->ocsClient->getApplication($app['ocsid'], $version);
214
+
215
+                            if(is_array($remoteAppEntry) && array_key_exists('level', $remoteAppEntry)) {
216
+                                $apps[$key]['level'] = $remoteAppEntry['level'];
217
+                            }
218
+                        }
219
+                    }
220
+                    break;
221
+                // not-installed apps
222
+                case 1:
223
+                    $apps = \OC_App::listAllApps(true, $includeUpdateInfo, $this->ocsClient);
224
+                    $apps = array_filter($apps, function ($app) {
225
+                        return !$app['active'];
226
+                    });
227
+                    $version = \OCP\Util::getVersion();
228
+                    foreach($apps as $key => $app) {
229
+                        if(!array_key_exists('level', $app) && array_key_exists('ocsid', $app)) {
230
+                            $remoteAppEntry = $this->ocsClient->getApplication($app['ocsid'], $version);
231
+
232
+                            if(is_array($remoteAppEntry) && array_key_exists('level', $remoteAppEntry)) {
233
+                                $apps[$key]['level'] = $remoteAppEntry['level'];
234
+                            }
235
+                        }
236
+                    }
237
+                    usort($apps, function ($a, $b) {
238
+                        $a = (string)$a['name'];
239
+                        $b = (string)$b['name'];
240
+                        if ($a === $b) {
241
+                            return 0;
242
+                        }
243
+                        return ($a < $b) ? -1 : 1;
244
+                    });
245
+                    break;
246
+                default:
247
+                    $filter = $this->config->getSystemValue('appstore.experimental.enabled', false) ? 'all' : 'approved';
248
+
249
+                    $apps = \OC_App::getAppstoreApps($filter, $category, $this->ocsClient);
250
+                    if (!$apps) {
251
+                        $apps = array();
252
+                    } else {
253
+                        // don't list installed apps
254
+                        $installedApps = $this->getInstalledApps(false);
255
+                        $installedApps = array_map(function ($app) {
256
+                            if (isset($app['ocsid'])) {
257
+                                return $app['ocsid'];
258
+                            }
259
+                            return $app['id'];
260
+                        }, $installedApps);
261
+                        $apps = array_filter($apps, function ($app) use ($installedApps) {
262
+                            return !in_array($app['id'], $installedApps);
263
+                        });
264
+
265
+                        // show tooltip if app is downloaded from remote server
266
+                        $inactiveApps = $this->getInactiveApps();
267
+                        foreach ($apps as &$app) {
268
+                            $app['needsDownload'] = !in_array($app['id'], $inactiveApps);
269
+                        }
270
+                    }
271
+
272
+                    // sort by score
273
+                    usort($apps, function ($a, $b) {
274
+                        $a = (int)$a['score'];
275
+                        $b = (int)$b['score'];
276
+                        if ($a === $b) {
277
+                            return 0;
278
+                        }
279
+                        return ($a > $b) ? -1 : 1;
280
+                    });
281
+                    break;
282
+            }
283
+        }
284
+
285
+        // fix groups to be an array
286
+        $dependencyAnalyzer = new DependencyAnalyzer(new Platform($this->config), $this->l10n);
287
+        $apps = array_map(function($app) use ($dependencyAnalyzer) {
288
+
289
+            // fix groups
290
+            $groups = array();
291
+            if (is_string($app['groups'])) {
292
+                $groups = json_decode($app['groups']);
293
+            }
294
+            $app['groups'] = $groups;
295
+            $app['canUnInstall'] = !$app['active'] && $app['removable'];
296
+
297
+            // fix licence vs license
298
+            if (isset($app['license']) && !isset($app['licence'])) {
299
+                $app['licence'] = $app['license'];
300
+            }
301
+
302
+            // analyse dependencies
303
+            $missing = $dependencyAnalyzer->analyze($app);
304
+            $app['canInstall'] = empty($missing);
305
+            $app['missingDependencies'] = $missing;
306
+
307
+            $app['missingMinOwnCloudVersion'] = !isset($app['dependencies']['owncloud']['@attributes']['min-version']);
308
+            $app['missingMaxOwnCloudVersion'] = !isset($app['dependencies']['owncloud']['@attributes']['max-version']);
309
+
310
+            return $app;
311
+        }, $apps);
312
+
313
+        $this->cache->set($cacheName, $apps, 300);
314
+
315
+        return ['apps' => $apps, 'status' => 'success'];
316
+    }
317
+
318
+    /**
319
+     * @param bool $includeUpdateInfo Should we check whether there is an update
320
+     *                                in the app store?
321
+     * @return array
322
+     */
323
+    private function getInstalledApps($includeUpdateInfo = true) {
324
+        $apps = \OC_App::listAllApps(true, $includeUpdateInfo, $this->ocsClient);
325
+        $apps = array_filter($apps, function ($app) {
326
+            return $app['active'];
327
+        });
328
+        return $apps;
329
+    }
330
+
331
+    /**
332
+     * @return array
333
+     */
334
+    private function getInactiveApps() {
335
+        $inactiveApps = \OC_App::listAllApps(true, false, $this->ocsClient);
336
+        $inactiveApps = array_filter($inactiveApps,
337
+            function ($app) {
338
+            return !$app['active'];
339
+        });
340
+        $inactiveApps = array_map(function($app) {
341
+            if (isset($app['ocsid'])) {
342
+                return $app['ocsid'];
343
+            }
344
+            return $app['id'];
345
+        }, $inactiveApps);
346
+        return $inactiveApps;
347
+    }
348 348
 
349 349
 }
Please login to merge, or discard this patch.
Spacing   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -151,19 +151,19 @@  discard block
 block discarded – undo
151 151
 	 */
152 152
 	public function listCategories() {
153 153
 
154
-		if(!is_null($this->cache->get('listCategories'))) {
154
+		if (!is_null($this->cache->get('listCategories'))) {
155 155
 			return $this->cache->get('listCategories');
156 156
 		}
157 157
 		$categories = [
158
-			['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string)$this->l10n->t('Enabled')],
159
-			['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string)$this->l10n->t('Not enabled')],
158
+			['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string) $this->l10n->t('Enabled')],
159
+			['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string) $this->l10n->t('Not enabled')],
160 160
 		];
161 161
 
162
-		if($this->ocsClient->isAppStoreEnabled()) {
162
+		if ($this->ocsClient->isAppStoreEnabled()) {
163 163
 			// apps from external repo via OCS
164 164
 			$ocs = $this->ocsClient->getCategories(\OCP\Util::getVersion());
165 165
 			if ($ocs) {
166
-				foreach($ocs as $k => $v) {
166
+				foreach ($ocs as $k => $v) {
167 167
 					$name = str_replace('ownCloud ', '', $v);
168 168
 					$ident = str_replace(' ', '-', urlencode(strtolower($name)));
169 169
 					$categories[] = [
@@ -190,29 +190,29 @@  discard block
 block discarded – undo
190 190
 	 */
191 191
 	public function listApps($category = '', $includeUpdateInfo = true) {
192 192
 		$category = $this->getCategory($category);
193
-		$cacheName = 'listApps-' . $category . '-' . (int) $includeUpdateInfo;
193
+		$cacheName = 'listApps-'.$category.'-'.(int) $includeUpdateInfo;
194 194
 
195
-		if(!is_null($this->cache->get($cacheName))) {
195
+		if (!is_null($this->cache->get($cacheName))) {
196 196
 			$apps = $this->cache->get($cacheName);
197 197
 		} else {
198 198
 			switch ($category) {
199 199
 				// installed apps
200 200
 				case 0:
201 201
 					$apps = $this->getInstalledApps($includeUpdateInfo);
202
-					usort($apps, function ($a, $b) {
203
-						$a = (string)$a['name'];
204
-						$b = (string)$b['name'];
202
+					usort($apps, function($a, $b) {
203
+						$a = (string) $a['name'];
204
+						$b = (string) $b['name'];
205 205
 						if ($a === $b) {
206 206
 							return 0;
207 207
 						}
208 208
 						return ($a < $b) ? -1 : 1;
209 209
 					});
210 210
 					$version = \OCP\Util::getVersion();
211
-					foreach($apps as $key => $app) {
212
-						if(!array_key_exists('level', $app) && array_key_exists('ocsid', $app)) {
211
+					foreach ($apps as $key => $app) {
212
+						if (!array_key_exists('level', $app) && array_key_exists('ocsid', $app)) {
213 213
 							$remoteAppEntry = $this->ocsClient->getApplication($app['ocsid'], $version);
214 214
 
215
-							if(is_array($remoteAppEntry) && array_key_exists('level', $remoteAppEntry)) {
215
+							if (is_array($remoteAppEntry) && array_key_exists('level', $remoteAppEntry)) {
216 216
 								$apps[$key]['level'] = $remoteAppEntry['level'];
217 217
 							}
218 218
 						}
@@ -221,22 +221,22 @@  discard block
 block discarded – undo
221 221
 				// not-installed apps
222 222
 				case 1:
223 223
 					$apps = \OC_App::listAllApps(true, $includeUpdateInfo, $this->ocsClient);
224
-					$apps = array_filter($apps, function ($app) {
224
+					$apps = array_filter($apps, function($app) {
225 225
 						return !$app['active'];
226 226
 					});
227 227
 					$version = \OCP\Util::getVersion();
228
-					foreach($apps as $key => $app) {
229
-						if(!array_key_exists('level', $app) && array_key_exists('ocsid', $app)) {
228
+					foreach ($apps as $key => $app) {
229
+						if (!array_key_exists('level', $app) && array_key_exists('ocsid', $app)) {
230 230
 							$remoteAppEntry = $this->ocsClient->getApplication($app['ocsid'], $version);
231 231
 
232
-							if(is_array($remoteAppEntry) && array_key_exists('level', $remoteAppEntry)) {
232
+							if (is_array($remoteAppEntry) && array_key_exists('level', $remoteAppEntry)) {
233 233
 								$apps[$key]['level'] = $remoteAppEntry['level'];
234 234
 							}
235 235
 						}
236 236
 					}
237
-					usort($apps, function ($a, $b) {
238
-						$a = (string)$a['name'];
239
-						$b = (string)$b['name'];
237
+					usort($apps, function($a, $b) {
238
+						$a = (string) $a['name'];
239
+						$b = (string) $b['name'];
240 240
 						if ($a === $b) {
241 241
 							return 0;
242 242
 						}
@@ -252,13 +252,13 @@  discard block
 block discarded – undo
252 252
 					} else {
253 253
 						// don't list installed apps
254 254
 						$installedApps = $this->getInstalledApps(false);
255
-						$installedApps = array_map(function ($app) {
255
+						$installedApps = array_map(function($app) {
256 256
 							if (isset($app['ocsid'])) {
257 257
 								return $app['ocsid'];
258 258
 							}
259 259
 							return $app['id'];
260 260
 						}, $installedApps);
261
-						$apps = array_filter($apps, function ($app) use ($installedApps) {
261
+						$apps = array_filter($apps, function($app) use ($installedApps) {
262 262
 							return !in_array($app['id'], $installedApps);
263 263
 						});
264 264
 
@@ -270,9 +270,9 @@  discard block
 block discarded – undo
270 270
 					}
271 271
 
272 272
 					// sort by score
273
-					usort($apps, function ($a, $b) {
274
-						$a = (int)$a['score'];
275
-						$b = (int)$b['score'];
273
+					usort($apps, function($a, $b) {
274
+						$a = (int) $a['score'];
275
+						$b = (int) $b['score'];
276 276
 						if ($a === $b) {
277 277
 							return 0;
278 278
 						}
@@ -322,7 +322,7 @@  discard block
 block discarded – undo
322 322
 	 */
323 323
 	private function getInstalledApps($includeUpdateInfo = true) {
324 324
 		$apps = \OC_App::listAllApps(true, $includeUpdateInfo, $this->ocsClient);
325
-		$apps = array_filter($apps, function ($app) {
325
+		$apps = array_filter($apps, function($app) {
326 326
 			return $app['active'];
327 327
 		});
328 328
 		return $apps;
@@ -334,7 +334,7 @@  discard block
 block discarded – undo
334 334
 	private function getInactiveApps() {
335 335
 		$inactiveApps = \OC_App::listAllApps(true, false, $this->ocsClient);
336 336
 		$inactiveApps = array_filter($inactiveApps,
337
-			function ($app) {
337
+			function($app) {
338 338
 			return !$app['active'];
339 339
 		});
340 340
 		$inactiveApps = array_map(function($app) {
Please login to merge, or discard this patch.
settings/Controller/CertificateController.php 2 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
 	 *
72 72
 	 * @NoAdminRequired
73 73
 	 * @NoSubadminRequired
74
-	 * @return array
74
+	 * @return DataResponse
75 75
 	 */
76 76
 	public function addPersonalRootCertificate() {
77 77
 		return $this->addCertificate($this->userCertificateManager);
@@ -81,7 +81,7 @@  discard block
 block discarded – undo
81 81
 	 * Add a new root certificate to a trust store
82 82
 	 *
83 83
 	 * @param ICertificateManager $certificateManager
84
-	 * @return array
84
+	 * @return DataResponse
85 85
 	 */
86 86
 	private function addCertificate(ICertificateManager $certificateManager) {
87 87
 		$headers = [];
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
 	/**
160 160
 	 * Add a new personal root certificate to the system's trust store
161 161
 	 *
162
-	 * @return array
162
+	 * @return DataResponse
163 163
 	 */
164 164
 	public function addSystemRootCertificate() {
165 165
 		return $this->addCertificate($this->systemCertificateManager);
Please login to merge, or discard this patch.
Indentation   +144 added lines, -144 removed lines patch added patch discarded remove patch
@@ -37,148 +37,148 @@
 block discarded – undo
37 37
  * @package OC\Settings\Controller
38 38
  */
39 39
 class CertificateController extends Controller {
40
-	/** @var ICertificateManager */
41
-	private $userCertificateManager;
42
-	/** @var ICertificateManager  */
43
-	private $systemCertificateManager;
44
-	/** @var IL10N */
45
-	private $l10n;
46
-	/** @var IAppManager */
47
-	private $appManager;
48
-
49
-	/**
50
-	 * @param string $appName
51
-	 * @param IRequest $request
52
-	 * @param ICertificateManager $userCertificateManager
53
-	 * @param ICertificateManager $systemCertificateManager
54
-	 * @param IL10N $l10n
55
-	 * @param IAppManager $appManager
56
-	 */
57
-	public function __construct($appName,
58
-								IRequest $request,
59
-								ICertificateManager $userCertificateManager,
60
-								ICertificateManager $systemCertificateManager,
61
-								IL10N $l10n,
62
-								IAppManager $appManager) {
63
-		parent::__construct($appName, $request);
64
-		$this->userCertificateManager = $userCertificateManager;
65
-		$this->systemCertificateManager = $systemCertificateManager;
66
-		$this->l10n = $l10n;
67
-		$this->appManager = $appManager;
68
-	}
69
-
70
-	/**
71
-	 * Add a new personal root certificate to the users' trust store
72
-	 *
73
-	 * @NoAdminRequired
74
-	 * @NoSubadminRequired
75
-	 * @return array
76
-	 */
77
-	public function addPersonalRootCertificate() {
78
-		return $this->addCertificate($this->userCertificateManager);
79
-	}
80
-
81
-	/**
82
-	 * Add a new root certificate to a trust store
83
-	 *
84
-	 * @param ICertificateManager $certificateManager
85
-	 * @return array
86
-	 */
87
-	private function addCertificate(ICertificateManager $certificateManager) {
88
-		$headers = [];
89
-		if ($this->request->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE_8])) {
90
-			// due to upload iframe workaround, need to set content-type to text/plain
91
-			$headers['Content-Type'] = 'text/plain';
92
-		}
93
-
94
-		if ($this->isCertificateImportAllowed() === false) {
95
-			return new DataResponse(['message' => 'Individual certificate management disabled'], Http::STATUS_FORBIDDEN, $headers);
96
-		}
97
-
98
-		$file = $this->request->getUploadedFile('rootcert_import');
99
-		if (empty($file)) {
100
-			return new DataResponse(['message' => 'No file uploaded'], Http::STATUS_UNPROCESSABLE_ENTITY, $headers);
101
-		}
102
-
103
-		try {
104
-			$certificate = $certificateManager->addCertificate(file_get_contents($file['tmp_name']), $file['name']);
105
-			return new DataResponse(
106
-				[
107
-					'name' => $certificate->getName(),
108
-					'commonName' => $certificate->getCommonName(),
109
-					'organization' => $certificate->getOrganization(),
110
-					'validFrom' => $certificate->getIssueDate()->getTimestamp(),
111
-					'validTill' => $certificate->getExpireDate()->getTimestamp(),
112
-					'validFromString' => $this->l10n->l('date', $certificate->getIssueDate()),
113
-					'validTillString' => $this->l10n->l('date', $certificate->getExpireDate()),
114
-					'issuer' => $certificate->getIssuerName(),
115
-					'issuerOrganization' => $certificate->getIssuerOrganization(),
116
-				],
117
-				Http::STATUS_OK,
118
-				$headers
119
-			);
120
-		} catch (\Exception $e) {
121
-			return new DataResponse('An error occurred.', Http::STATUS_UNPROCESSABLE_ENTITY, $headers);
122
-		}
123
-	}
124
-
125
-	/**
126
-	 * Removes a personal root certificate from the users' trust store
127
-	 *
128
-	 * @NoAdminRequired
129
-	 * @NoSubadminRequired
130
-	 * @param string $certificateIdentifier
131
-	 * @return DataResponse
132
-	 */
133
-	public function removePersonalRootCertificate($certificateIdentifier) {
134
-
135
-		if ($this->isCertificateImportAllowed() === false) {
136
-			return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
137
-		}
138
-
139
-		$this->userCertificateManager->removeCertificate($certificateIdentifier);
140
-		return new DataResponse();
141
-	}
142
-
143
-	/**
144
-	 * check if certificate import is allowed
145
-	 *
146
-	 * @return bool
147
-	 */
148
-	protected function isCertificateImportAllowed() {
149
-		$externalStorageEnabled = $this->appManager->isEnabledForUser('files_external');
150
-		if ($externalStorageEnabled) {
151
-			/** @var \OCA\Files_External\Service\BackendService $backendService */
152
-			$backendService = \OC_Mount_Config::$app->getContainer()->query('\OCA\Files_External\Service\BackendService');
153
-			if ($backendService->isUserMountingAllowed()) {
154
-				return true;
155
-			}
156
-		}
157
-		return false;
158
-	}
159
-
160
-	/**
161
-	 * Add a new personal root certificate to the system's trust store
162
-	 *
163
-	 * @return array
164
-	 */
165
-	public function addSystemRootCertificate() {
166
-		return $this->addCertificate($this->systemCertificateManager);
167
-	}
168
-
169
-	/**
170
-	 * Removes a personal root certificate from the users' trust store
171
-	 *
172
-	 * @param string $certificateIdentifier
173
-	 * @return DataResponse
174
-	 */
175
-	public function removeSystemRootCertificate($certificateIdentifier) {
176
-
177
-		if ($this->isCertificateImportAllowed() === false) {
178
-			return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
179
-		}
180
-
181
-		$this->systemCertificateManager->removeCertificate($certificateIdentifier);
182
-		return new DataResponse();
183
-	}
40
+    /** @var ICertificateManager */
41
+    private $userCertificateManager;
42
+    /** @var ICertificateManager  */
43
+    private $systemCertificateManager;
44
+    /** @var IL10N */
45
+    private $l10n;
46
+    /** @var IAppManager */
47
+    private $appManager;
48
+
49
+    /**
50
+     * @param string $appName
51
+     * @param IRequest $request
52
+     * @param ICertificateManager $userCertificateManager
53
+     * @param ICertificateManager $systemCertificateManager
54
+     * @param IL10N $l10n
55
+     * @param IAppManager $appManager
56
+     */
57
+    public function __construct($appName,
58
+                                IRequest $request,
59
+                                ICertificateManager $userCertificateManager,
60
+                                ICertificateManager $systemCertificateManager,
61
+                                IL10N $l10n,
62
+                                IAppManager $appManager) {
63
+        parent::__construct($appName, $request);
64
+        $this->userCertificateManager = $userCertificateManager;
65
+        $this->systemCertificateManager = $systemCertificateManager;
66
+        $this->l10n = $l10n;
67
+        $this->appManager = $appManager;
68
+    }
69
+
70
+    /**
71
+     * Add a new personal root certificate to the users' trust store
72
+     *
73
+     * @NoAdminRequired
74
+     * @NoSubadminRequired
75
+     * @return array
76
+     */
77
+    public function addPersonalRootCertificate() {
78
+        return $this->addCertificate($this->userCertificateManager);
79
+    }
80
+
81
+    /**
82
+     * Add a new root certificate to a trust store
83
+     *
84
+     * @param ICertificateManager $certificateManager
85
+     * @return array
86
+     */
87
+    private function addCertificate(ICertificateManager $certificateManager) {
88
+        $headers = [];
89
+        if ($this->request->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE_8])) {
90
+            // due to upload iframe workaround, need to set content-type to text/plain
91
+            $headers['Content-Type'] = 'text/plain';
92
+        }
93
+
94
+        if ($this->isCertificateImportAllowed() === false) {
95
+            return new DataResponse(['message' => 'Individual certificate management disabled'], Http::STATUS_FORBIDDEN, $headers);
96
+        }
97
+
98
+        $file = $this->request->getUploadedFile('rootcert_import');
99
+        if (empty($file)) {
100
+            return new DataResponse(['message' => 'No file uploaded'], Http::STATUS_UNPROCESSABLE_ENTITY, $headers);
101
+        }
102
+
103
+        try {
104
+            $certificate = $certificateManager->addCertificate(file_get_contents($file['tmp_name']), $file['name']);
105
+            return new DataResponse(
106
+                [
107
+                    'name' => $certificate->getName(),
108
+                    'commonName' => $certificate->getCommonName(),
109
+                    'organization' => $certificate->getOrganization(),
110
+                    'validFrom' => $certificate->getIssueDate()->getTimestamp(),
111
+                    'validTill' => $certificate->getExpireDate()->getTimestamp(),
112
+                    'validFromString' => $this->l10n->l('date', $certificate->getIssueDate()),
113
+                    'validTillString' => $this->l10n->l('date', $certificate->getExpireDate()),
114
+                    'issuer' => $certificate->getIssuerName(),
115
+                    'issuerOrganization' => $certificate->getIssuerOrganization(),
116
+                ],
117
+                Http::STATUS_OK,
118
+                $headers
119
+            );
120
+        } catch (\Exception $e) {
121
+            return new DataResponse('An error occurred.', Http::STATUS_UNPROCESSABLE_ENTITY, $headers);
122
+        }
123
+    }
124
+
125
+    /**
126
+     * Removes a personal root certificate from the users' trust store
127
+     *
128
+     * @NoAdminRequired
129
+     * @NoSubadminRequired
130
+     * @param string $certificateIdentifier
131
+     * @return DataResponse
132
+     */
133
+    public function removePersonalRootCertificate($certificateIdentifier) {
134
+
135
+        if ($this->isCertificateImportAllowed() === false) {
136
+            return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
137
+        }
138
+
139
+        $this->userCertificateManager->removeCertificate($certificateIdentifier);
140
+        return new DataResponse();
141
+    }
142
+
143
+    /**
144
+     * check if certificate import is allowed
145
+     *
146
+     * @return bool
147
+     */
148
+    protected function isCertificateImportAllowed() {
149
+        $externalStorageEnabled = $this->appManager->isEnabledForUser('files_external');
150
+        if ($externalStorageEnabled) {
151
+            /** @var \OCA\Files_External\Service\BackendService $backendService */
152
+            $backendService = \OC_Mount_Config::$app->getContainer()->query('\OCA\Files_External\Service\BackendService');
153
+            if ($backendService->isUserMountingAllowed()) {
154
+                return true;
155
+            }
156
+        }
157
+        return false;
158
+    }
159
+
160
+    /**
161
+     * Add a new personal root certificate to the system's trust store
162
+     *
163
+     * @return array
164
+     */
165
+    public function addSystemRootCertificate() {
166
+        return $this->addCertificate($this->systemCertificateManager);
167
+    }
168
+
169
+    /**
170
+     * Removes a personal root certificate from the users' trust store
171
+     *
172
+     * @param string $certificateIdentifier
173
+     * @return DataResponse
174
+     */
175
+    public function removeSystemRootCertificate($certificateIdentifier) {
176
+
177
+        if ($this->isCertificateImportAllowed() === false) {
178
+            return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
179
+        }
180
+
181
+        $this->systemCertificateManager->removeCertificate($certificateIdentifier);
182
+        return new DataResponse();
183
+    }
184 184
 }
Please login to merge, or discard this patch.
settings/Controller/CheckSetupController.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -268,7 +268,7 @@
 block discarded – undo
268 268
 
269 269
 	/**
270 270
 	 * @NoCSRFRequired
271
-	 * @return DataResponse
271
+	 * @return DataDisplayResponse
272 272
 	 */
273 273
 	public function getFailedIntegrityCheckFiles() {
274 274
 		if(!$this->checker->isCodeCheckEnforced()) {
Please login to merge, or discard this patch.
Indentation   +298 added lines, -298 removed lines patch added patch discarded remove patch
@@ -44,247 +44,247 @@  discard block
 block discarded – undo
44 44
  * @package OC\Settings\Controller
45 45
  */
46 46
 class CheckSetupController extends Controller {
47
-	/** @var IConfig */
48
-	private $config;
49
-	/** @var IClientService */
50
-	private $clientService;
51
-	/** @var \OC_Util */
52
-	private $util;
53
-	/** @var IURLGenerator */
54
-	private $urlGenerator;
55
-	/** @var IL10N */
56
-	private $l10n;
57
-	/** @var Checker */
58
-	private $checker;
59
-
60
-	/**
61
-	 * @param string $AppName
62
-	 * @param IRequest $request
63
-	 * @param IConfig $config
64
-	 * @param IClientService $clientService
65
-	 * @param IURLGenerator $urlGenerator
66
-	 * @param \OC_Util $util
67
-	 * @param IL10N $l10n
68
-	 * @param Checker $checker
69
-	 */
70
-	public function __construct($AppName,
71
-								IRequest $request,
72
-								IConfig $config,
73
-								IClientService $clientService,
74
-								IURLGenerator $urlGenerator,
75
-								\OC_Util $util,
76
-								IL10N $l10n,
77
-								Checker $checker) {
78
-		parent::__construct($AppName, $request);
79
-		$this->config = $config;
80
-		$this->clientService = $clientService;
81
-		$this->util = $util;
82
-		$this->urlGenerator = $urlGenerator;
83
-		$this->l10n = $l10n;
84
-		$this->checker = $checker;
85
-	}
86
-
87
-	/**
88
-	 * Checks if the ownCloud server can connect to the internet using HTTPS and HTTP
89
-	 * @return bool
90
-	 */
91
-	private function isInternetConnectionWorking() {
92
-		if ($this->config->getSystemValue('has_internet_connection', true) === false) {
93
-			return false;
94
-		}
95
-
96
-		try {
97
-			$client = $this->clientService->newClient();
98
-			$client->get('https://www.owncloud.org/');
99
-			$client->get('http://www.owncloud.org/');
100
-			return true;
101
-		} catch (\Exception $e) {
102
-			return false;
103
-		}
104
-	}
105
-
106
-	/**
107
-	 * Checks whether a local memcache is installed or not
108
-	 * @return bool
109
-	 */
110
-	private function isMemcacheConfigured() {
111
-		return $this->config->getSystemValue('memcache.local', null) !== null;
112
-	}
113
-
114
-	/**
115
-	 * Whether /dev/urandom is available to the PHP controller
116
-	 *
117
-	 * @return bool
118
-	 */
119
-	private function isUrandomAvailable() {
120
-		if(@file_exists('/dev/urandom')) {
121
-			$file = fopen('/dev/urandom', 'rb');
122
-			if($file) {
123
-				fclose($file);
124
-				return true;
125
-			}
126
-		}
127
-
128
-		return false;
129
-	}
130
-
131
-	/**
132
-	 * Public for the sake of unit-testing
133
-	 *
134
-	 * @return array
135
-	 */
136
-	protected function getCurlVersion() {
137
-		return curl_version();
138
-	}
139
-
140
-	/**
141
-	 * Check if the used  SSL lib is outdated. Older OpenSSL and NSS versions do
142
-	 * have multiple bugs which likely lead to problems in combination with
143
-	 * functionality required by ownCloud such as SNI.
144
-	 *
145
-	 * @link https://github.com/owncloud/core/issues/17446#issuecomment-122877546
146
-	 * @link https://bugzilla.redhat.com/show_bug.cgi?id=1241172
147
-	 * @return string
148
-	 */
149
-	private function isUsedTlsLibOutdated() {
150
-		// Appstore is disabled by default in EE
151
-		$appStoreDefault = false;
152
-		if (\OC_Util::getEditionString() === '') {
153
-			$appStoreDefault = true;
154
-		}
155
-
156
-		// Don't run check when:
157
-		// 1. Server has `has_internet_connection` set to false
158
-		// 2. AppStore AND S2S is disabled
159
-		if(!$this->config->getSystemValue('has_internet_connection', true)) {
160
-			return '';
161
-		}
162
-		if(!$this->config->getSystemValue('appstoreenabled', $appStoreDefault)
163
-			&& $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'no'
164
-			&& $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'no') {
165
-			return '';
166
-		}
167
-
168
-		$versionString = $this->getCurlVersion();
169
-		if(isset($versionString['ssl_version'])) {
170
-			$versionString = $versionString['ssl_version'];
171
-		} else {
172
-			return '';
173
-		}
174
-
175
-		$features = (string)$this->l10n->t('installing and updating apps via the app store or Federated Cloud Sharing');
176
-		if(!$this->config->getSystemValue('appstoreenabled', $appStoreDefault)) {
177
-			$features = (string)$this->l10n->t('Federated Cloud Sharing');
178
-		}
179
-
180
-		// Check if at least OpenSSL after 1.01d or 1.0.2b
181
-		if(strpos($versionString, 'OpenSSL/') === 0) {
182
-			$majorVersion = substr($versionString, 8, 5);
183
-			$patchRelease = substr($versionString, 13, 6);
184
-
185
-			if(($majorVersion === '1.0.1' && ord($patchRelease) < ord('d')) ||
186
-				($majorVersion === '1.0.2' && ord($patchRelease) < ord('b'))) {
187
-				return (string) $this->l10n->t('cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably.', ['OpenSSL', $versionString, $features]);
188
-			}
189
-		}
190
-
191
-		// Check if NSS and perform heuristic check
192
-		if(strpos($versionString, 'NSS/') === 0) {
193
-			try {
194
-				$firstClient = $this->clientService->newClient();
195
-				$firstClient->get('https://www.owncloud.org/');
196
-
197
-				$secondClient = $this->clientService->newClient();
198
-				$secondClient->get('https://owncloud.org/');
199
-			} catch (ClientException $e) {
200
-				if($e->getResponse()->getStatusCode() === 400) {
201
-					return (string) $this->l10n->t('cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably.', ['NSS', $versionString, $features]);
202
-				}
203
-			}
204
-		}
205
-
206
-		return '';
207
-	}
208
-
209
-	/**
210
-	 * Whether the version is outdated
211
-	 *
212
-	 * @return bool
213
-	 */
214
-	protected function isPhpOutdated() {
215
-		if (version_compare(PHP_VERSION, '5.5.0') === -1) {
216
-			return true;
217
-		}
218
-		return false;
219
-	}
220
-
221
-	/**
222
-	 * Whether the php version is still supported (at time of release)
223
-	 * according to: https://secure.php.net/supported-versions.php
224
-	 *
225
-	 * @return array
226
-	 */
227
-	private function isPhpSupported() {
228
-		return ['eol' => $this->isPhpOutdated(), 'version' => PHP_VERSION];
229
-	}
230
-
231
-	/**
232
-	 * Check if the reverse proxy configuration is working as expected
233
-	 *
234
-	 * @return bool
235
-	 */
236
-	private function forwardedForHeadersWorking() {
237
-		$trustedProxies = $this->config->getSystemValue('trusted_proxies', []);
238
-		$remoteAddress = $this->request->getRemoteAddress();
239
-
240
-		if (is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) {
241
-			return false;
242
-		}
243
-
244
-		// either not enabled or working correctly
245
-		return true;
246
-	}
247
-
248
-	/**
249
-	 * Checks if the correct memcache module for PHP is installed. Only
250
-	 * fails if memcached is configured and the working module is not installed.
251
-	 *
252
-	 * @return bool
253
-	 */
254
-	private function isCorrectMemcachedPHPModuleInstalled() {
255
-		if ($this->config->getSystemValue('memcache.distributed', null) !== '\OC\Memcache\Memcached') {
256
-			return true;
257
-		}
258
-
259
-		// there are two different memcached modules for PHP
260
-		// we only support memcached and not memcache
261
-		// https://code.google.com/p/memcached/wiki/PHPClientComparison
262
-		return !(!extension_loaded('memcached') && extension_loaded('memcache'));
263
-	}
264
-
265
-	/**
266
-	 * @return RedirectResponse
267
-	 */
268
-	public function rescanFailedIntegrityCheck() {
269
-		$this->checker->runInstanceVerification();
270
-		return new RedirectResponse(
271
-			$this->urlGenerator->linkToRoute('settings.AdminSettings.index')
272
-		);
273
-	}
274
-
275
-	/**
276
-	 * @NoCSRFRequired
277
-	 * @return DataResponse
278
-	 */
279
-	public function getFailedIntegrityCheckFiles() {
280
-		if(!$this->checker->isCodeCheckEnforced()) {
281
-			return new DataDisplayResponse('Integrity checker has been disabled. Integrity cannot be verified.');
282
-		}
283
-
284
-		$completeResults = $this->checker->getResults();
285
-
286
-		if(!empty($completeResults)) {
287
-			$formattedTextResponse = 'Technical information
47
+    /** @var IConfig */
48
+    private $config;
49
+    /** @var IClientService */
50
+    private $clientService;
51
+    /** @var \OC_Util */
52
+    private $util;
53
+    /** @var IURLGenerator */
54
+    private $urlGenerator;
55
+    /** @var IL10N */
56
+    private $l10n;
57
+    /** @var Checker */
58
+    private $checker;
59
+
60
+    /**
61
+     * @param string $AppName
62
+     * @param IRequest $request
63
+     * @param IConfig $config
64
+     * @param IClientService $clientService
65
+     * @param IURLGenerator $urlGenerator
66
+     * @param \OC_Util $util
67
+     * @param IL10N $l10n
68
+     * @param Checker $checker
69
+     */
70
+    public function __construct($AppName,
71
+                                IRequest $request,
72
+                                IConfig $config,
73
+                                IClientService $clientService,
74
+                                IURLGenerator $urlGenerator,
75
+                                \OC_Util $util,
76
+                                IL10N $l10n,
77
+                                Checker $checker) {
78
+        parent::__construct($AppName, $request);
79
+        $this->config = $config;
80
+        $this->clientService = $clientService;
81
+        $this->util = $util;
82
+        $this->urlGenerator = $urlGenerator;
83
+        $this->l10n = $l10n;
84
+        $this->checker = $checker;
85
+    }
86
+
87
+    /**
88
+     * Checks if the ownCloud server can connect to the internet using HTTPS and HTTP
89
+     * @return bool
90
+     */
91
+    private function isInternetConnectionWorking() {
92
+        if ($this->config->getSystemValue('has_internet_connection', true) === false) {
93
+            return false;
94
+        }
95
+
96
+        try {
97
+            $client = $this->clientService->newClient();
98
+            $client->get('https://www.owncloud.org/');
99
+            $client->get('http://www.owncloud.org/');
100
+            return true;
101
+        } catch (\Exception $e) {
102
+            return false;
103
+        }
104
+    }
105
+
106
+    /**
107
+     * Checks whether a local memcache is installed or not
108
+     * @return bool
109
+     */
110
+    private function isMemcacheConfigured() {
111
+        return $this->config->getSystemValue('memcache.local', null) !== null;
112
+    }
113
+
114
+    /**
115
+     * Whether /dev/urandom is available to the PHP controller
116
+     *
117
+     * @return bool
118
+     */
119
+    private function isUrandomAvailable() {
120
+        if(@file_exists('/dev/urandom')) {
121
+            $file = fopen('/dev/urandom', 'rb');
122
+            if($file) {
123
+                fclose($file);
124
+                return true;
125
+            }
126
+        }
127
+
128
+        return false;
129
+    }
130
+
131
+    /**
132
+     * Public for the sake of unit-testing
133
+     *
134
+     * @return array
135
+     */
136
+    protected function getCurlVersion() {
137
+        return curl_version();
138
+    }
139
+
140
+    /**
141
+     * Check if the used  SSL lib is outdated. Older OpenSSL and NSS versions do
142
+     * have multiple bugs which likely lead to problems in combination with
143
+     * functionality required by ownCloud such as SNI.
144
+     *
145
+     * @link https://github.com/owncloud/core/issues/17446#issuecomment-122877546
146
+     * @link https://bugzilla.redhat.com/show_bug.cgi?id=1241172
147
+     * @return string
148
+     */
149
+    private function isUsedTlsLibOutdated() {
150
+        // Appstore is disabled by default in EE
151
+        $appStoreDefault = false;
152
+        if (\OC_Util::getEditionString() === '') {
153
+            $appStoreDefault = true;
154
+        }
155
+
156
+        // Don't run check when:
157
+        // 1. Server has `has_internet_connection` set to false
158
+        // 2. AppStore AND S2S is disabled
159
+        if(!$this->config->getSystemValue('has_internet_connection', true)) {
160
+            return '';
161
+        }
162
+        if(!$this->config->getSystemValue('appstoreenabled', $appStoreDefault)
163
+            && $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'no'
164
+            && $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'no') {
165
+            return '';
166
+        }
167
+
168
+        $versionString = $this->getCurlVersion();
169
+        if(isset($versionString['ssl_version'])) {
170
+            $versionString = $versionString['ssl_version'];
171
+        } else {
172
+            return '';
173
+        }
174
+
175
+        $features = (string)$this->l10n->t('installing and updating apps via the app store or Federated Cloud Sharing');
176
+        if(!$this->config->getSystemValue('appstoreenabled', $appStoreDefault)) {
177
+            $features = (string)$this->l10n->t('Federated Cloud Sharing');
178
+        }
179
+
180
+        // Check if at least OpenSSL after 1.01d or 1.0.2b
181
+        if(strpos($versionString, 'OpenSSL/') === 0) {
182
+            $majorVersion = substr($versionString, 8, 5);
183
+            $patchRelease = substr($versionString, 13, 6);
184
+
185
+            if(($majorVersion === '1.0.1' && ord($patchRelease) < ord('d')) ||
186
+                ($majorVersion === '1.0.2' && ord($patchRelease) < ord('b'))) {
187
+                return (string) $this->l10n->t('cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably.', ['OpenSSL', $versionString, $features]);
188
+            }
189
+        }
190
+
191
+        // Check if NSS and perform heuristic check
192
+        if(strpos($versionString, 'NSS/') === 0) {
193
+            try {
194
+                $firstClient = $this->clientService->newClient();
195
+                $firstClient->get('https://www.owncloud.org/');
196
+
197
+                $secondClient = $this->clientService->newClient();
198
+                $secondClient->get('https://owncloud.org/');
199
+            } catch (ClientException $e) {
200
+                if($e->getResponse()->getStatusCode() === 400) {
201
+                    return (string) $this->l10n->t('cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably.', ['NSS', $versionString, $features]);
202
+                }
203
+            }
204
+        }
205
+
206
+        return '';
207
+    }
208
+
209
+    /**
210
+     * Whether the version is outdated
211
+     *
212
+     * @return bool
213
+     */
214
+    protected function isPhpOutdated() {
215
+        if (version_compare(PHP_VERSION, '5.5.0') === -1) {
216
+            return true;
217
+        }
218
+        return false;
219
+    }
220
+
221
+    /**
222
+     * Whether the php version is still supported (at time of release)
223
+     * according to: https://secure.php.net/supported-versions.php
224
+     *
225
+     * @return array
226
+     */
227
+    private function isPhpSupported() {
228
+        return ['eol' => $this->isPhpOutdated(), 'version' => PHP_VERSION];
229
+    }
230
+
231
+    /**
232
+     * Check if the reverse proxy configuration is working as expected
233
+     *
234
+     * @return bool
235
+     */
236
+    private function forwardedForHeadersWorking() {
237
+        $trustedProxies = $this->config->getSystemValue('trusted_proxies', []);
238
+        $remoteAddress = $this->request->getRemoteAddress();
239
+
240
+        if (is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) {
241
+            return false;
242
+        }
243
+
244
+        // either not enabled or working correctly
245
+        return true;
246
+    }
247
+
248
+    /**
249
+     * Checks if the correct memcache module for PHP is installed. Only
250
+     * fails if memcached is configured and the working module is not installed.
251
+     *
252
+     * @return bool
253
+     */
254
+    private function isCorrectMemcachedPHPModuleInstalled() {
255
+        if ($this->config->getSystemValue('memcache.distributed', null) !== '\OC\Memcache\Memcached') {
256
+            return true;
257
+        }
258
+
259
+        // there are two different memcached modules for PHP
260
+        // we only support memcached and not memcache
261
+        // https://code.google.com/p/memcached/wiki/PHPClientComparison
262
+        return !(!extension_loaded('memcached') && extension_loaded('memcache'));
263
+    }
264
+
265
+    /**
266
+     * @return RedirectResponse
267
+     */
268
+    public function rescanFailedIntegrityCheck() {
269
+        $this->checker->runInstanceVerification();
270
+        return new RedirectResponse(
271
+            $this->urlGenerator->linkToRoute('settings.AdminSettings.index')
272
+        );
273
+    }
274
+
275
+    /**
276
+     * @NoCSRFRequired
277
+     * @return DataResponse
278
+     */
279
+    public function getFailedIntegrityCheckFiles() {
280
+        if(!$this->checker->isCodeCheckEnforced()) {
281
+            return new DataDisplayResponse('Integrity checker has been disabled. Integrity cannot be verified.');
282
+        }
283
+
284
+        $completeResults = $this->checker->getResults();
285
+
286
+        if(!empty($completeResults)) {
287
+            $formattedTextResponse = 'Technical information
288 288
 =====================
289 289
 The following list covers which files have failed the integrity check. Please read
290 290
 the previous linked documentation to learn more about the errors and how to fix
@@ -293,64 +293,64 @@  discard block
 block discarded – undo
293 293
 Results
294 294
 =======
295 295
 ';
296
-			foreach($completeResults as $context => $contextResult) {
297
-				$formattedTextResponse .= "- $context\n";
298
-
299
-				foreach($contextResult as $category => $result) {
300
-					$formattedTextResponse .= "\t- $category\n";
301
-					if($category !== 'EXCEPTION') {
302
-						foreach ($result as $key => $results) {
303
-							$formattedTextResponse .= "\t\t- $key\n";
304
-						}
305
-					} else {
306
-						foreach ($result as $key => $results) {
307
-							$formattedTextResponse .= "\t\t- $results\n";
308
-						}
309
-					}
310
-
311
-				}
312
-			}
313
-
314
-			$formattedTextResponse .= '
296
+            foreach($completeResults as $context => $contextResult) {
297
+                $formattedTextResponse .= "- $context\n";
298
+
299
+                foreach($contextResult as $category => $result) {
300
+                    $formattedTextResponse .= "\t- $category\n";
301
+                    if($category !== 'EXCEPTION') {
302
+                        foreach ($result as $key => $results) {
303
+                            $formattedTextResponse .= "\t\t- $key\n";
304
+                        }
305
+                    } else {
306
+                        foreach ($result as $key => $results) {
307
+                            $formattedTextResponse .= "\t\t- $results\n";
308
+                        }
309
+                    }
310
+
311
+                }
312
+            }
313
+
314
+            $formattedTextResponse .= '
315 315
 Raw output
316 316
 ==========
317 317
 ';
318
-			$formattedTextResponse .= print_r($completeResults, true);
319
-		} else {
320
-			$formattedTextResponse = 'No errors have been found.';
321
-		}
322
-
323
-
324
-		$response = new DataDisplayResponse(
325
-			$formattedTextResponse,
326
-			Http::STATUS_OK,
327
-			[
328
-				'Content-Type' => 'text/plain',
329
-			]
330
-		);
331
-
332
-		return $response;
333
-	}
334
-
335
-	/**
336
-	 * @return DataResponse
337
-	 */
338
-	public function check() {
339
-		return new DataResponse(
340
-			[
341
-				'serverHasInternetConnection' => $this->isInternetConnectionWorking(),
342
-				'isMemcacheConfigured' => $this->isMemcacheConfigured(),
343
-				'memcacheDocs' => $this->urlGenerator->linkToDocs('admin-performance'),
344
-				'isUrandomAvailable' => $this->isUrandomAvailable(),
345
-				'securityDocs' => $this->urlGenerator->linkToDocs('admin-security'),
346
-				'isUsedTlsLibOutdated' => $this->isUsedTlsLibOutdated(),
347
-				'phpSupported' => $this->isPhpSupported(),
348
-				'forwardedForHeadersWorking' => $this->forwardedForHeadersWorking(),
349
-				'reverseProxyDocs' => $this->urlGenerator->linkToDocs('admin-reverse-proxy'),
350
-				'isCorrectMemcachedPHPModuleInstalled' => $this->isCorrectMemcachedPHPModuleInstalled(),
351
-				'hasPassedCodeIntegrityCheck' => $this->checker->hasPassedCheck(),
352
-				'codeIntegrityCheckerDocumentation' => $this->urlGenerator->linkToDocs('admin-code-integrity'),
353
-			]
354
-		);
355
-	}
318
+            $formattedTextResponse .= print_r($completeResults, true);
319
+        } else {
320
+            $formattedTextResponse = 'No errors have been found.';
321
+        }
322
+
323
+
324
+        $response = new DataDisplayResponse(
325
+            $formattedTextResponse,
326
+            Http::STATUS_OK,
327
+            [
328
+                'Content-Type' => 'text/plain',
329
+            ]
330
+        );
331
+
332
+        return $response;
333
+    }
334
+
335
+    /**
336
+     * @return DataResponse
337
+     */
338
+    public function check() {
339
+        return new DataResponse(
340
+            [
341
+                'serverHasInternetConnection' => $this->isInternetConnectionWorking(),
342
+                'isMemcacheConfigured' => $this->isMemcacheConfigured(),
343
+                'memcacheDocs' => $this->urlGenerator->linkToDocs('admin-performance'),
344
+                'isUrandomAvailable' => $this->isUrandomAvailable(),
345
+                'securityDocs' => $this->urlGenerator->linkToDocs('admin-security'),
346
+                'isUsedTlsLibOutdated' => $this->isUsedTlsLibOutdated(),
347
+                'phpSupported' => $this->isPhpSupported(),
348
+                'forwardedForHeadersWorking' => $this->forwardedForHeadersWorking(),
349
+                'reverseProxyDocs' => $this->urlGenerator->linkToDocs('admin-reverse-proxy'),
350
+                'isCorrectMemcachedPHPModuleInstalled' => $this->isCorrectMemcachedPHPModuleInstalled(),
351
+                'hasPassedCodeIntegrityCheck' => $this->checker->hasPassedCheck(),
352
+                'codeIntegrityCheckerDocumentation' => $this->urlGenerator->linkToDocs('admin-code-integrity'),
353
+            ]
354
+        );
355
+    }
356 356
 }
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -117,9 +117,9 @@  discard block
 block discarded – undo
117 117
 	 * @return bool
118 118
 	 */
119 119
 	private function isUrandomAvailable() {
120
-		if(@file_exists('/dev/urandom')) {
120
+		if (@file_exists('/dev/urandom')) {
121 121
 			$file = fopen('/dev/urandom', 'rb');
122
-			if($file) {
122
+			if ($file) {
123 123
 				fclose($file);
124 124
 				return true;
125 125
 			}
@@ -156,40 +156,40 @@  discard block
 block discarded – undo
156 156
 		// Don't run check when:
157 157
 		// 1. Server has `has_internet_connection` set to false
158 158
 		// 2. AppStore AND S2S is disabled
159
-		if(!$this->config->getSystemValue('has_internet_connection', true)) {
159
+		if (!$this->config->getSystemValue('has_internet_connection', true)) {
160 160
 			return '';
161 161
 		}
162
-		if(!$this->config->getSystemValue('appstoreenabled', $appStoreDefault)
162
+		if (!$this->config->getSystemValue('appstoreenabled', $appStoreDefault)
163 163
 			&& $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'no'
164 164
 			&& $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'no') {
165 165
 			return '';
166 166
 		}
167 167
 
168 168
 		$versionString = $this->getCurlVersion();
169
-		if(isset($versionString['ssl_version'])) {
169
+		if (isset($versionString['ssl_version'])) {
170 170
 			$versionString = $versionString['ssl_version'];
171 171
 		} else {
172 172
 			return '';
173 173
 		}
174 174
 
175
-		$features = (string)$this->l10n->t('installing and updating apps via the app store or Federated Cloud Sharing');
176
-		if(!$this->config->getSystemValue('appstoreenabled', $appStoreDefault)) {
177
-			$features = (string)$this->l10n->t('Federated Cloud Sharing');
175
+		$features = (string) $this->l10n->t('installing and updating apps via the app store or Federated Cloud Sharing');
176
+		if (!$this->config->getSystemValue('appstoreenabled', $appStoreDefault)) {
177
+			$features = (string) $this->l10n->t('Federated Cloud Sharing');
178 178
 		}
179 179
 
180 180
 		// Check if at least OpenSSL after 1.01d or 1.0.2b
181
-		if(strpos($versionString, 'OpenSSL/') === 0) {
181
+		if (strpos($versionString, 'OpenSSL/') === 0) {
182 182
 			$majorVersion = substr($versionString, 8, 5);
183 183
 			$patchRelease = substr($versionString, 13, 6);
184 184
 
185
-			if(($majorVersion === '1.0.1' && ord($patchRelease) < ord('d')) ||
185
+			if (($majorVersion === '1.0.1' && ord($patchRelease) < ord('d')) ||
186 186
 				($majorVersion === '1.0.2' && ord($patchRelease) < ord('b'))) {
187 187
 				return (string) $this->l10n->t('cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably.', ['OpenSSL', $versionString, $features]);
188 188
 			}
189 189
 		}
190 190
 
191 191
 		// Check if NSS and perform heuristic check
192
-		if(strpos($versionString, 'NSS/') === 0) {
192
+		if (strpos($versionString, 'NSS/') === 0) {
193 193
 			try {
194 194
 				$firstClient = $this->clientService->newClient();
195 195
 				$firstClient->get('https://www.owncloud.org/');
@@ -197,7 +197,7 @@  discard block
 block discarded – undo
197 197
 				$secondClient = $this->clientService->newClient();
198 198
 				$secondClient->get('https://owncloud.org/');
199 199
 			} catch (ClientException $e) {
200
-				if($e->getResponse()->getStatusCode() === 400) {
200
+				if ($e->getResponse()->getStatusCode() === 400) {
201 201
 					return (string) $this->l10n->t('cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably.', ['NSS', $versionString, $features]);
202 202
 				}
203 203
 			}
@@ -277,13 +277,13 @@  discard block
 block discarded – undo
277 277
 	 * @return DataResponse
278 278
 	 */
279 279
 	public function getFailedIntegrityCheckFiles() {
280
-		if(!$this->checker->isCodeCheckEnforced()) {
280
+		if (!$this->checker->isCodeCheckEnforced()) {
281 281
 			return new DataDisplayResponse('Integrity checker has been disabled. Integrity cannot be verified.');
282 282
 		}
283 283
 
284 284
 		$completeResults = $this->checker->getResults();
285 285
 
286
-		if(!empty($completeResults)) {
286
+		if (!empty($completeResults)) {
287 287
 			$formattedTextResponse = 'Technical information
288 288
 =====================
289 289
 The following list covers which files have failed the integrity check. Please read
@@ -293,12 +293,12 @@  discard block
 block discarded – undo
293 293
 Results
294 294
 =======
295 295
 ';
296
-			foreach($completeResults as $context => $contextResult) {
296
+			foreach ($completeResults as $context => $contextResult) {
297 297
 				$formattedTextResponse .= "- $context\n";
298 298
 
299
-				foreach($contextResult as $category => $result) {
299
+				foreach ($contextResult as $category => $result) {
300 300
 					$formattedTextResponse .= "\t- $category\n";
301
-					if($category !== 'EXCEPTION') {
301
+					if ($category !== 'EXCEPTION') {
302 302
 						foreach ($result as $key => $results) {
303 303
 							$formattedTextResponse .= "\t\t- $key\n";
304 304
 						}
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Storage/Google.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -216,7 +216,7 @@
 block discarded – undo
216 216
 	 *
217 217
 	 * @param \Google_Service_Drive_DriveFile
218 218
 	 *
219
-	 * @return true if the file is a Google Doc file, false otherwise
219
+	 * @return boolean if the file is a Google Doc file, false otherwise
220 220
 	 */
221 221
 	private function isGoogleDocFile($file) {
222 222
 		return $this->getGoogleDocExtension($file->getMimeType()) !== '';
Please login to merge, or discard this patch.
Indentation   +680 added lines, -680 removed lines patch added patch discarded remove patch
@@ -40,689 +40,689 @@
 block discarded – undo
40 40
 use Icewind\Streams\RetryWrapper;
41 41
 
42 42
 set_include_path(get_include_path().PATH_SEPARATOR.
43
-	\OC_App::getAppPath('files_external').'/3rdparty/google-api-php-client/src');
43
+    \OC_App::getAppPath('files_external').'/3rdparty/google-api-php-client/src');
44 44
 require_once 'Google/autoload.php';
45 45
 
46 46
 class Google extends \OC\Files\Storage\Common {
47 47
 
48
-	private $client;
49
-	private $id;
50
-	private $service;
51
-	private $driveFiles;
52
-
53
-	private static $tempFiles = array();
54
-
55
-	// Google Doc mimetypes
56
-	const FOLDER = 'application/vnd.google-apps.folder';
57
-	const DOCUMENT = 'application/vnd.google-apps.document';
58
-	const SPREADSHEET = 'application/vnd.google-apps.spreadsheet';
59
-	const DRAWING = 'application/vnd.google-apps.drawing';
60
-	const PRESENTATION = 'application/vnd.google-apps.presentation';
61
-	const MAP = 'application/vnd.google-apps.map';
62
-
63
-	public function __construct($params) {
64
-		if (isset($params['configured']) && $params['configured'] === 'true'
65
-			&& isset($params['client_id']) && isset($params['client_secret'])
66
-			&& isset($params['token'])
67
-		) {
68
-			$this->client = new \Google_Client();
69
-			$this->client->setClientId($params['client_id']);
70
-			$this->client->setClientSecret($params['client_secret']);
71
-			$this->client->setScopes(array('https://www.googleapis.com/auth/drive'));
72
-			$this->client->setAccessToken($params['token']);
73
-			// if curl isn't available we're likely to run into
74
-			// https://github.com/google/google-api-php-client/issues/59
75
-			// - disable gzip to avoid it.
76
-			if (!function_exists('curl_version') || !function_exists('curl_exec')) {
77
-				$this->client->setClassConfig("Google_Http_Request", "disable_gzip", true);
78
-			}
79
-			// note: API connection is lazy
80
-			$this->service = new \Google_Service_Drive($this->client);
81
-			$token = json_decode($params['token'], true);
82
-			$this->id = 'google::'.substr($params['client_id'], 0, 30).$token['created'];
83
-		} else {
84
-			throw new \Exception('Creating Google storage failed');
85
-		}
86
-	}
87
-
88
-	public function getId() {
89
-		return $this->id;
90
-	}
91
-
92
-	/**
93
-	 * Get the Google_Service_Drive_DriveFile object for the specified path.
94
-	 * Returns false on failure.
95
-	 * @param string $path
96
-	 * @return \Google_Service_Drive_DriveFile|false
97
-	 */
98
-	private function getDriveFile($path) {
99
-		// Remove leading and trailing slashes
100
-		$path = trim($path, '/');
101
-		if ($path === '.') {
102
-			$path = '';
103
-		}
104
-		if (isset($this->driveFiles[$path])) {
105
-			return $this->driveFiles[$path];
106
-		} else if ($path === '') {
107
-			$root = $this->service->files->get('root');
108
-			$this->driveFiles[$path] = $root;
109
-			return $root;
110
-		} else {
111
-			// Google Drive SDK does not have methods for retrieving files by path
112
-			// Instead we must find the id of the parent folder of the file
113
-			$parentId = $this->getDriveFile('')->getId();
114
-			$folderNames = explode('/', $path);
115
-			$path = '';
116
-			// Loop through each folder of this path to get to the file
117
-			foreach ($folderNames as $name) {
118
-				// Reconstruct path from beginning
119
-				if ($path === '') {
120
-					$path .= $name;
121
-				} else {
122
-					$path .= '/'.$name;
123
-				}
124
-				if (isset($this->driveFiles[$path])) {
125
-					$parentId = $this->driveFiles[$path]->getId();
126
-				} else {
127
-					$q = "title='" . str_replace("'","\\'", $name) . "' and '" . str_replace("'","\\'", $parentId) . "' in parents and trashed = false";
128
-					$result = $this->service->files->listFiles(array('q' => $q))->getItems();
129
-					if (!empty($result)) {
130
-						// Google Drive allows files with the same name, ownCloud doesn't
131
-						if (count($result) > 1) {
132
-							$this->onDuplicateFileDetected($path);
133
-							return false;
134
-						} else {
135
-							$file = current($result);
136
-							$this->driveFiles[$path] = $file;
137
-							$parentId = $file->getId();
138
-						}
139
-					} else {
140
-						// Google Docs have no extension in their title, so try without extension
141
-						$pos = strrpos($path, '.');
142
-						if ($pos !== false) {
143
-							$pathWithoutExt = substr($path, 0, $pos);
144
-							$file = $this->getDriveFile($pathWithoutExt);
145
-							if ($file && $this->isGoogleDocFile($file)) {
146
-								// Switch cached Google_Service_Drive_DriveFile to the correct index
147
-								unset($this->driveFiles[$pathWithoutExt]);
148
-								$this->driveFiles[$path] = $file;
149
-								$parentId = $file->getId();
150
-							} else {
151
-								return false;
152
-							}
153
-						} else {
154
-							return false;
155
-						}
156
-					}
157
-				}
158
-			}
159
-			return $this->driveFiles[$path];
160
-		}
161
-	}
162
-
163
-	/**
164
-	 * Set the Google_Service_Drive_DriveFile object in the cache
165
-	 * @param string $path
166
-	 * @param \Google_Service_Drive_DriveFile|false $file
167
-	 */
168
-	private function setDriveFile($path, $file) {
169
-		$path = trim($path, '/');
170
-		$this->driveFiles[$path] = $file;
171
-		if ($file === false) {
172
-			// Remove all children
173
-			$len = strlen($path);
174
-			foreach ($this->driveFiles as $key => $file) {
175
-				if (substr($key, 0, $len) === $path) {
176
-					unset($this->driveFiles[$key]);
177
-				}
178
-			}
179
-		}
180
-	}
181
-
182
-	/**
183
-	 * Write a log message to inform about duplicate file names
184
-	 * @param string $path
185
-	 */
186
-	private function onDuplicateFileDetected($path) {
187
-		$about = $this->service->about->get();
188
-		$user = $about->getName();
189
-		\OCP\Util::writeLog('files_external',
190
-			'Ignoring duplicate file name: '.$path.' on Google Drive for Google user: '.$user,
191
-			\OCP\Util::INFO
192
-		);
193
-	}
194
-
195
-	/**
196
-	 * Generate file extension for a Google Doc, choosing Open Document formats for download
197
-	 * @param string $mimetype
198
-	 * @return string
199
-	 */
200
-	private function getGoogleDocExtension($mimetype) {
201
-		if ($mimetype === self::DOCUMENT) {
202
-			return 'odt';
203
-		} else if ($mimetype === self::SPREADSHEET) {
204
-			return 'ods';
205
-		} else if ($mimetype === self::DRAWING) {
206
-			return 'jpg';
207
-		} else if ($mimetype === self::PRESENTATION) {
208
-			// Download as .odp is not available
209
-			return 'pdf';
210
-		} else {
211
-			return '';
212
-		}
213
-	}
214
-
215
-	/**
216
-	 * Returns whether the given drive file is a Google Doc file
217
-	 *
218
-	 * @param \Google_Service_Drive_DriveFile
219
-	 *
220
-	 * @return true if the file is a Google Doc file, false otherwise
221
-	 */
222
-	private function isGoogleDocFile($file) {
223
-		return $this->getGoogleDocExtension($file->getMimeType()) !== '';
224
-	}
225
-
226
-	public function mkdir($path) {
227
-		if (!$this->is_dir($path)) {
228
-			$parentFolder = $this->getDriveFile(dirname($path));
229
-			if ($parentFolder) {
230
-				$folder = new \Google_Service_Drive_DriveFile();
231
-				$folder->setTitle(basename($path));
232
-				$folder->setMimeType(self::FOLDER);
233
-				$parent = new \Google_Service_Drive_ParentReference();
234
-				$parent->setId($parentFolder->getId());
235
-				$folder->setParents(array($parent));
236
-				$result = $this->service->files->insert($folder);
237
-				if ($result) {
238
-					$this->setDriveFile($path, $result);
239
-				}
240
-				return (bool)$result;
241
-			}
242
-		}
243
-		return false;
244
-	}
245
-
246
-	public function rmdir($path) {
247
-		if (!$this->isDeletable($path)) {
248
-			return false;
249
-		}
250
-		if (trim($path, '/') === '') {
251
-			$dir = $this->opendir($path);
252
-			if(is_resource($dir)) {
253
-				while (($file = readdir($dir)) !== false) {
254
-					if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
255
-						if (!$this->unlink($path.'/'.$file)) {
256
-							return false;
257
-						}
258
-					}
259
-				}
260
-				closedir($dir);
261
-			}
262
-			$this->driveFiles = array();
263
-			return true;
264
-		} else {
265
-			return $this->unlink($path);
266
-		}
267
-	}
268
-
269
-	public function opendir($path) {
270
-		$folder = $this->getDriveFile($path);
271
-		if ($folder) {
272
-			$files = array();
273
-			$duplicates = array();
274
-			$pageToken = true;
275
-			while ($pageToken) {
276
-				$params = array();
277
-				if ($pageToken !== true) {
278
-					$params['pageToken'] = $pageToken;
279
-				}
280
-				$params['q'] = "'" . str_replace("'","\\'", $folder->getId()) . "' in parents and trashed = false";
281
-				$children = $this->service->files->listFiles($params);
282
-				foreach ($children->getItems() as $child) {
283
-					$name = $child->getTitle();
284
-					// Check if this is a Google Doc i.e. no extension in name
285
-					$extension = $child->getFileExtension();
286
-					if (empty($extension)) {
287
-						if ($child->getMimeType() === self::MAP) {
288
-							continue; // No method known to transfer map files, ignore it
289
-						} else if ($child->getMimeType() !== self::FOLDER) {
290
-							$name .= '.'.$this->getGoogleDocExtension($child->getMimeType());
291
-						}
292
-					}
293
-					if ($path === '') {
294
-						$filepath = $name;
295
-					} else {
296
-						$filepath = $path.'/'.$name;
297
-					}
298
-					// Google Drive allows files with the same name, ownCloud doesn't
299
-					// Prevent opendir() from returning any duplicate files
300
-					$key = array_search($name, $files);
301
-					if ($key !== false || isset($duplicates[$filepath])) {
302
-						if (!isset($duplicates[$filepath])) {
303
-							$duplicates[$filepath] = true;
304
-							$this->setDriveFile($filepath, false);
305
-							unset($files[$key]);
306
-							$this->onDuplicateFileDetected($filepath);
307
-						}
308
-					} else {
309
-						// Cache the Google_Service_Drive_DriveFile for future use
310
-						$this->setDriveFile($filepath, $child);
311
-						$files[] = $name;
312
-					}
313
-				}
314
-				$pageToken = $children->getNextPageToken();
315
-			}
316
-			return IteratorDirectory::wrap($files);
317
-		} else {
318
-			return false;
319
-		}
320
-	}
321
-
322
-	public function stat($path) {
323
-		$file = $this->getDriveFile($path);
324
-		if ($file) {
325
-			$stat = array();
326
-			if ($this->filetype($path) === 'dir') {
327
-				$stat['size'] = 0;
328
-			} else {
329
-				// Check if this is a Google Doc
330
-				if ($this->isGoogleDocFile($file)) {
331
-					// Return unknown file size
332
-					$stat['size'] = \OCP\Files\FileInfo::SPACE_UNKNOWN;
333
-				} else {
334
-					$stat['size'] = $file->getFileSize();
335
-				}
336
-			}
337
-			$stat['atime'] = strtotime($file->getLastViewedByMeDate());
338
-			$stat['mtime'] = strtotime($file->getModifiedDate());
339
-			$stat['ctime'] = strtotime($file->getCreatedDate());
340
-			return $stat;
341
-		} else {
342
-			return false;
343
-		}
344
-	}
345
-
346
-	public function filetype($path) {
347
-		if ($path === '') {
348
-			return 'dir';
349
-		} else {
350
-			$file = $this->getDriveFile($path);
351
-			if ($file) {
352
-				if ($file->getMimeType() === self::FOLDER) {
353
-					return 'dir';
354
-				} else {
355
-					return 'file';
356
-				}
357
-			} else {
358
-				return false;
359
-			}
360
-		}
361
-	}
362
-
363
-	public function isUpdatable($path) {
364
-		$file = $this->getDriveFile($path);
365
-		if ($file) {
366
-			return $file->getEditable();
367
-		} else {
368
-			return false;
369
-		}
370
-	}
371
-
372
-	public function file_exists($path) {
373
-		return (bool)$this->getDriveFile($path);
374
-	}
375
-
376
-	public function unlink($path) {
377
-		$file = $this->getDriveFile($path);
378
-		if ($file) {
379
-			$result = $this->service->files->trash($file->getId());
380
-			if ($result) {
381
-				$this->setDriveFile($path, false);
382
-			}
383
-			return (bool)$result;
384
-		} else {
385
-			return false;
386
-		}
387
-	}
388
-
389
-	public function rename($path1, $path2) {
390
-		$file = $this->getDriveFile($path1);
391
-		if ($file) {
392
-			$newFile = $this->getDriveFile($path2);
393
-			if (dirname($path1) === dirname($path2)) {
394
-				if ($newFile) {
395
-					// rename to the name of the target file, could be an office file without extension
396
-					$file->setTitle($newFile->getTitle());
397
-				} else {
398
-					$file->setTitle(basename(($path2)));
399
-				}
400
-			} else {
401
-				// Change file parent
402
-				$parentFolder2 = $this->getDriveFile(dirname($path2));
403
-				if ($parentFolder2) {
404
-					$parent = new \Google_Service_Drive_ParentReference();
405
-					$parent->setId($parentFolder2->getId());
406
-					$file->setParents(array($parent));
407
-				} else {
408
-					return false;
409
-				}
410
-			}
411
-			// We need to get the object for the existing file with the same
412
-			// name (if there is one) before we do the patch. If oldfile
413
-			// exists and is a directory we have to delete it before we
414
-			// do the rename too.
415
-			$oldfile = $this->getDriveFile($path2);
416
-			if ($oldfile && $this->is_dir($path2)) {
417
-				$this->rmdir($path2);
418
-				$oldfile = false;
419
-			}
420
-			$result = $this->service->files->patch($file->getId(), $file);
421
-			if ($result) {
422
-				$this->setDriveFile($path1, false);
423
-				$this->setDriveFile($path2, $result);
424
-				if ($oldfile && $newFile) {
425
-					// only delete if they have a different id (same id can happen for part files)
426
-					if ($newFile->getId() !== $oldfile->getId()) {
427
-						$this->service->files->delete($oldfile->getId());
428
-					}
429
-				}
430
-			}
431
-			return (bool)$result;
432
-		} else {
433
-			return false;
434
-		}
435
-	}
436
-
437
-	public function fopen($path, $mode) {
438
-		$pos = strrpos($path, '.');
439
-		if ($pos !== false) {
440
-			$ext = substr($path, $pos);
441
-		} else {
442
-			$ext = '';
443
-		}
444
-		switch ($mode) {
445
-			case 'r':
446
-			case 'rb':
447
-				$file = $this->getDriveFile($path);
448
-				if ($file) {
449
-					$exportLinks = $file->getExportLinks();
450
-					$mimetype = $this->getMimeType($path);
451
-					$downloadUrl = null;
452
-					if ($exportLinks && isset($exportLinks[$mimetype])) {
453
-						$downloadUrl = $exportLinks[$mimetype];
454
-					} else {
455
-						$downloadUrl = $file->getDownloadUrl();
456
-					}
457
-					if (isset($downloadUrl)) {
458
-						$request = new \Google_Http_Request($downloadUrl, 'GET', null, null);
459
-						$httpRequest = $this->client->getAuth()->sign($request);
460
-						// the library's service doesn't support streaming, so we use Guzzle instead
461
-						$client = \OC::$server->getHTTPClientService()->newClient();
462
-						try {
463
-							$response = $client->get($downloadUrl, [
464
-								'headers' => $httpRequest->getRequestHeaders(),
465
-								'stream' => true,
466
-								'verify' => realpath(__DIR__ . '/../../../3rdparty/google-api-php-client/src/Google/IO/cacerts.pem'),
467
-							]);
468
-						} catch (RequestException $e) {
469
-							if(!is_null($e->getResponse())) {
470
-								if ($e->getResponse()->getStatusCode() === 404) {
471
-									return false;
472
-								} else {
473
-									throw $e;
474
-								}
475
-							} else {
476
-								throw $e;
477
-							}
478
-						}
479
-
480
-						$handle = $response->getBody();
481
-						return RetryWrapper::wrap($handle);
482
-					}
483
-				}
484
-				return false;
485
-			case 'w':
486
-			case 'wb':
487
-			case 'a':
488
-			case 'ab':
489
-			case 'r+':
490
-			case 'w+':
491
-			case 'wb+':
492
-			case 'a+':
493
-			case 'x':
494
-			case 'x+':
495
-			case 'c':
496
-			case 'c+':
497
-				$tmpFile = \OCP\Files::tmpFile($ext);
498
-				\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
499
-				if ($this->file_exists($path)) {
500
-					$source = $this->fopen($path, 'rb');
501
-					file_put_contents($tmpFile, $source);
502
-				}
503
-				self::$tempFiles[$tmpFile] = $path;
504
-				return fopen('close://'.$tmpFile, $mode);
505
-		}
506
-	}
507
-
508
-	public function writeBack($tmpFile) {
509
-		if (isset(self::$tempFiles[$tmpFile])) {
510
-			$path = self::$tempFiles[$tmpFile];
511
-			$parentFolder = $this->getDriveFile(dirname($path));
512
-			if ($parentFolder) {
513
-				$mimetype = \OC::$server->getMimeTypeDetector()->detect($tmpFile);
514
-				$params = array(
515
-					'mimeType' => $mimetype,
516
-					'uploadType' => 'media'
517
-				);
518
-				$result = false;
519
-
520
-				$chunkSizeBytes = 10 * 1024 * 1024;
521
-
522
-				$useChunking = false;
523
-				$size = filesize($tmpFile);
524
-				if ($size > $chunkSizeBytes) {
525
-					$useChunking = true;
526
-				} else {
527
-					$params['data'] = file_get_contents($tmpFile);
528
-				}
529
-
530
-				if ($this->file_exists($path)) {
531
-					$file = $this->getDriveFile($path);
532
-					$this->client->setDefer($useChunking);
533
-					$request = $this->service->files->update($file->getId(), $file, $params);
534
-				} else {
535
-					$file = new \Google_Service_Drive_DriveFile();
536
-					$file->setTitle(basename($path));
537
-					$file->setMimeType($mimetype);
538
-					$parent = new \Google_Service_Drive_ParentReference();
539
-					$parent->setId($parentFolder->getId());
540
-					$file->setParents(array($parent));
541
-					$this->client->setDefer($useChunking);
542
-					$request = $this->service->files->insert($file, $params);
543
-				}
544
-
545
-				if ($useChunking) {
546
-					// Create a media file upload to represent our upload process.
547
-					$media = new \Google_Http_MediaFileUpload(
548
-						$this->client,
549
-						$request,
550
-						'text/plain',
551
-						null,
552
-						true,
553
-						$chunkSizeBytes
554
-					);
555
-					$media->setFileSize($size);
556
-
557
-					// Upload the various chunks. $status will be false until the process is
558
-					// complete.
559
-					$status = false;
560
-					$handle = fopen($tmpFile, 'rb');
561
-					while (!$status && !feof($handle)) {
562
-						$chunk = fread($handle, $chunkSizeBytes);
563
-						$status = $media->nextChunk($chunk);
564
-					}
565
-
566
-					// The final value of $status will be the data from the API for the object
567
-					// that has been uploaded.
568
-					$result = false;
569
-					if ($status !== false) {
570
-						$result = $status;
571
-					}
572
-
573
-					fclose($handle);
574
-				} else {
575
-					$result = $request;
576
-				}
577
-
578
-				// Reset to the client to execute requests immediately in the future.
579
-				$this->client->setDefer(false);
580
-
581
-				if ($result) {
582
-					$this->setDriveFile($path, $result);
583
-				}
584
-			}
585
-			unlink($tmpFile);
586
-		}
587
-	}
588
-
589
-	public function getMimeType($path) {
590
-		$file = $this->getDriveFile($path);
591
-		if ($file) {
592
-			$mimetype = $file->getMimeType();
593
-			// Convert Google Doc mimetypes, choosing Open Document formats for download
594
-			if ($mimetype === self::FOLDER) {
595
-				return 'httpd/unix-directory';
596
-			} else if ($mimetype === self::DOCUMENT) {
597
-				return 'application/vnd.oasis.opendocument.text';
598
-			} else if ($mimetype === self::SPREADSHEET) {
599
-				return 'application/x-vnd.oasis.opendocument.spreadsheet';
600
-			} else if ($mimetype === self::DRAWING) {
601
-				return 'image/jpeg';
602
-			} else if ($mimetype === self::PRESENTATION) {
603
-				// Download as .odp is not available
604
-				return 'application/pdf';
605
-			} else {
606
-				// use extension-based detection, could be an encrypted file
607
-				return parent::getMimeType($path);
608
-			}
609
-		} else {
610
-			return false;
611
-		}
612
-	}
613
-
614
-	public function free_space($path) {
615
-		$about = $this->service->about->get();
616
-		return $about->getQuotaBytesTotal() - $about->getQuotaBytesUsed();
617
-	}
618
-
619
-	public function touch($path, $mtime = null) {
620
-		$file = $this->getDriveFile($path);
621
-		$result = false;
622
-		if ($file) {
623
-			if (isset($mtime)) {
624
-				// This is just RFC3339, but frustratingly, GDrive's API *requires*
625
-				// the fractions portion be present, while no handy PHP constant
626
-				// for RFC3339 or ISO8601 includes it. So we do it ourselves.
627
-				$file->setModifiedDate(date('Y-m-d\TH:i:s.uP', $mtime));
628
-				$result = $this->service->files->patch($file->getId(), $file, array(
629
-					'setModifiedDate' => true,
630
-				));
631
-			} else {
632
-				$result = $this->service->files->touch($file->getId());
633
-			}
634
-		} else {
635
-			$parentFolder = $this->getDriveFile(dirname($path));
636
-			if ($parentFolder) {
637
-				$file = new \Google_Service_Drive_DriveFile();
638
-				$file->setTitle(basename($path));
639
-				$parent = new \Google_Service_Drive_ParentReference();
640
-				$parent->setId($parentFolder->getId());
641
-				$file->setParents(array($parent));
642
-				$result = $this->service->files->insert($file);
643
-			}
644
-		}
645
-		if ($result) {
646
-			$this->setDriveFile($path, $result);
647
-		}
648
-		return (bool)$result;
649
-	}
650
-
651
-	public function test() {
652
-		if ($this->free_space('')) {
653
-			return true;
654
-		}
655
-		return false;
656
-	}
657
-
658
-	public function hasUpdated($path, $time) {
659
-		$appConfig = \OC::$server->getAppConfig();
660
-		if ($this->is_file($path)) {
661
-			return parent::hasUpdated($path, $time);
662
-		} else {
663
-			// Google Drive doesn't change modified times of folders when files inside are updated
664
-			// Instead we use the Changes API to see if folders have been updated, and it's a pain
665
-			$folder = $this->getDriveFile($path);
666
-			if ($folder) {
667
-				$result = false;
668
-				$folderId = $folder->getId();
669
-				$startChangeId = $appConfig->getValue('files_external', $this->getId().'cId');
670
-				$params = array(
671
-					'includeDeleted' => true,
672
-					'includeSubscribed' => true,
673
-				);
674
-				if (isset($startChangeId)) {
675
-					$startChangeId = (int)$startChangeId;
676
-					$largestChangeId = $startChangeId;
677
-					$params['startChangeId'] = $startChangeId + 1;
678
-				} else {
679
-					$largestChangeId = 0;
680
-				}
681
-				$pageToken = true;
682
-				while ($pageToken) {
683
-					if ($pageToken !== true) {
684
-						$params['pageToken'] = $pageToken;
685
-					}
686
-					$changes = $this->service->changes->listChanges($params);
687
-					if ($largestChangeId === 0 || $largestChangeId === $startChangeId) {
688
-						$largestChangeId = $changes->getLargestChangeId();
689
-					}
690
-					if (isset($startChangeId)) {
691
-						// Check if a file in this folder has been updated
692
-						// There is no way to filter by folder at the API level...
693
-						foreach ($changes->getItems() as $change) {
694
-							$file = $change->getFile();
695
-							if ($file) {
696
-								foreach ($file->getParents() as $parent) {
697
-									if ($parent->getId() === $folderId) {
698
-										$result = true;
699
-									// Check if there are changes in different folders
700
-									} else if ($change->getId() <= $largestChangeId) {
701
-										// Decrement id so this change is fetched when called again
702
-										$largestChangeId = $change->getId();
703
-										$largestChangeId--;
704
-									}
705
-								}
706
-							}
707
-						}
708
-						$pageToken = $changes->getNextPageToken();
709
-					} else {
710
-						// Assuming the initial scan just occurred and changes are negligible
711
-						break;
712
-					}
713
-				}
714
-				$appConfig->setValue('files_external', $this->getId().'cId', $largestChangeId);
715
-				return $result;
716
-			}
717
-		}
718
-		return false;
719
-	}
720
-
721
-	/**
722
-	 * check if curl is installed
723
-	 */
724
-	public static function checkDependencies() {
725
-		return true;
726
-	}
48
+    private $client;
49
+    private $id;
50
+    private $service;
51
+    private $driveFiles;
52
+
53
+    private static $tempFiles = array();
54
+
55
+    // Google Doc mimetypes
56
+    const FOLDER = 'application/vnd.google-apps.folder';
57
+    const DOCUMENT = 'application/vnd.google-apps.document';
58
+    const SPREADSHEET = 'application/vnd.google-apps.spreadsheet';
59
+    const DRAWING = 'application/vnd.google-apps.drawing';
60
+    const PRESENTATION = 'application/vnd.google-apps.presentation';
61
+    const MAP = 'application/vnd.google-apps.map';
62
+
63
+    public function __construct($params) {
64
+        if (isset($params['configured']) && $params['configured'] === 'true'
65
+            && isset($params['client_id']) && isset($params['client_secret'])
66
+            && isset($params['token'])
67
+        ) {
68
+            $this->client = new \Google_Client();
69
+            $this->client->setClientId($params['client_id']);
70
+            $this->client->setClientSecret($params['client_secret']);
71
+            $this->client->setScopes(array('https://www.googleapis.com/auth/drive'));
72
+            $this->client->setAccessToken($params['token']);
73
+            // if curl isn't available we're likely to run into
74
+            // https://github.com/google/google-api-php-client/issues/59
75
+            // - disable gzip to avoid it.
76
+            if (!function_exists('curl_version') || !function_exists('curl_exec')) {
77
+                $this->client->setClassConfig("Google_Http_Request", "disable_gzip", true);
78
+            }
79
+            // note: API connection is lazy
80
+            $this->service = new \Google_Service_Drive($this->client);
81
+            $token = json_decode($params['token'], true);
82
+            $this->id = 'google::'.substr($params['client_id'], 0, 30).$token['created'];
83
+        } else {
84
+            throw new \Exception('Creating Google storage failed');
85
+        }
86
+    }
87
+
88
+    public function getId() {
89
+        return $this->id;
90
+    }
91
+
92
+    /**
93
+     * Get the Google_Service_Drive_DriveFile object for the specified path.
94
+     * Returns false on failure.
95
+     * @param string $path
96
+     * @return \Google_Service_Drive_DriveFile|false
97
+     */
98
+    private function getDriveFile($path) {
99
+        // Remove leading and trailing slashes
100
+        $path = trim($path, '/');
101
+        if ($path === '.') {
102
+            $path = '';
103
+        }
104
+        if (isset($this->driveFiles[$path])) {
105
+            return $this->driveFiles[$path];
106
+        } else if ($path === '') {
107
+            $root = $this->service->files->get('root');
108
+            $this->driveFiles[$path] = $root;
109
+            return $root;
110
+        } else {
111
+            // Google Drive SDK does not have methods for retrieving files by path
112
+            // Instead we must find the id of the parent folder of the file
113
+            $parentId = $this->getDriveFile('')->getId();
114
+            $folderNames = explode('/', $path);
115
+            $path = '';
116
+            // Loop through each folder of this path to get to the file
117
+            foreach ($folderNames as $name) {
118
+                // Reconstruct path from beginning
119
+                if ($path === '') {
120
+                    $path .= $name;
121
+                } else {
122
+                    $path .= '/'.$name;
123
+                }
124
+                if (isset($this->driveFiles[$path])) {
125
+                    $parentId = $this->driveFiles[$path]->getId();
126
+                } else {
127
+                    $q = "title='" . str_replace("'","\\'", $name) . "' and '" . str_replace("'","\\'", $parentId) . "' in parents and trashed = false";
128
+                    $result = $this->service->files->listFiles(array('q' => $q))->getItems();
129
+                    if (!empty($result)) {
130
+                        // Google Drive allows files with the same name, ownCloud doesn't
131
+                        if (count($result) > 1) {
132
+                            $this->onDuplicateFileDetected($path);
133
+                            return false;
134
+                        } else {
135
+                            $file = current($result);
136
+                            $this->driveFiles[$path] = $file;
137
+                            $parentId = $file->getId();
138
+                        }
139
+                    } else {
140
+                        // Google Docs have no extension in their title, so try without extension
141
+                        $pos = strrpos($path, '.');
142
+                        if ($pos !== false) {
143
+                            $pathWithoutExt = substr($path, 0, $pos);
144
+                            $file = $this->getDriveFile($pathWithoutExt);
145
+                            if ($file && $this->isGoogleDocFile($file)) {
146
+                                // Switch cached Google_Service_Drive_DriveFile to the correct index
147
+                                unset($this->driveFiles[$pathWithoutExt]);
148
+                                $this->driveFiles[$path] = $file;
149
+                                $parentId = $file->getId();
150
+                            } else {
151
+                                return false;
152
+                            }
153
+                        } else {
154
+                            return false;
155
+                        }
156
+                    }
157
+                }
158
+            }
159
+            return $this->driveFiles[$path];
160
+        }
161
+    }
162
+
163
+    /**
164
+     * Set the Google_Service_Drive_DriveFile object in the cache
165
+     * @param string $path
166
+     * @param \Google_Service_Drive_DriveFile|false $file
167
+     */
168
+    private function setDriveFile($path, $file) {
169
+        $path = trim($path, '/');
170
+        $this->driveFiles[$path] = $file;
171
+        if ($file === false) {
172
+            // Remove all children
173
+            $len = strlen($path);
174
+            foreach ($this->driveFiles as $key => $file) {
175
+                if (substr($key, 0, $len) === $path) {
176
+                    unset($this->driveFiles[$key]);
177
+                }
178
+            }
179
+        }
180
+    }
181
+
182
+    /**
183
+     * Write a log message to inform about duplicate file names
184
+     * @param string $path
185
+     */
186
+    private function onDuplicateFileDetected($path) {
187
+        $about = $this->service->about->get();
188
+        $user = $about->getName();
189
+        \OCP\Util::writeLog('files_external',
190
+            'Ignoring duplicate file name: '.$path.' on Google Drive for Google user: '.$user,
191
+            \OCP\Util::INFO
192
+        );
193
+    }
194
+
195
+    /**
196
+     * Generate file extension for a Google Doc, choosing Open Document formats for download
197
+     * @param string $mimetype
198
+     * @return string
199
+     */
200
+    private function getGoogleDocExtension($mimetype) {
201
+        if ($mimetype === self::DOCUMENT) {
202
+            return 'odt';
203
+        } else if ($mimetype === self::SPREADSHEET) {
204
+            return 'ods';
205
+        } else if ($mimetype === self::DRAWING) {
206
+            return 'jpg';
207
+        } else if ($mimetype === self::PRESENTATION) {
208
+            // Download as .odp is not available
209
+            return 'pdf';
210
+        } else {
211
+            return '';
212
+        }
213
+    }
214
+
215
+    /**
216
+     * Returns whether the given drive file is a Google Doc file
217
+     *
218
+     * @param \Google_Service_Drive_DriveFile
219
+     *
220
+     * @return true if the file is a Google Doc file, false otherwise
221
+     */
222
+    private function isGoogleDocFile($file) {
223
+        return $this->getGoogleDocExtension($file->getMimeType()) !== '';
224
+    }
225
+
226
+    public function mkdir($path) {
227
+        if (!$this->is_dir($path)) {
228
+            $parentFolder = $this->getDriveFile(dirname($path));
229
+            if ($parentFolder) {
230
+                $folder = new \Google_Service_Drive_DriveFile();
231
+                $folder->setTitle(basename($path));
232
+                $folder->setMimeType(self::FOLDER);
233
+                $parent = new \Google_Service_Drive_ParentReference();
234
+                $parent->setId($parentFolder->getId());
235
+                $folder->setParents(array($parent));
236
+                $result = $this->service->files->insert($folder);
237
+                if ($result) {
238
+                    $this->setDriveFile($path, $result);
239
+                }
240
+                return (bool)$result;
241
+            }
242
+        }
243
+        return false;
244
+    }
245
+
246
+    public function rmdir($path) {
247
+        if (!$this->isDeletable($path)) {
248
+            return false;
249
+        }
250
+        if (trim($path, '/') === '') {
251
+            $dir = $this->opendir($path);
252
+            if(is_resource($dir)) {
253
+                while (($file = readdir($dir)) !== false) {
254
+                    if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
255
+                        if (!$this->unlink($path.'/'.$file)) {
256
+                            return false;
257
+                        }
258
+                    }
259
+                }
260
+                closedir($dir);
261
+            }
262
+            $this->driveFiles = array();
263
+            return true;
264
+        } else {
265
+            return $this->unlink($path);
266
+        }
267
+    }
268
+
269
+    public function opendir($path) {
270
+        $folder = $this->getDriveFile($path);
271
+        if ($folder) {
272
+            $files = array();
273
+            $duplicates = array();
274
+            $pageToken = true;
275
+            while ($pageToken) {
276
+                $params = array();
277
+                if ($pageToken !== true) {
278
+                    $params['pageToken'] = $pageToken;
279
+                }
280
+                $params['q'] = "'" . str_replace("'","\\'", $folder->getId()) . "' in parents and trashed = false";
281
+                $children = $this->service->files->listFiles($params);
282
+                foreach ($children->getItems() as $child) {
283
+                    $name = $child->getTitle();
284
+                    // Check if this is a Google Doc i.e. no extension in name
285
+                    $extension = $child->getFileExtension();
286
+                    if (empty($extension)) {
287
+                        if ($child->getMimeType() === self::MAP) {
288
+                            continue; // No method known to transfer map files, ignore it
289
+                        } else if ($child->getMimeType() !== self::FOLDER) {
290
+                            $name .= '.'.$this->getGoogleDocExtension($child->getMimeType());
291
+                        }
292
+                    }
293
+                    if ($path === '') {
294
+                        $filepath = $name;
295
+                    } else {
296
+                        $filepath = $path.'/'.$name;
297
+                    }
298
+                    // Google Drive allows files with the same name, ownCloud doesn't
299
+                    // Prevent opendir() from returning any duplicate files
300
+                    $key = array_search($name, $files);
301
+                    if ($key !== false || isset($duplicates[$filepath])) {
302
+                        if (!isset($duplicates[$filepath])) {
303
+                            $duplicates[$filepath] = true;
304
+                            $this->setDriveFile($filepath, false);
305
+                            unset($files[$key]);
306
+                            $this->onDuplicateFileDetected($filepath);
307
+                        }
308
+                    } else {
309
+                        // Cache the Google_Service_Drive_DriveFile for future use
310
+                        $this->setDriveFile($filepath, $child);
311
+                        $files[] = $name;
312
+                    }
313
+                }
314
+                $pageToken = $children->getNextPageToken();
315
+            }
316
+            return IteratorDirectory::wrap($files);
317
+        } else {
318
+            return false;
319
+        }
320
+    }
321
+
322
+    public function stat($path) {
323
+        $file = $this->getDriveFile($path);
324
+        if ($file) {
325
+            $stat = array();
326
+            if ($this->filetype($path) === 'dir') {
327
+                $stat['size'] = 0;
328
+            } else {
329
+                // Check if this is a Google Doc
330
+                if ($this->isGoogleDocFile($file)) {
331
+                    // Return unknown file size
332
+                    $stat['size'] = \OCP\Files\FileInfo::SPACE_UNKNOWN;
333
+                } else {
334
+                    $stat['size'] = $file->getFileSize();
335
+                }
336
+            }
337
+            $stat['atime'] = strtotime($file->getLastViewedByMeDate());
338
+            $stat['mtime'] = strtotime($file->getModifiedDate());
339
+            $stat['ctime'] = strtotime($file->getCreatedDate());
340
+            return $stat;
341
+        } else {
342
+            return false;
343
+        }
344
+    }
345
+
346
+    public function filetype($path) {
347
+        if ($path === '') {
348
+            return 'dir';
349
+        } else {
350
+            $file = $this->getDriveFile($path);
351
+            if ($file) {
352
+                if ($file->getMimeType() === self::FOLDER) {
353
+                    return 'dir';
354
+                } else {
355
+                    return 'file';
356
+                }
357
+            } else {
358
+                return false;
359
+            }
360
+        }
361
+    }
362
+
363
+    public function isUpdatable($path) {
364
+        $file = $this->getDriveFile($path);
365
+        if ($file) {
366
+            return $file->getEditable();
367
+        } else {
368
+            return false;
369
+        }
370
+    }
371
+
372
+    public function file_exists($path) {
373
+        return (bool)$this->getDriveFile($path);
374
+    }
375
+
376
+    public function unlink($path) {
377
+        $file = $this->getDriveFile($path);
378
+        if ($file) {
379
+            $result = $this->service->files->trash($file->getId());
380
+            if ($result) {
381
+                $this->setDriveFile($path, false);
382
+            }
383
+            return (bool)$result;
384
+        } else {
385
+            return false;
386
+        }
387
+    }
388
+
389
+    public function rename($path1, $path2) {
390
+        $file = $this->getDriveFile($path1);
391
+        if ($file) {
392
+            $newFile = $this->getDriveFile($path2);
393
+            if (dirname($path1) === dirname($path2)) {
394
+                if ($newFile) {
395
+                    // rename to the name of the target file, could be an office file without extension
396
+                    $file->setTitle($newFile->getTitle());
397
+                } else {
398
+                    $file->setTitle(basename(($path2)));
399
+                }
400
+            } else {
401
+                // Change file parent
402
+                $parentFolder2 = $this->getDriveFile(dirname($path2));
403
+                if ($parentFolder2) {
404
+                    $parent = new \Google_Service_Drive_ParentReference();
405
+                    $parent->setId($parentFolder2->getId());
406
+                    $file->setParents(array($parent));
407
+                } else {
408
+                    return false;
409
+                }
410
+            }
411
+            // We need to get the object for the existing file with the same
412
+            // name (if there is one) before we do the patch. If oldfile
413
+            // exists and is a directory we have to delete it before we
414
+            // do the rename too.
415
+            $oldfile = $this->getDriveFile($path2);
416
+            if ($oldfile && $this->is_dir($path2)) {
417
+                $this->rmdir($path2);
418
+                $oldfile = false;
419
+            }
420
+            $result = $this->service->files->patch($file->getId(), $file);
421
+            if ($result) {
422
+                $this->setDriveFile($path1, false);
423
+                $this->setDriveFile($path2, $result);
424
+                if ($oldfile && $newFile) {
425
+                    // only delete if they have a different id (same id can happen for part files)
426
+                    if ($newFile->getId() !== $oldfile->getId()) {
427
+                        $this->service->files->delete($oldfile->getId());
428
+                    }
429
+                }
430
+            }
431
+            return (bool)$result;
432
+        } else {
433
+            return false;
434
+        }
435
+    }
436
+
437
+    public function fopen($path, $mode) {
438
+        $pos = strrpos($path, '.');
439
+        if ($pos !== false) {
440
+            $ext = substr($path, $pos);
441
+        } else {
442
+            $ext = '';
443
+        }
444
+        switch ($mode) {
445
+            case 'r':
446
+            case 'rb':
447
+                $file = $this->getDriveFile($path);
448
+                if ($file) {
449
+                    $exportLinks = $file->getExportLinks();
450
+                    $mimetype = $this->getMimeType($path);
451
+                    $downloadUrl = null;
452
+                    if ($exportLinks && isset($exportLinks[$mimetype])) {
453
+                        $downloadUrl = $exportLinks[$mimetype];
454
+                    } else {
455
+                        $downloadUrl = $file->getDownloadUrl();
456
+                    }
457
+                    if (isset($downloadUrl)) {
458
+                        $request = new \Google_Http_Request($downloadUrl, 'GET', null, null);
459
+                        $httpRequest = $this->client->getAuth()->sign($request);
460
+                        // the library's service doesn't support streaming, so we use Guzzle instead
461
+                        $client = \OC::$server->getHTTPClientService()->newClient();
462
+                        try {
463
+                            $response = $client->get($downloadUrl, [
464
+                                'headers' => $httpRequest->getRequestHeaders(),
465
+                                'stream' => true,
466
+                                'verify' => realpath(__DIR__ . '/../../../3rdparty/google-api-php-client/src/Google/IO/cacerts.pem'),
467
+                            ]);
468
+                        } catch (RequestException $e) {
469
+                            if(!is_null($e->getResponse())) {
470
+                                if ($e->getResponse()->getStatusCode() === 404) {
471
+                                    return false;
472
+                                } else {
473
+                                    throw $e;
474
+                                }
475
+                            } else {
476
+                                throw $e;
477
+                            }
478
+                        }
479
+
480
+                        $handle = $response->getBody();
481
+                        return RetryWrapper::wrap($handle);
482
+                    }
483
+                }
484
+                return false;
485
+            case 'w':
486
+            case 'wb':
487
+            case 'a':
488
+            case 'ab':
489
+            case 'r+':
490
+            case 'w+':
491
+            case 'wb+':
492
+            case 'a+':
493
+            case 'x':
494
+            case 'x+':
495
+            case 'c':
496
+            case 'c+':
497
+                $tmpFile = \OCP\Files::tmpFile($ext);
498
+                \OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
499
+                if ($this->file_exists($path)) {
500
+                    $source = $this->fopen($path, 'rb');
501
+                    file_put_contents($tmpFile, $source);
502
+                }
503
+                self::$tempFiles[$tmpFile] = $path;
504
+                return fopen('close://'.$tmpFile, $mode);
505
+        }
506
+    }
507
+
508
+    public function writeBack($tmpFile) {
509
+        if (isset(self::$tempFiles[$tmpFile])) {
510
+            $path = self::$tempFiles[$tmpFile];
511
+            $parentFolder = $this->getDriveFile(dirname($path));
512
+            if ($parentFolder) {
513
+                $mimetype = \OC::$server->getMimeTypeDetector()->detect($tmpFile);
514
+                $params = array(
515
+                    'mimeType' => $mimetype,
516
+                    'uploadType' => 'media'
517
+                );
518
+                $result = false;
519
+
520
+                $chunkSizeBytes = 10 * 1024 * 1024;
521
+
522
+                $useChunking = false;
523
+                $size = filesize($tmpFile);
524
+                if ($size > $chunkSizeBytes) {
525
+                    $useChunking = true;
526
+                } else {
527
+                    $params['data'] = file_get_contents($tmpFile);
528
+                }
529
+
530
+                if ($this->file_exists($path)) {
531
+                    $file = $this->getDriveFile($path);
532
+                    $this->client->setDefer($useChunking);
533
+                    $request = $this->service->files->update($file->getId(), $file, $params);
534
+                } else {
535
+                    $file = new \Google_Service_Drive_DriveFile();
536
+                    $file->setTitle(basename($path));
537
+                    $file->setMimeType($mimetype);
538
+                    $parent = new \Google_Service_Drive_ParentReference();
539
+                    $parent->setId($parentFolder->getId());
540
+                    $file->setParents(array($parent));
541
+                    $this->client->setDefer($useChunking);
542
+                    $request = $this->service->files->insert($file, $params);
543
+                }
544
+
545
+                if ($useChunking) {
546
+                    // Create a media file upload to represent our upload process.
547
+                    $media = new \Google_Http_MediaFileUpload(
548
+                        $this->client,
549
+                        $request,
550
+                        'text/plain',
551
+                        null,
552
+                        true,
553
+                        $chunkSizeBytes
554
+                    );
555
+                    $media->setFileSize($size);
556
+
557
+                    // Upload the various chunks. $status will be false until the process is
558
+                    // complete.
559
+                    $status = false;
560
+                    $handle = fopen($tmpFile, 'rb');
561
+                    while (!$status && !feof($handle)) {
562
+                        $chunk = fread($handle, $chunkSizeBytes);
563
+                        $status = $media->nextChunk($chunk);
564
+                    }
565
+
566
+                    // The final value of $status will be the data from the API for the object
567
+                    // that has been uploaded.
568
+                    $result = false;
569
+                    if ($status !== false) {
570
+                        $result = $status;
571
+                    }
572
+
573
+                    fclose($handle);
574
+                } else {
575
+                    $result = $request;
576
+                }
577
+
578
+                // Reset to the client to execute requests immediately in the future.
579
+                $this->client->setDefer(false);
580
+
581
+                if ($result) {
582
+                    $this->setDriveFile($path, $result);
583
+                }
584
+            }
585
+            unlink($tmpFile);
586
+        }
587
+    }
588
+
589
+    public function getMimeType($path) {
590
+        $file = $this->getDriveFile($path);
591
+        if ($file) {
592
+            $mimetype = $file->getMimeType();
593
+            // Convert Google Doc mimetypes, choosing Open Document formats for download
594
+            if ($mimetype === self::FOLDER) {
595
+                return 'httpd/unix-directory';
596
+            } else if ($mimetype === self::DOCUMENT) {
597
+                return 'application/vnd.oasis.opendocument.text';
598
+            } else if ($mimetype === self::SPREADSHEET) {
599
+                return 'application/x-vnd.oasis.opendocument.spreadsheet';
600
+            } else if ($mimetype === self::DRAWING) {
601
+                return 'image/jpeg';
602
+            } else if ($mimetype === self::PRESENTATION) {
603
+                // Download as .odp is not available
604
+                return 'application/pdf';
605
+            } else {
606
+                // use extension-based detection, could be an encrypted file
607
+                return parent::getMimeType($path);
608
+            }
609
+        } else {
610
+            return false;
611
+        }
612
+    }
613
+
614
+    public function free_space($path) {
615
+        $about = $this->service->about->get();
616
+        return $about->getQuotaBytesTotal() - $about->getQuotaBytesUsed();
617
+    }
618
+
619
+    public function touch($path, $mtime = null) {
620
+        $file = $this->getDriveFile($path);
621
+        $result = false;
622
+        if ($file) {
623
+            if (isset($mtime)) {
624
+                // This is just RFC3339, but frustratingly, GDrive's API *requires*
625
+                // the fractions portion be present, while no handy PHP constant
626
+                // for RFC3339 or ISO8601 includes it. So we do it ourselves.
627
+                $file->setModifiedDate(date('Y-m-d\TH:i:s.uP', $mtime));
628
+                $result = $this->service->files->patch($file->getId(), $file, array(
629
+                    'setModifiedDate' => true,
630
+                ));
631
+            } else {
632
+                $result = $this->service->files->touch($file->getId());
633
+            }
634
+        } else {
635
+            $parentFolder = $this->getDriveFile(dirname($path));
636
+            if ($parentFolder) {
637
+                $file = new \Google_Service_Drive_DriveFile();
638
+                $file->setTitle(basename($path));
639
+                $parent = new \Google_Service_Drive_ParentReference();
640
+                $parent->setId($parentFolder->getId());
641
+                $file->setParents(array($parent));
642
+                $result = $this->service->files->insert($file);
643
+            }
644
+        }
645
+        if ($result) {
646
+            $this->setDriveFile($path, $result);
647
+        }
648
+        return (bool)$result;
649
+    }
650
+
651
+    public function test() {
652
+        if ($this->free_space('')) {
653
+            return true;
654
+        }
655
+        return false;
656
+    }
657
+
658
+    public function hasUpdated($path, $time) {
659
+        $appConfig = \OC::$server->getAppConfig();
660
+        if ($this->is_file($path)) {
661
+            return parent::hasUpdated($path, $time);
662
+        } else {
663
+            // Google Drive doesn't change modified times of folders when files inside are updated
664
+            // Instead we use the Changes API to see if folders have been updated, and it's a pain
665
+            $folder = $this->getDriveFile($path);
666
+            if ($folder) {
667
+                $result = false;
668
+                $folderId = $folder->getId();
669
+                $startChangeId = $appConfig->getValue('files_external', $this->getId().'cId');
670
+                $params = array(
671
+                    'includeDeleted' => true,
672
+                    'includeSubscribed' => true,
673
+                );
674
+                if (isset($startChangeId)) {
675
+                    $startChangeId = (int)$startChangeId;
676
+                    $largestChangeId = $startChangeId;
677
+                    $params['startChangeId'] = $startChangeId + 1;
678
+                } else {
679
+                    $largestChangeId = 0;
680
+                }
681
+                $pageToken = true;
682
+                while ($pageToken) {
683
+                    if ($pageToken !== true) {
684
+                        $params['pageToken'] = $pageToken;
685
+                    }
686
+                    $changes = $this->service->changes->listChanges($params);
687
+                    if ($largestChangeId === 0 || $largestChangeId === $startChangeId) {
688
+                        $largestChangeId = $changes->getLargestChangeId();
689
+                    }
690
+                    if (isset($startChangeId)) {
691
+                        // Check if a file in this folder has been updated
692
+                        // There is no way to filter by folder at the API level...
693
+                        foreach ($changes->getItems() as $change) {
694
+                            $file = $change->getFile();
695
+                            if ($file) {
696
+                                foreach ($file->getParents() as $parent) {
697
+                                    if ($parent->getId() === $folderId) {
698
+                                        $result = true;
699
+                                    // Check if there are changes in different folders
700
+                                    } else if ($change->getId() <= $largestChangeId) {
701
+                                        // Decrement id so this change is fetched when called again
702
+                                        $largestChangeId = $change->getId();
703
+                                        $largestChangeId--;
704
+                                    }
705
+                                }
706
+                            }
707
+                        }
708
+                        $pageToken = $changes->getNextPageToken();
709
+                    } else {
710
+                        // Assuming the initial scan just occurred and changes are negligible
711
+                        break;
712
+                    }
713
+                }
714
+                $appConfig->setValue('files_external', $this->getId().'cId', $largestChangeId);
715
+                return $result;
716
+            }
717
+        }
718
+        return false;
719
+    }
720
+
721
+    /**
722
+     * check if curl is installed
723
+     */
724
+    public static function checkDependencies() {
725
+        return true;
726
+    }
727 727
 
728 728
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -124,7 +124,7 @@  discard block
 block discarded – undo
124 124
 				if (isset($this->driveFiles[$path])) {
125 125
 					$parentId = $this->driveFiles[$path]->getId();
126 126
 				} else {
127
-					$q = "title='" . str_replace("'","\\'", $name) . "' and '" . str_replace("'","\\'", $parentId) . "' in parents and trashed = false";
127
+					$q = "title='".str_replace("'", "\\'", $name)."' and '".str_replace("'", "\\'", $parentId)."' in parents and trashed = false";
128 128
 					$result = $this->service->files->listFiles(array('q' => $q))->getItems();
129 129
 					if (!empty($result)) {
130 130
 						// Google Drive allows files with the same name, ownCloud doesn't
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
 				if ($result) {
238 238
 					$this->setDriveFile($path, $result);
239 239
 				}
240
-				return (bool)$result;
240
+				return (bool) $result;
241 241
 			}
242 242
 		}
243 243
 		return false;
@@ -249,7 +249,7 @@  discard block
 block discarded – undo
249 249
 		}
250 250
 		if (trim($path, '/') === '') {
251 251
 			$dir = $this->opendir($path);
252
-			if(is_resource($dir)) {
252
+			if (is_resource($dir)) {
253 253
 				while (($file = readdir($dir)) !== false) {
254 254
 					if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
255 255
 						if (!$this->unlink($path.'/'.$file)) {
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
 				if ($pageToken !== true) {
278 278
 					$params['pageToken'] = $pageToken;
279 279
 				}
280
-				$params['q'] = "'" . str_replace("'","\\'", $folder->getId()) . "' in parents and trashed = false";
280
+				$params['q'] = "'".str_replace("'", "\\'", $folder->getId())."' in parents and trashed = false";
281 281
 				$children = $this->service->files->listFiles($params);
282 282
 				foreach ($children->getItems() as $child) {
283 283
 					$name = $child->getTitle();
@@ -370,7 +370,7 @@  discard block
 block discarded – undo
370 370
 	}
371 371
 
372 372
 	public function file_exists($path) {
373
-		return (bool)$this->getDriveFile($path);
373
+		return (bool) $this->getDriveFile($path);
374 374
 	}
375 375
 
376 376
 	public function unlink($path) {
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
 			if ($result) {
381 381
 				$this->setDriveFile($path, false);
382 382
 			}
383
-			return (bool)$result;
383
+			return (bool) $result;
384 384
 		} else {
385 385
 			return false;
386 386
 		}
@@ -428,7 +428,7 @@  discard block
 block discarded – undo
428 428
 					}
429 429
 				}
430 430
 			}
431
-			return (bool)$result;
431
+			return (bool) $result;
432 432
 		} else {
433 433
 			return false;
434 434
 		}
@@ -463,10 +463,10 @@  discard block
 block discarded – undo
463 463
 							$response = $client->get($downloadUrl, [
464 464
 								'headers' => $httpRequest->getRequestHeaders(),
465 465
 								'stream' => true,
466
-								'verify' => realpath(__DIR__ . '/../../../3rdparty/google-api-php-client/src/Google/IO/cacerts.pem'),
466
+								'verify' => realpath(__DIR__.'/../../../3rdparty/google-api-php-client/src/Google/IO/cacerts.pem'),
467 467
 							]);
468 468
 						} catch (RequestException $e) {
469
-							if(!is_null($e->getResponse())) {
469
+							if (!is_null($e->getResponse())) {
470 470
 								if ($e->getResponse()->getStatusCode() === 404) {
471 471
 									return false;
472 472
 								} else {
@@ -645,7 +645,7 @@  discard block
 block discarded – undo
645 645
 		if ($result) {
646 646
 			$this->setDriveFile($path, $result);
647 647
 		}
648
-		return (bool)$result;
648
+		return (bool) $result;
649 649
 	}
650 650
 
651 651
 	public function test() {
@@ -672,7 +672,7 @@  discard block
 block discarded – undo
672 672
 					'includeSubscribed' => true,
673 673
 				);
674 674
 				if (isset($startChangeId)) {
675
-					$startChangeId = (int)$startChangeId;
675
+					$startChangeId = (int) $startChangeId;
676 676
 					$largestChangeId = $startChangeId;
677 677
 					$params['startChangeId'] = $startChangeId + 1;
678 678
 				} else {
Please login to merge, or discard this patch.
lib/private/Files/View.php 3 patches
Doc Comments   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -200,7 +200,7 @@  discard block
 block discarded – undo
200 200
 	 * and does not take the chroot into account )
201 201
 	 *
202 202
 	 * @param string $path
203
-	 * @return \OCP\Files\Mount\IMountPoint
203
+	 * @return Mount\MountPoint|null
204 204
 	 */
205 205
 	public function getMount($path) {
206 206
 		return Filesystem::getMountManager()->find($this->getAbsolutePath($path));
@@ -963,7 +963,7 @@  discard block
 block discarded – undo
963 963
 
964 964
 	/**
965 965
 	 * @param string $path
966
-	 * @return bool|string
966
+	 * @return string|false
967 967
 	 * @throws \OCP\Files\InvalidPathException
968 968
 	 */
969 969
 	public function toTmpFile($path) {
@@ -1078,7 +1078,7 @@  discard block
 block discarded – undo
1078 1078
 	 * @param string $path
1079 1079
 	 * @param array $hooks (optional)
1080 1080
 	 * @param mixed $extraParam (optional)
1081
-	 * @return mixed
1081
+	 * @return string
1082 1082
 	 * @throws \Exception
1083 1083
 	 *
1084 1084
 	 * This method takes requests for basic filesystem functions (e.g. reading & writing
@@ -2086,7 +2086,7 @@  discard block
 block discarded – undo
2086 2086
 
2087 2087
 	/**
2088 2088
 	 * @param string $filename
2089
-	 * @return array
2089
+	 * @return string[]
2090 2090
 	 * @throws \OC\User\NoUserException
2091 2091
 	 * @throws NotFoundException
2092 2092
 	 */
Please login to merge, or discard this patch.
Indentation   +2050 added lines, -2050 removed lines patch added patch discarded remove patch
@@ -81,2058 +81,2058 @@
 block discarded – undo
81 81
  * \OC\Files\Storage\Storage object
82 82
  */
83 83
 class View {
84
-	/** @var string */
85
-	private $fakeRoot = '';
86
-
87
-	/**
88
-	 * @var \OCP\Lock\ILockingProvider
89
-	 */
90
-	private $lockingProvider;
91
-
92
-	private $lockingEnabled;
93
-
94
-	private $updaterEnabled = true;
95
-
96
-	private $userManager;
97
-
98
-	/**
99
-	 * @param string $root
100
-	 * @throws \Exception If $root contains an invalid path
101
-	 */
102
-	public function __construct($root = '') {
103
-		if (is_null($root)) {
104
-			throw new \InvalidArgumentException('Root can\'t be null');
105
-		}
106
-		if (!Filesystem::isValidPath($root)) {
107
-			throw new \Exception();
108
-		}
109
-
110
-		$this->fakeRoot = $root;
111
-		$this->lockingProvider = \OC::$server->getLockingProvider();
112
-		$this->lockingEnabled = !($this->lockingProvider instanceof \OC\Lock\NoopLockingProvider);
113
-		$this->userManager = \OC::$server->getUserManager();
114
-	}
115
-
116
-	public function getAbsolutePath($path = '/') {
117
-		if ($path === null) {
118
-			return null;
119
-		}
120
-		$this->assertPathLength($path);
121
-		if ($path === '') {
122
-			$path = '/';
123
-		}
124
-		if ($path[0] !== '/') {
125
-			$path = '/' . $path;
126
-		}
127
-		return $this->fakeRoot . $path;
128
-	}
129
-
130
-	/**
131
-	 * change the root to a fake root
132
-	 *
133
-	 * @param string $fakeRoot
134
-	 * @return boolean|null
135
-	 */
136
-	public function chroot($fakeRoot) {
137
-		if (!$fakeRoot == '') {
138
-			if ($fakeRoot[0] !== '/') {
139
-				$fakeRoot = '/' . $fakeRoot;
140
-			}
141
-		}
142
-		$this->fakeRoot = $fakeRoot;
143
-	}
144
-
145
-	/**
146
-	 * get the fake root
147
-	 *
148
-	 * @return string
149
-	 */
150
-	public function getRoot() {
151
-		return $this->fakeRoot;
152
-	}
153
-
154
-	/**
155
-	 * get path relative to the root of the view
156
-	 *
157
-	 * @param string $path
158
-	 * @return string
159
-	 */
160
-	public function getRelativePath($path) {
161
-		$this->assertPathLength($path);
162
-		if ($this->fakeRoot == '') {
163
-			return $path;
164
-		}
165
-
166
-		if (rtrim($path, '/') === rtrim($this->fakeRoot, '/')) {
167
-			return '/';
168
-		}
169
-
170
-		// missing slashes can cause wrong matches!
171
-		$root = rtrim($this->fakeRoot, '/') . '/';
172
-
173
-		if (strpos($path, $root) !== 0) {
174
-			return null;
175
-		} else {
176
-			$path = substr($path, strlen($this->fakeRoot));
177
-			if (strlen($path) === 0) {
178
-				return '/';
179
-			} else {
180
-				return $path;
181
-			}
182
-		}
183
-	}
184
-
185
-	/**
186
-	 * get the mountpoint of the storage object for a path
187
-	 * ( note: because a storage is not always mounted inside the fakeroot, the
188
-	 * returned mountpoint is relative to the absolute root of the filesystem
189
-	 * and does not take the chroot into account )
190
-	 *
191
-	 * @param string $path
192
-	 * @return string
193
-	 */
194
-	public function getMountPoint($path) {
195
-		return Filesystem::getMountPoint($this->getAbsolutePath($path));
196
-	}
197
-
198
-	/**
199
-	 * get the mountpoint of the storage object for a path
200
-	 * ( note: because a storage is not always mounted inside the fakeroot, the
201
-	 * returned mountpoint is relative to the absolute root of the filesystem
202
-	 * and does not take the chroot into account )
203
-	 *
204
-	 * @param string $path
205
-	 * @return \OCP\Files\Mount\IMountPoint
206
-	 */
207
-	public function getMount($path) {
208
-		return Filesystem::getMountManager()->find($this->getAbsolutePath($path));
209
-	}
210
-
211
-	/**
212
-	 * resolve a path to a storage and internal path
213
-	 *
214
-	 * @param string $path
215
-	 * @return array an array consisting of the storage and the internal path
216
-	 */
217
-	public function resolvePath($path) {
218
-		$a = $this->getAbsolutePath($path);
219
-		$p = Filesystem::normalizePath($a);
220
-		return Filesystem::resolvePath($p);
221
-	}
222
-
223
-	/**
224
-	 * return the path to a local version of the file
225
-	 * we need this because we can't know if a file is stored local or not from
226
-	 * outside the filestorage and for some purposes a local file is needed
227
-	 *
228
-	 * @param string $path
229
-	 * @return string
230
-	 */
231
-	public function getLocalFile($path) {
232
-		$parent = substr($path, 0, strrpos($path, '/'));
233
-		$path = $this->getAbsolutePath($path);
234
-		list($storage, $internalPath) = Filesystem::resolvePath($path);
235
-		if (Filesystem::isValidPath($parent) and $storage) {
236
-			return $storage->getLocalFile($internalPath);
237
-		} else {
238
-			return null;
239
-		}
240
-	}
241
-
242
-	/**
243
-	 * @param string $path
244
-	 * @return string
245
-	 */
246
-	public function getLocalFolder($path) {
247
-		$parent = substr($path, 0, strrpos($path, '/'));
248
-		$path = $this->getAbsolutePath($path);
249
-		list($storage, $internalPath) = Filesystem::resolvePath($path);
250
-		if (Filesystem::isValidPath($parent) and $storage) {
251
-			return $storage->getLocalFolder($internalPath);
252
-		} else {
253
-			return null;
254
-		}
255
-	}
256
-
257
-	/**
258
-	 * the following functions operate with arguments and return values identical
259
-	 * to those of their PHP built-in equivalents. Mostly they are merely wrappers
260
-	 * for \OC\Files\Storage\Storage via basicOperation().
261
-	 */
262
-	public function mkdir($path) {
263
-		return $this->basicOperation('mkdir', $path, array('create', 'write'));
264
-	}
265
-
266
-	/**
267
-	 * remove mount point
268
-	 *
269
-	 * @param \OC\Files\Mount\MoveableMount $mount
270
-	 * @param string $path relative to data/
271
-	 * @return boolean
272
-	 */
273
-	protected function removeMount($mount, $path) {
274
-		if ($mount instanceof MoveableMount) {
275
-			// cut of /user/files to get the relative path to data/user/files
276
-			$pathParts = explode('/', $path, 4);
277
-			$relPath = '/' . $pathParts[3];
278
-			$this->lockFile($relPath, ILockingProvider::LOCK_SHARED, true);
279
-			\OC_Hook::emit(
280
-				Filesystem::CLASSNAME, "umount",
281
-				array(Filesystem::signal_param_path => $relPath)
282
-			);
283
-			$this->changeLock($relPath, ILockingProvider::LOCK_EXCLUSIVE, true);
284
-			$result = $mount->removeMount();
285
-			$this->changeLock($relPath, ILockingProvider::LOCK_SHARED, true);
286
-			if ($result) {
287
-				\OC_Hook::emit(
288
-					Filesystem::CLASSNAME, "post_umount",
289
-					array(Filesystem::signal_param_path => $relPath)
290
-				);
291
-			}
292
-			$this->unlockFile($relPath, ILockingProvider::LOCK_SHARED, true);
293
-			return $result;
294
-		} else {
295
-			// do not allow deleting the storage's root / the mount point
296
-			// because for some storages it might delete the whole contents
297
-			// but isn't supposed to work that way
298
-			return false;
299
-		}
300
-	}
301
-
302
-	public function disableCacheUpdate() {
303
-		$this->updaterEnabled = false;
304
-	}
305
-
306
-	public function enableCacheUpdate() {
307
-		$this->updaterEnabled = true;
308
-	}
309
-
310
-	protected function writeUpdate(Storage $storage, $internalPath, $time = null) {
311
-		if ($this->updaterEnabled) {
312
-			if (is_null($time)) {
313
-				$time = time();
314
-			}
315
-			$storage->getUpdater()->update($internalPath, $time);
316
-		}
317
-	}
318
-
319
-	protected function removeUpdate(Storage $storage, $internalPath) {
320
-		if ($this->updaterEnabled) {
321
-			$storage->getUpdater()->remove($internalPath);
322
-		}
323
-	}
324
-
325
-	protected function renameUpdate(Storage $sourceStorage, Storage $targetStorage, $sourceInternalPath, $targetInternalPath) {
326
-		if ($this->updaterEnabled) {
327
-			$targetStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
328
-		}
329
-	}
330
-
331
-	/**
332
-	 * @param string $path
333
-	 * @return bool|mixed
334
-	 */
335
-	public function rmdir($path) {
336
-		$absolutePath = $this->getAbsolutePath($path);
337
-		$mount = Filesystem::getMountManager()->find($absolutePath);
338
-		if ($mount->getInternalPath($absolutePath) === '') {
339
-			return $this->removeMount($mount, $absolutePath);
340
-		}
341
-		if ($this->is_dir($path)) {
342
-			$result = $this->basicOperation('rmdir', $path, array('delete'));
343
-		} else {
344
-			$result = false;
345
-		}
346
-
347
-		if (!$result && !$this->file_exists($path)) { //clear ghost files from the cache on delete
348
-			$storage = $mount->getStorage();
349
-			$internalPath = $mount->getInternalPath($absolutePath);
350
-			$storage->getUpdater()->remove($internalPath);
351
-		}
352
-		return $result;
353
-	}
354
-
355
-	/**
356
-	 * @param string $path
357
-	 * @return resource
358
-	 */
359
-	public function opendir($path) {
360
-		return $this->basicOperation('opendir', $path, array('read'));
361
-	}
362
-
363
-	/**
364
-	 * @param $handle
365
-	 * @return mixed
366
-	 */
367
-	public function readdir($handle) {
368
-		$fsLocal = new Storage\Local(array('datadir' => '/'));
369
-		return $fsLocal->readdir($handle);
370
-	}
371
-
372
-	/**
373
-	 * @param string $path
374
-	 * @return bool|mixed
375
-	 */
376
-	public function is_dir($path) {
377
-		if ($path == '/') {
378
-			return true;
379
-		}
380
-		return $this->basicOperation('is_dir', $path);
381
-	}
382
-
383
-	/**
384
-	 * @param string $path
385
-	 * @return bool|mixed
386
-	 */
387
-	public function is_file($path) {
388
-		if ($path == '/') {
389
-			return false;
390
-		}
391
-		return $this->basicOperation('is_file', $path);
392
-	}
393
-
394
-	/**
395
-	 * @param string $path
396
-	 * @return mixed
397
-	 */
398
-	public function stat($path) {
399
-		return $this->basicOperation('stat', $path);
400
-	}
401
-
402
-	/**
403
-	 * @param string $path
404
-	 * @return mixed
405
-	 */
406
-	public function filetype($path) {
407
-		return $this->basicOperation('filetype', $path);
408
-	}
409
-
410
-	/**
411
-	 * @param string $path
412
-	 * @return mixed
413
-	 */
414
-	public function filesize($path) {
415
-		return $this->basicOperation('filesize', $path);
416
-	}
417
-
418
-	/**
419
-	 * @param string $path
420
-	 * @return bool|mixed
421
-	 * @throws \OCP\Files\InvalidPathException
422
-	 */
423
-	public function readfile($path) {
424
-		$this->assertPathLength($path);
425
-		@ob_end_clean();
426
-		$handle = $this->fopen($path, 'rb');
427
-		if ($handle) {
428
-			$chunkSize = 8192; // 8 kB chunks
429
-			while (!feof($handle)) {
430
-				echo fread($handle, $chunkSize);
431
-				flush();
432
-			}
433
-			$size = $this->filesize($path);
434
-			return $size;
435
-		}
436
-		return false;
437
-	}
438
-
439
-	/**
440
-	 * @param string $path
441
-	 * @param int $from
442
-	 * @param int $to
443
-	 * @return bool|mixed
444
-	 * @throws \OCP\Files\InvalidPathException
445
-	 * @throws \OCP\Files\UnseekableException
446
-	 */
447
-	public function readfilePart($path, $from, $to) {
448
-		$this->assertPathLength($path);
449
-		@ob_end_clean();
450
-		$handle = $this->fopen($path, 'rb');
451
-		if ($handle) {
452
-			if (fseek($handle, $from) === 0) {
453
-				$chunkSize = 8192; // 8 kB chunks
454
-				$end = $to + 1;
455
-				while (!feof($handle) && ftell($handle) < $end) {
456
-					$len = $end - ftell($handle);
457
-					if ($len > $chunkSize) {
458
-						$len = $chunkSize;
459
-					}
460
-					echo fread($handle, $len);
461
-					flush();
462
-				}
463
-				$size = ftell($handle) - $from;
464
-				return $size;
465
-			}
466
-
467
-			throw new \OCP\Files\UnseekableException('fseek error');
468
-		}
469
-		return false;
470
-	}
471
-
472
-	/**
473
-	 * @param string $path
474
-	 * @return mixed
475
-	 */
476
-	public function isCreatable($path) {
477
-		return $this->basicOperation('isCreatable', $path);
478
-	}
479
-
480
-	/**
481
-	 * @param string $path
482
-	 * @return mixed
483
-	 */
484
-	public function isReadable($path) {
485
-		return $this->basicOperation('isReadable', $path);
486
-	}
487
-
488
-	/**
489
-	 * @param string $path
490
-	 * @return mixed
491
-	 */
492
-	public function isUpdatable($path) {
493
-		return $this->basicOperation('isUpdatable', $path);
494
-	}
495
-
496
-	/**
497
-	 * @param string $path
498
-	 * @return bool|mixed
499
-	 */
500
-	public function isDeletable($path) {
501
-		$absolutePath = $this->getAbsolutePath($path);
502
-		$mount = Filesystem::getMountManager()->find($absolutePath);
503
-		if ($mount->getInternalPath($absolutePath) === '') {
504
-			return $mount instanceof MoveableMount;
505
-		}
506
-		return $this->basicOperation('isDeletable', $path);
507
-	}
508
-
509
-	/**
510
-	 * @param string $path
511
-	 * @return mixed
512
-	 */
513
-	public function isSharable($path) {
514
-		return $this->basicOperation('isSharable', $path);
515
-	}
516
-
517
-	/**
518
-	 * @param string $path
519
-	 * @return bool|mixed
520
-	 */
521
-	public function file_exists($path) {
522
-		if ($path == '/') {
523
-			return true;
524
-		}
525
-		return $this->basicOperation('file_exists', $path);
526
-	}
527
-
528
-	/**
529
-	 * @param string $path
530
-	 * @return mixed
531
-	 */
532
-	public function filemtime($path) {
533
-		return $this->basicOperation('filemtime', $path);
534
-	}
535
-
536
-	/**
537
-	 * @param string $path
538
-	 * @param int|string $mtime
539
-	 * @return bool
540
-	 */
541
-	public function touch($path, $mtime = null) {
542
-		if (!is_null($mtime) and !is_numeric($mtime)) {
543
-			$mtime = strtotime($mtime);
544
-		}
545
-
546
-		$hooks = array('touch');
547
-
548
-		if (!$this->file_exists($path)) {
549
-			$hooks[] = 'create';
550
-			$hooks[] = 'write';
551
-		}
552
-		$result = $this->basicOperation('touch', $path, $hooks, $mtime);
553
-		if (!$result) {
554
-			// If create file fails because of permissions on external storage like SMB folders,
555
-			// check file exists and return false if not.
556
-			if (!$this->file_exists($path)) {
557
-				return false;
558
-			}
559
-			if (is_null($mtime)) {
560
-				$mtime = time();
561
-			}
562
-			//if native touch fails, we emulate it by changing the mtime in the cache
563
-			$this->putFileInfo($path, array('mtime' => $mtime));
564
-		}
565
-		return true;
566
-	}
567
-
568
-	/**
569
-	 * @param string $path
570
-	 * @return mixed
571
-	 */
572
-	public function file_get_contents($path) {
573
-		return $this->basicOperation('file_get_contents', $path, array('read'));
574
-	}
575
-
576
-	/**
577
-	 * @param bool $exists
578
-	 * @param string $path
579
-	 * @param bool $run
580
-	 */
581
-	protected function emit_file_hooks_pre($exists, $path, &$run) {
582
-		if (!$exists) {
583
-			\OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_create, array(
584
-				Filesystem::signal_param_path => $this->getHookPath($path),
585
-				Filesystem::signal_param_run => &$run,
586
-			));
587
-		} else {
588
-			\OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_update, array(
589
-				Filesystem::signal_param_path => $this->getHookPath($path),
590
-				Filesystem::signal_param_run => &$run,
591
-			));
592
-		}
593
-		\OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_write, array(
594
-			Filesystem::signal_param_path => $this->getHookPath($path),
595
-			Filesystem::signal_param_run => &$run,
596
-		));
597
-	}
598
-
599
-	/**
600
-	 * @param bool $exists
601
-	 * @param string $path
602
-	 */
603
-	protected function emit_file_hooks_post($exists, $path) {
604
-		if (!$exists) {
605
-			\OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_post_create, array(
606
-				Filesystem::signal_param_path => $this->getHookPath($path),
607
-			));
608
-		} else {
609
-			\OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_post_update, array(
610
-				Filesystem::signal_param_path => $this->getHookPath($path),
611
-			));
612
-		}
613
-		\OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_post_write, array(
614
-			Filesystem::signal_param_path => $this->getHookPath($path),
615
-		));
616
-	}
617
-
618
-	/**
619
-	 * @param string $path
620
-	 * @param mixed $data
621
-	 * @return bool|mixed
622
-	 * @throws \Exception
623
-	 */
624
-	public function file_put_contents($path, $data) {
625
-		if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier
626
-			$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
627
-			if (Filesystem::isValidPath($path)
628
-				and !Filesystem::isFileBlacklisted($path)
629
-			) {
630
-				$path = $this->getRelativePath($absolutePath);
631
-
632
-				$this->lockFile($path, ILockingProvider::LOCK_SHARED);
633
-
634
-				$exists = $this->file_exists($path);
635
-				$run = true;
636
-				if ($this->shouldEmitHooks($path)) {
637
-					$this->emit_file_hooks_pre($exists, $path, $run);
638
-				}
639
-				if (!$run) {
640
-					$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
641
-					return false;
642
-				}
643
-
644
-				$this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
645
-
646
-				/** @var \OC\Files\Storage\Storage $storage */
647
-				list($storage, $internalPath) = $this->resolvePath($path);
648
-				$target = $storage->fopen($internalPath, 'w');
649
-				if ($target) {
650
-					list (, $result) = \OC_Helper::streamCopy($data, $target);
651
-					fclose($target);
652
-					fclose($data);
653
-
654
-					$this->writeUpdate($storage, $internalPath);
655
-
656
-					$this->changeLock($path, ILockingProvider::LOCK_SHARED);
657
-
658
-					if ($this->shouldEmitHooks($path) && $result !== false) {
659
-						$this->emit_file_hooks_post($exists, $path);
660
-					}
661
-					$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
662
-					return $result;
663
-				} else {
664
-					$this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
665
-					return false;
666
-				}
667
-			} else {
668
-				return false;
669
-			}
670
-		} else {
671
-			$hooks = ($this->file_exists($path)) ? array('update', 'write') : array('create', 'write');
672
-			return $this->basicOperation('file_put_contents', $path, $hooks, $data);
673
-		}
674
-	}
675
-
676
-	/**
677
-	 * @param string $path
678
-	 * @return bool|mixed
679
-	 */
680
-	public function unlink($path) {
681
-		if ($path === '' || $path === '/') {
682
-			// do not allow deleting the root
683
-			return false;
684
-		}
685
-		$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
686
-		$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
687
-		$mount = Filesystem::getMountManager()->find($absolutePath . $postFix);
688
-		if ($mount and $mount->getInternalPath($absolutePath) === '') {
689
-			return $this->removeMount($mount, $absolutePath);
690
-		}
691
-		$result = $this->basicOperation('unlink', $path, array('delete'));
692
-		if (!$result && !$this->file_exists($path)) { //clear ghost files from the cache on delete
693
-			$storage = $mount->getStorage();
694
-			$internalPath = $mount->getInternalPath($absolutePath);
695
-			$storage->getUpdater()->remove($internalPath);
696
-			return true;
697
-		} else {
698
-			return $result;
699
-		}
700
-	}
701
-
702
-	/**
703
-	 * @param string $directory
704
-	 * @return bool|mixed
705
-	 */
706
-	public function deleteAll($directory) {
707
-		return $this->rmdir($directory);
708
-	}
709
-
710
-	/**
711
-	 * Rename/move a file or folder from the source path to target path.
712
-	 *
713
-	 * @param string $path1 source path
714
-	 * @param string $path2 target path
715
-	 *
716
-	 * @return bool|mixed
717
-	 */
718
-	public function rename($path1, $path2) {
719
-		$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1));
720
-		$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2));
721
-		$result = false;
722
-		if (
723
-			Filesystem::isValidPath($path2)
724
-			and Filesystem::isValidPath($path1)
725
-			and !Filesystem::isFileBlacklisted($path2)
726
-		) {
727
-			$path1 = $this->getRelativePath($absolutePath1);
728
-			$path2 = $this->getRelativePath($absolutePath2);
729
-			$exists = $this->file_exists($path2);
730
-
731
-			if ($path1 == null or $path2 == null) {
732
-				return false;
733
-			}
734
-
735
-			$this->lockFile($path1, ILockingProvider::LOCK_SHARED, true);
736
-			try {
737
-				$this->lockFile($path2, ILockingProvider::LOCK_SHARED, true);
738
-			} catch (LockedException $e) {
739
-				$this->unlockFile($path1, ILockingProvider::LOCK_SHARED);
740
-				throw $e;
741
-			}
742
-
743
-			$run = true;
744
-			if ($this->shouldEmitHooks($path1) && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2))) {
745
-				// if it was a rename from a part file to a regular file it was a write and not a rename operation
746
-				$this->emit_file_hooks_pre($exists, $path2, $run);
747
-			} elseif ($this->shouldEmitHooks($path1)) {
748
-				\OC_Hook::emit(
749
-					Filesystem::CLASSNAME, Filesystem::signal_rename,
750
-					array(
751
-						Filesystem::signal_param_oldpath => $this->getHookPath($path1),
752
-						Filesystem::signal_param_newpath => $this->getHookPath($path2),
753
-						Filesystem::signal_param_run => &$run
754
-					)
755
-				);
756
-			}
757
-			if ($run) {
758
-				$this->verifyPath(dirname($path2), basename($path2));
759
-
760
-				$manager = Filesystem::getMountManager();
761
-				$mount1 = $this->getMount($path1);
762
-				$mount2 = $this->getMount($path2);
763
-				$storage1 = $mount1->getStorage();
764
-				$storage2 = $mount2->getStorage();
765
-				$internalPath1 = $mount1->getInternalPath($absolutePath1);
766
-				$internalPath2 = $mount2->getInternalPath($absolutePath2);
767
-
768
-				$this->changeLock($path1, ILockingProvider::LOCK_EXCLUSIVE, true);
769
-				$this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE, true);
770
-
771
-				if ($internalPath1 === '' and $mount1 instanceof MoveableMount) {
772
-					if ($this->isTargetAllowed($absolutePath2)) {
773
-						/**
774
-						 * @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount1
775
-						 */
776
-						$sourceMountPoint = $mount1->getMountPoint();
777
-						$result = $mount1->moveMount($absolutePath2);
778
-						$manager->moveMount($sourceMountPoint, $mount1->getMountPoint());
779
-					} else {
780
-						$result = false;
781
-					}
782
-					// moving a file/folder within the same mount point
783
-				} elseif ($storage1 === $storage2) {
784
-					if ($storage1) {
785
-						$result = $storage1->rename($internalPath1, $internalPath2);
786
-					} else {
787
-						$result = false;
788
-					}
789
-					// moving a file/folder between storages (from $storage1 to $storage2)
790
-				} else {
791
-					$result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2);
792
-				}
793
-
794
-				if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) {
795
-					// if it was a rename from a part file to a regular file it was a write and not a rename operation
796
-
797
-					$this->writeUpdate($storage2, $internalPath2);
798
-				} else if ($result) {
799
-					if ($internalPath1 !== '') { // don't do a cache update for moved mounts
800
-						$this->renameUpdate($storage1, $storage2, $internalPath1, $internalPath2);
801
-					}
802
-				}
803
-
804
-				$this->changeLock($path1, ILockingProvider::LOCK_SHARED, true);
805
-				$this->changeLock($path2, ILockingProvider::LOCK_SHARED, true);
806
-
807
-				if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) {
808
-					if ($this->shouldEmitHooks()) {
809
-						$this->emit_file_hooks_post($exists, $path2);
810
-					}
811
-				} elseif ($result) {
812
-					if ($this->shouldEmitHooks($path1) and $this->shouldEmitHooks($path2)) {
813
-						\OC_Hook::emit(
814
-							Filesystem::CLASSNAME,
815
-							Filesystem::signal_post_rename,
816
-							array(
817
-								Filesystem::signal_param_oldpath => $this->getHookPath($path1),
818
-								Filesystem::signal_param_newpath => $this->getHookPath($path2)
819
-							)
820
-						);
821
-					}
822
-				}
823
-			}
824
-			$this->unlockFile($path1, ILockingProvider::LOCK_SHARED, true);
825
-			$this->unlockFile($path2, ILockingProvider::LOCK_SHARED, true);
826
-		}
827
-		return $result;
828
-	}
829
-
830
-	/**
831
-	 * Copy a file/folder from the source path to target path
832
-	 *
833
-	 * @param string $path1 source path
834
-	 * @param string $path2 target path
835
-	 * @param bool $preserveMtime whether to preserve mtime on the copy
836
-	 *
837
-	 * @return bool|mixed
838
-	 */
839
-	public function copy($path1, $path2, $preserveMtime = false) {
840
-		$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1));
841
-		$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2));
842
-		$result = false;
843
-		if (
844
-			Filesystem::isValidPath($path2)
845
-			and Filesystem::isValidPath($path1)
846
-			and !Filesystem::isFileBlacklisted($path2)
847
-		) {
848
-			$path1 = $this->getRelativePath($absolutePath1);
849
-			$path2 = $this->getRelativePath($absolutePath2);
850
-
851
-			if ($path1 == null or $path2 == null) {
852
-				return false;
853
-			}
854
-			$run = true;
855
-
856
-			$this->lockFile($path2, ILockingProvider::LOCK_SHARED);
857
-			$this->lockFile($path1, ILockingProvider::LOCK_SHARED);
858
-			$lockTypePath1 = ILockingProvider::LOCK_SHARED;
859
-			$lockTypePath2 = ILockingProvider::LOCK_SHARED;
860
-
861
-			try {
862
-
863
-				$exists = $this->file_exists($path2);
864
-				if ($this->shouldEmitHooks()) {
865
-					\OC_Hook::emit(
866
-						Filesystem::CLASSNAME,
867
-						Filesystem::signal_copy,
868
-						array(
869
-							Filesystem::signal_param_oldpath => $this->getHookPath($path1),
870
-							Filesystem::signal_param_newpath => $this->getHookPath($path2),
871
-							Filesystem::signal_param_run => &$run
872
-						)
873
-					);
874
-					$this->emit_file_hooks_pre($exists, $path2, $run);
875
-				}
876
-				if ($run) {
877
-					$mount1 = $this->getMount($path1);
878
-					$mount2 = $this->getMount($path2);
879
-					$storage1 = $mount1->getStorage();
880
-					$internalPath1 = $mount1->getInternalPath($absolutePath1);
881
-					$storage2 = $mount2->getStorage();
882
-					$internalPath2 = $mount2->getInternalPath($absolutePath2);
883
-
884
-					$this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE);
885
-					$lockTypePath2 = ILockingProvider::LOCK_EXCLUSIVE;
886
-
887
-					if ($mount1->getMountPoint() == $mount2->getMountPoint()) {
888
-						if ($storage1) {
889
-							$result = $storage1->copy($internalPath1, $internalPath2);
890
-						} else {
891
-							$result = false;
892
-						}
893
-					} else {
894
-						$result = $storage2->copyFromStorage($storage1, $internalPath1, $internalPath2);
895
-					}
896
-
897
-					$this->writeUpdate($storage2, $internalPath2);
898
-
899
-					$this->changeLock($path2, ILockingProvider::LOCK_SHARED);
900
-					$lockTypePath2 = ILockingProvider::LOCK_SHARED;
901
-
902
-					if ($this->shouldEmitHooks() && $result !== false) {
903
-						\OC_Hook::emit(
904
-							Filesystem::CLASSNAME,
905
-							Filesystem::signal_post_copy,
906
-							array(
907
-								Filesystem::signal_param_oldpath => $this->getHookPath($path1),
908
-								Filesystem::signal_param_newpath => $this->getHookPath($path2)
909
-							)
910
-						);
911
-						$this->emit_file_hooks_post($exists, $path2);
912
-					}
913
-
914
-				}
915
-			} catch (\Exception $e) {
916
-				$this->unlockFile($path2, $lockTypePath2);
917
-				$this->unlockFile($path1, $lockTypePath1);
918
-				throw $e;
919
-			}
920
-
921
-			$this->unlockFile($path2, $lockTypePath2);
922
-			$this->unlockFile($path1, $lockTypePath1);
923
-
924
-		}
925
-		return $result;
926
-	}
927
-
928
-	/**
929
-	 * @param string $path
930
-	 * @param string $mode
931
-	 * @return resource
932
-	 */
933
-	public function fopen($path, $mode) {
934
-		$hooks = array();
935
-		switch ($mode) {
936
-			case 'r':
937
-			case 'rb':
938
-				$hooks[] = 'read';
939
-				break;
940
-			case 'r+':
941
-			case 'rb+':
942
-			case 'w+':
943
-			case 'wb+':
944
-			case 'x+':
945
-			case 'xb+':
946
-			case 'a+':
947
-			case 'ab+':
948
-				$hooks[] = 'read';
949
-				$hooks[] = 'write';
950
-				break;
951
-			case 'w':
952
-			case 'wb':
953
-			case 'x':
954
-			case 'xb':
955
-			case 'a':
956
-			case 'ab':
957
-				$hooks[] = 'write';
958
-				break;
959
-			default:
960
-				\OCP\Util::writeLog('core', 'invalid mode (' . $mode . ') for ' . $path, \OCP\Util::ERROR);
961
-		}
962
-
963
-		return $this->basicOperation('fopen', $path, $hooks, $mode);
964
-	}
965
-
966
-	/**
967
-	 * @param string $path
968
-	 * @return bool|string
969
-	 * @throws \OCP\Files\InvalidPathException
970
-	 */
971
-	public function toTmpFile($path) {
972
-		$this->assertPathLength($path);
973
-		if (Filesystem::isValidPath($path)) {
974
-			$source = $this->fopen($path, 'r');
975
-			if ($source) {
976
-				$extension = pathinfo($path, PATHINFO_EXTENSION);
977
-				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($extension);
978
-				file_put_contents($tmpFile, $source);
979
-				return $tmpFile;
980
-			} else {
981
-				return false;
982
-			}
983
-		} else {
984
-			return false;
985
-		}
986
-	}
987
-
988
-	/**
989
-	 * @param string $tmpFile
990
-	 * @param string $path
991
-	 * @return bool|mixed
992
-	 * @throws \OCP\Files\InvalidPathException
993
-	 */
994
-	public function fromTmpFile($tmpFile, $path) {
995
-		$this->assertPathLength($path);
996
-		if (Filesystem::isValidPath($path)) {
997
-
998
-			// Get directory that the file is going into
999
-			$filePath = dirname($path);
1000
-
1001
-			// Create the directories if any
1002
-			if (!$this->file_exists($filePath)) {
1003
-				$result = $this->createParentDirectories($filePath);
1004
-				if($result === false) {
1005
-					return false;
1006
-				}
1007
-			}
1008
-
1009
-			$source = fopen($tmpFile, 'r');
1010
-			if ($source) {
1011
-				$result = $this->file_put_contents($path, $source);
1012
-				// $this->file_put_contents() might have already closed
1013
-				// the resource, so we check it, before trying to close it
1014
-				// to avoid messages in the error log.
1015
-				if (is_resource($source)) {
1016
-					fclose($source);
1017
-				}
1018
-				unlink($tmpFile);
1019
-				return $result;
1020
-			} else {
1021
-				return false;
1022
-			}
1023
-		} else {
1024
-			return false;
1025
-		}
1026
-	}
1027
-
1028
-
1029
-	/**
1030
-	 * @param string $path
1031
-	 * @return mixed
1032
-	 * @throws \OCP\Files\InvalidPathException
1033
-	 */
1034
-	public function getMimeType($path) {
1035
-		$this->assertPathLength($path);
1036
-		return $this->basicOperation('getMimeType', $path);
1037
-	}
1038
-
1039
-	/**
1040
-	 * @param string $type
1041
-	 * @param string $path
1042
-	 * @param bool $raw
1043
-	 * @return bool|null|string
1044
-	 */
1045
-	public function hash($type, $path, $raw = false) {
1046
-		$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
1047
-		$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
1048
-		if (Filesystem::isValidPath($path)) {
1049
-			$path = $this->getRelativePath($absolutePath);
1050
-			if ($path == null) {
1051
-				return false;
1052
-			}
1053
-			if ($this->shouldEmitHooks($path)) {
1054
-				\OC_Hook::emit(
1055
-					Filesystem::CLASSNAME,
1056
-					Filesystem::signal_read,
1057
-					array(Filesystem::signal_param_path => $this->getHookPath($path))
1058
-				);
1059
-			}
1060
-			list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
1061
-			if ($storage) {
1062
-				$result = $storage->hash($type, $internalPath, $raw);
1063
-				return $result;
1064
-			}
1065
-		}
1066
-		return null;
1067
-	}
1068
-
1069
-	/**
1070
-	 * @param string $path
1071
-	 * @return mixed
1072
-	 * @throws \OCP\Files\InvalidPathException
1073
-	 */
1074
-	public function free_space($path = '/') {
1075
-		$this->assertPathLength($path);
1076
-		return $this->basicOperation('free_space', $path);
1077
-	}
1078
-
1079
-	/**
1080
-	 * abstraction layer for basic filesystem functions: wrapper for \OC\Files\Storage\Storage
1081
-	 *
1082
-	 * @param string $operation
1083
-	 * @param string $path
1084
-	 * @param array $hooks (optional)
1085
-	 * @param mixed $extraParam (optional)
1086
-	 * @return mixed
1087
-	 * @throws \Exception
1088
-	 *
1089
-	 * This method takes requests for basic filesystem functions (e.g. reading & writing
1090
-	 * files), processes hooks and proxies, sanitises paths, and finally passes them on to
1091
-	 * \OC\Files\Storage\Storage for delegation to a storage backend for execution
1092
-	 */
1093
-	private function basicOperation($operation, $path, $hooks = [], $extraParam = null) {
1094
-		$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
1095
-		$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
1096
-		if (Filesystem::isValidPath($path)
1097
-			and !Filesystem::isFileBlacklisted($path)
1098
-		) {
1099
-			$path = $this->getRelativePath($absolutePath);
1100
-			if ($path == null) {
1101
-				return false;
1102
-			}
1103
-
1104
-			if (in_array('write', $hooks) || in_array('delete', $hooks) || in_array('read', $hooks)) {
1105
-				// always a shared lock during pre-hooks so the hook can read the file
1106
-				$this->lockFile($path, ILockingProvider::LOCK_SHARED);
1107
-			}
1108
-
1109
-			$run = $this->runHooks($hooks, $path);
1110
-			/** @var \OC\Files\Storage\Storage $storage */
1111
-			list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
1112
-			if ($run and $storage) {
1113
-				if (in_array('write', $hooks) || in_array('delete', $hooks)) {
1114
-					$this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
1115
-				}
1116
-				try {
1117
-					if (!is_null($extraParam)) {
1118
-						$result = $storage->$operation($internalPath, $extraParam);
1119
-					} else {
1120
-						$result = $storage->$operation($internalPath);
1121
-					}
1122
-				} catch (\Exception $e) {
1123
-					if (in_array('write', $hooks) || in_array('delete', $hooks)) {
1124
-						$this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
1125
-					} else if (in_array('read', $hooks)) {
1126
-						$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
1127
-					}
1128
-					throw $e;
1129
-				}
1130
-
1131
-				if ($result && in_array('delete', $hooks) and $result) {
1132
-					$this->removeUpdate($storage, $internalPath);
1133
-				}
1134
-				if ($result && in_array('write', $hooks) and $operation !== 'fopen') {
1135
-					$this->writeUpdate($storage, $internalPath);
1136
-				}
1137
-				if ($result && in_array('touch', $hooks)) {
1138
-					$this->writeUpdate($storage, $internalPath, $extraParam);
1139
-				}
1140
-
1141
-				if ((in_array('write', $hooks) || in_array('delete', $hooks)) && ($operation !== 'fopen' || $result === false)) {
1142
-					$this->changeLock($path, ILockingProvider::LOCK_SHARED);
1143
-				}
1144
-
1145
-				$unlockLater = false;
1146
-				if ($this->lockingEnabled && $operation === 'fopen' && is_resource($result)) {
1147
-					$unlockLater = true;
1148
-					$result = CallbackWrapper::wrap($result, null, null, function () use ($hooks, $path) {
1149
-						if (in_array('write', $hooks)) {
1150
-							$this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
1151
-						} else if (in_array('read', $hooks)) {
1152
-							$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
1153
-						}
1154
-					});
1155
-				}
1156
-
1157
-				if ($this->shouldEmitHooks($path) && $result !== false) {
1158
-					if ($operation != 'fopen') { //no post hooks for fopen, the file stream is still open
1159
-						$this->runHooks($hooks, $path, true);
1160
-					}
1161
-				}
1162
-
1163
-				if (!$unlockLater
1164
-					&& (in_array('write', $hooks) || in_array('delete', $hooks) || in_array('read', $hooks))
1165
-				) {
1166
-					$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
1167
-				}
1168
-				return $result;
1169
-			} else {
1170
-				$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
1171
-			}
1172
-		}
1173
-		return null;
1174
-	}
1175
-
1176
-	/**
1177
-	 * get the path relative to the default root for hook usage
1178
-	 *
1179
-	 * @param string $path
1180
-	 * @return string
1181
-	 */
1182
-	private function getHookPath($path) {
1183
-		if (!Filesystem::getView()) {
1184
-			return $path;
1185
-		}
1186
-		return Filesystem::getView()->getRelativePath($this->getAbsolutePath($path));
1187
-	}
1188
-
1189
-	private function shouldEmitHooks($path = '') {
1190
-		if ($path && Cache\Scanner::isPartialFile($path)) {
1191
-			return false;
1192
-		}
1193
-		if (!Filesystem::$loaded) {
1194
-			return false;
1195
-		}
1196
-		$defaultRoot = Filesystem::getRoot();
1197
-		if ($defaultRoot === null) {
1198
-			return false;
1199
-		}
1200
-		if ($this->fakeRoot === $defaultRoot) {
1201
-			return true;
1202
-		}
1203
-		$fullPath = $this->getAbsolutePath($path);
1204
-
1205
-		if ($fullPath === $defaultRoot) {
1206
-			return true;
1207
-		}
1208
-
1209
-		return (strlen($fullPath) > strlen($defaultRoot)) && (substr($fullPath, 0, strlen($defaultRoot) + 1) === $defaultRoot . '/');
1210
-	}
1211
-
1212
-	/**
1213
-	 * @param string[] $hooks
1214
-	 * @param string $path
1215
-	 * @param bool $post
1216
-	 * @return bool
1217
-	 */
1218
-	private function runHooks($hooks, $path, $post = false) {
1219
-		$relativePath = $path;
1220
-		$path = $this->getHookPath($path);
1221
-		$prefix = ($post) ? 'post_' : '';
1222
-		$run = true;
1223
-		if ($this->shouldEmitHooks($relativePath)) {
1224
-			foreach ($hooks as $hook) {
1225
-				if ($hook != 'read') {
1226
-					\OC_Hook::emit(
1227
-						Filesystem::CLASSNAME,
1228
-						$prefix . $hook,
1229
-						array(
1230
-							Filesystem::signal_param_run => &$run,
1231
-							Filesystem::signal_param_path => $path
1232
-						)
1233
-					);
1234
-				} elseif (!$post) {
1235
-					\OC_Hook::emit(
1236
-						Filesystem::CLASSNAME,
1237
-						$prefix . $hook,
1238
-						array(
1239
-							Filesystem::signal_param_path => $path
1240
-						)
1241
-					);
1242
-				}
1243
-			}
1244
-		}
1245
-		return $run;
1246
-	}
1247
-
1248
-	/**
1249
-	 * check if a file or folder has been updated since $time
1250
-	 *
1251
-	 * @param string $path
1252
-	 * @param int $time
1253
-	 * @return bool
1254
-	 */
1255
-	public function hasUpdated($path, $time) {
1256
-		return $this->basicOperation('hasUpdated', $path, array(), $time);
1257
-	}
1258
-
1259
-	/**
1260
-	 * @param string $ownerId
1261
-	 * @return \OC\User\User
1262
-	 */
1263
-	private function getUserObjectForOwner($ownerId) {
1264
-		$owner = $this->userManager->get($ownerId);
1265
-		if ($owner instanceof IUser) {
1266
-			return $owner;
1267
-		} else {
1268
-			return new User($ownerId, null);
1269
-		}
1270
-	}
1271
-
1272
-	/**
1273
-	 * Get file info from cache
1274
-	 *
1275
-	 * If the file is not in cached it will be scanned
1276
-	 * If the file has changed on storage the cache will be updated
1277
-	 *
1278
-	 * @param \OC\Files\Storage\Storage $storage
1279
-	 * @param string $internalPath
1280
-	 * @param string $relativePath
1281
-	 * @return array|bool
1282
-	 */
1283
-	private function getCacheEntry($storage, $internalPath, $relativePath) {
1284
-		$cache = $storage->getCache($internalPath);
1285
-		$data = $cache->get($internalPath);
1286
-		$watcher = $storage->getWatcher($internalPath);
1287
-
1288
-		try {
1289
-			// if the file is not in the cache or needs to be updated, trigger the scanner and reload the data
1290
-			if (!$data || $data['size'] === -1) {
1291
-				$this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
1292
-				if (!$storage->file_exists($internalPath)) {
1293
-					$this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
1294
-					return false;
1295
-				}
1296
-				$scanner = $storage->getScanner($internalPath);
1297
-				$scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
1298
-				$data = $cache->get($internalPath);
1299
-				$this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
1300
-			} else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->needsUpdate($internalPath, $data)) {
1301
-				$this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
1302
-				$watcher->update($internalPath, $data);
1303
-				$storage->getPropagator()->propagateChange($internalPath, time());
1304
-				$data = $cache->get($internalPath);
1305
-				$this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
1306
-			}
1307
-		} catch (LockedException $e) {
1308
-			// if the file is locked we just use the old cache info
1309
-		}
1310
-
1311
-		return $data;
1312
-	}
1313
-
1314
-	/**
1315
-	 * get the filesystem info
1316
-	 *
1317
-	 * @param string $path
1318
-	 * @param boolean|string $includeMountPoints true to add mountpoint sizes,
1319
-	 * 'ext' to add only ext storage mount point sizes. Defaults to true.
1320
-	 * defaults to true
1321
-	 * @return \OC\Files\FileInfo|false False if file does not exist
1322
-	 */
1323
-	public function getFileInfo($path, $includeMountPoints = true) {
1324
-		$this->assertPathLength($path);
1325
-		if (!Filesystem::isValidPath($path)) {
1326
-			return false;
1327
-		}
1328
-		if (Cache\Scanner::isPartialFile($path)) {
1329
-			return $this->getPartFileInfo($path);
1330
-		}
1331
-		$relativePath = $path;
1332
-		$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
1333
-
1334
-		$mount = Filesystem::getMountManager()->find($path);
1335
-		$storage = $mount->getStorage();
1336
-		$internalPath = $mount->getInternalPath($path);
1337
-		if ($storage) {
1338
-			$data = $this->getCacheEntry($storage, $internalPath, $relativePath);
1339
-
1340
-			if (!$data instanceof ICacheEntry) {
1341
-				return false;
1342
-			}
1343
-
1344
-			if ($mount instanceof MoveableMount && $internalPath === '') {
1345
-				$data['permissions'] |= \OCP\Constants::PERMISSION_DELETE;
1346
-			}
1347
-
1348
-			$owner = $this->getUserObjectForOwner($storage->getOwner($internalPath));
1349
-			$info = new FileInfo($path, $storage, $internalPath, $data, $mount, $owner);
1350
-
1351
-			if ($data and isset($data['fileid'])) {
1352
-				if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {
1353
-					//add the sizes of other mount points to the folder
1354
-					$extOnly = ($includeMountPoints === 'ext');
1355
-					$mounts = Filesystem::getMountManager()->findIn($path);
1356
-					foreach ($mounts as $mount) {
1357
-						$subStorage = $mount->getStorage();
1358
-						if ($subStorage) {
1359
-							// exclude shared storage ?
1360
-							if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) {
1361
-								continue;
1362
-							}
1363
-							$subCache = $subStorage->getCache('');
1364
-							$rootEntry = $subCache->get('');
1365
-							$info->addSubEntry($rootEntry, $mount->getMountPoint());
1366
-						}
1367
-					}
1368
-				}
1369
-			}
1370
-
1371
-			return $info;
1372
-		}
1373
-
1374
-		return false;
1375
-	}
1376
-
1377
-	/**
1378
-	 * get the content of a directory
1379
-	 *
1380
-	 * @param string $directory path under datadirectory
1381
-	 * @param string $mimetype_filter limit returned content to this mimetype or mimepart
1382
-	 * @return FileInfo[]
1383
-	 */
1384
-	public function getDirectoryContent($directory, $mimetype_filter = '') {
1385
-		$this->assertPathLength($directory);
1386
-		if (!Filesystem::isValidPath($directory)) {
1387
-			return [];
1388
-		}
1389
-		$path = $this->getAbsolutePath($directory);
1390
-		$path = Filesystem::normalizePath($path);
1391
-		$mount = $this->getMount($directory);
1392
-		$storage = $mount->getStorage();
1393
-		$internalPath = $mount->getInternalPath($path);
1394
-		if ($storage) {
1395
-			$cache = $storage->getCache($internalPath);
1396
-			$user = \OC_User::getUser();
1397
-
1398
-			$data = $this->getCacheEntry($storage, $internalPath, $directory);
1399
-
1400
-			if (!$data instanceof ICacheEntry || !isset($data['fileid']) || !($data->getPermissions() && Constants::PERMISSION_READ)) {
1401
-				return [];
1402
-			}
1403
-
1404
-			$folderId = $data['fileid'];
1405
-			$contents = $cache->getFolderContentsById($folderId); //TODO: mimetype_filter
1406
-
1407
-			$sharingDisabled = \OCP\Util::isSharingDisabledForUser();
1408
-			/**
1409
-			 * @var \OC\Files\FileInfo[] $files
1410
-			 */
1411
-			$files = array_map(function (ICacheEntry $content) use ($path, $storage, $mount, $sharingDisabled) {
1412
-				if ($sharingDisabled) {
1413
-					$content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
1414
-				}
1415
-				$owner = $this->getUserObjectForOwner($storage->getOwner($content['path']));
1416
-				return new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner);
1417
-			}, $contents);
1418
-
1419
-			//add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
1420
-			$mounts = Filesystem::getMountManager()->findIn($path);
1421
-			$dirLength = strlen($path);
1422
-			foreach ($mounts as $mount) {
1423
-				$mountPoint = $mount->getMountPoint();
1424
-				$subStorage = $mount->getStorage();
1425
-				if ($subStorage) {
1426
-					$subCache = $subStorage->getCache('');
1427
-
1428
-					$rootEntry = $subCache->get('');
1429
-					if (!$rootEntry) {
1430
-						$subScanner = $subStorage->getScanner('');
1431
-						try {
1432
-							$subScanner->scanFile('');
1433
-						} catch (\OCP\Files\StorageNotAvailableException $e) {
1434
-							continue;
1435
-						} catch (\OCP\Files\StorageInvalidException $e) {
1436
-							continue;
1437
-						} catch (\Exception $e) {
1438
-							// sometimes when the storage is not available it can be any exception
1439
-							\OCP\Util::writeLog(
1440
-								'core',
1441
-								'Exception while scanning storage "' . $subStorage->getId() . '": ' .
1442
-								get_class($e) . ': ' . $e->getMessage(),
1443
-								\OCP\Util::ERROR
1444
-							);
1445
-							continue;
1446
-						}
1447
-						$rootEntry = $subCache->get('');
1448
-					}
1449
-
1450
-					if ($rootEntry && ($rootEntry->getPermissions() && Constants::PERMISSION_READ)) {
1451
-						$relativePath = trim(substr($mountPoint, $dirLength), '/');
1452
-						if ($pos = strpos($relativePath, '/')) {
1453
-							//mountpoint inside subfolder add size to the correct folder
1454
-							$entryName = substr($relativePath, 0, $pos);
1455
-							foreach ($files as &$entry) {
1456
-								if ($entry->getName() === $entryName) {
1457
-									$entry->addSubEntry($rootEntry, $mountPoint);
1458
-								}
1459
-							}
1460
-						} else { //mountpoint in this folder, add an entry for it
1461
-							$rootEntry['name'] = $relativePath;
1462
-							$rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file';
1463
-							$permissions = $rootEntry['permissions'];
1464
-							// do not allow renaming/deleting the mount point if they are not shared files/folders
1465
-							// for shared files/folders we use the permissions given by the owner
1466
-							if ($mount instanceof MoveableMount) {
1467
-								$rootEntry['permissions'] = $permissions | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
1468
-							} else {
1469
-								$rootEntry['permissions'] = $permissions & (\OCP\Constants::PERMISSION_ALL - (\OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE));
1470
-							}
1471
-
1472
-							//remove any existing entry with the same name
1473
-							foreach ($files as $i => $file) {
1474
-								if ($file['name'] === $rootEntry['name']) {
1475
-									unset($files[$i]);
1476
-									break;
1477
-								}
1478
-							}
1479
-							$rootEntry['path'] = substr(Filesystem::normalizePath($path . '/' . $rootEntry['name']), strlen($user) + 2); // full path without /$user/
1480
-
1481
-							// if sharing was disabled for the user we remove the share permissions
1482
-							if (\OCP\Util::isSharingDisabledForUser()) {
1483
-								$rootEntry['permissions'] = $rootEntry['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
1484
-							}
1485
-
1486
-							$owner = $this->getUserObjectForOwner($subStorage->getOwner(''));
1487
-							$files[] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry, $mount, $owner);
1488
-						}
1489
-					}
1490
-				}
1491
-			}
1492
-
1493
-			if ($mimetype_filter) {
1494
-				$files = array_filter($files, function (FileInfo $file) use ($mimetype_filter) {
1495
-					if (strpos($mimetype_filter, '/')) {
1496
-						return $file->getMimetype() === $mimetype_filter;
1497
-					} else {
1498
-						return $file->getMimePart() === $mimetype_filter;
1499
-					}
1500
-				});
1501
-			}
1502
-
1503
-			return $files;
1504
-		} else {
1505
-			return [];
1506
-		}
1507
-	}
1508
-
1509
-	/**
1510
-	 * change file metadata
1511
-	 *
1512
-	 * @param string $path
1513
-	 * @param array|\OCP\Files\FileInfo $data
1514
-	 * @return int
1515
-	 *
1516
-	 * returns the fileid of the updated file
1517
-	 */
1518
-	public function putFileInfo($path, $data) {
1519
-		$this->assertPathLength($path);
1520
-		if ($data instanceof FileInfo) {
1521
-			$data = $data->getData();
1522
-		}
1523
-		$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
1524
-		/**
1525
-		 * @var \OC\Files\Storage\Storage $storage
1526
-		 * @var string $internalPath
1527
-		 */
1528
-		list($storage, $internalPath) = Filesystem::resolvePath($path);
1529
-		if ($storage) {
1530
-			$cache = $storage->getCache($path);
1531
-
1532
-			if (!$cache->inCache($internalPath)) {
1533
-				$scanner = $storage->getScanner($internalPath);
1534
-				$scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
1535
-			}
1536
-
1537
-			return $cache->put($internalPath, $data);
1538
-		} else {
1539
-			return -1;
1540
-		}
1541
-	}
1542
-
1543
-	/**
1544
-	 * search for files with the name matching $query
1545
-	 *
1546
-	 * @param string $query
1547
-	 * @return FileInfo[]
1548
-	 */
1549
-	public function search($query) {
1550
-		return $this->searchCommon('search', array('%' . $query . '%'));
1551
-	}
1552
-
1553
-	/**
1554
-	 * search for files with the name matching $query
1555
-	 *
1556
-	 * @param string $query
1557
-	 * @return FileInfo[]
1558
-	 */
1559
-	public function searchRaw($query) {
1560
-		return $this->searchCommon('search', array($query));
1561
-	}
1562
-
1563
-	/**
1564
-	 * search for files by mimetype
1565
-	 *
1566
-	 * @param string $mimetype
1567
-	 * @return FileInfo[]
1568
-	 */
1569
-	public function searchByMime($mimetype) {
1570
-		return $this->searchCommon('searchByMime', array($mimetype));
1571
-	}
1572
-
1573
-	/**
1574
-	 * search for files by tag
1575
-	 *
1576
-	 * @param string|int $tag name or tag id
1577
-	 * @param string $userId owner of the tags
1578
-	 * @return FileInfo[]
1579
-	 */
1580
-	public function searchByTag($tag, $userId) {
1581
-		return $this->searchCommon('searchByTag', array($tag, $userId));
1582
-	}
1583
-
1584
-	/**
1585
-	 * @param string $method cache method
1586
-	 * @param array $args
1587
-	 * @return FileInfo[]
1588
-	 */
1589
-	private function searchCommon($method, $args) {
1590
-		$files = array();
1591
-		$rootLength = strlen($this->fakeRoot);
1592
-
1593
-		$mount = $this->getMount('');
1594
-		$mountPoint = $mount->getMountPoint();
1595
-		$storage = $mount->getStorage();
1596
-		if ($storage) {
1597
-			$cache = $storage->getCache('');
1598
-
1599
-			$results = call_user_func_array(array($cache, $method), $args);
1600
-			foreach ($results as $result) {
1601
-				if (substr($mountPoint . $result['path'], 0, $rootLength + 1) === $this->fakeRoot . '/') {
1602
-					$internalPath = $result['path'];
1603
-					$path = $mountPoint . $result['path'];
1604
-					$result['path'] = substr($mountPoint . $result['path'], $rootLength);
1605
-					$owner = \OC::$server->getUserManager()->get($storage->getOwner($internalPath));
1606
-					$files[] = new FileInfo($path, $storage, $internalPath, $result, $mount, $owner);
1607
-				}
1608
-			}
1609
-
1610
-			$mounts = Filesystem::getMountManager()->findIn($this->fakeRoot);
1611
-			foreach ($mounts as $mount) {
1612
-				$mountPoint = $mount->getMountPoint();
1613
-				$storage = $mount->getStorage();
1614
-				if ($storage) {
1615
-					$cache = $storage->getCache('');
1616
-
1617
-					$relativeMountPoint = substr($mountPoint, $rootLength);
1618
-					$results = call_user_func_array(array($cache, $method), $args);
1619
-					if ($results) {
1620
-						foreach ($results as $result) {
1621
-							$internalPath = $result['path'];
1622
-							$result['path'] = rtrim($relativeMountPoint . $result['path'], '/');
1623
-							$path = rtrim($mountPoint . $internalPath, '/');
1624
-							$owner = \OC::$server->getUserManager()->get($storage->getOwner($internalPath));
1625
-							$files[] = new FileInfo($path, $storage, $internalPath, $result, $mount, $owner);
1626
-						}
1627
-					}
1628
-				}
1629
-			}
1630
-		}
1631
-		return $files;
1632
-	}
1633
-
1634
-	/**
1635
-	 * Get the owner for a file or folder
1636
-	 *
1637
-	 * @param string $path
1638
-	 * @return string the user id of the owner
1639
-	 * @throws NotFoundException
1640
-	 */
1641
-	public function getOwner($path) {
1642
-		$info = $this->getFileInfo($path);
1643
-		if (!$info) {
1644
-			throw new NotFoundException($path . ' not found while trying to get owner');
1645
-		}
1646
-		return $info->getOwner()->getUID();
1647
-	}
1648
-
1649
-	/**
1650
-	 * get the ETag for a file or folder
1651
-	 *
1652
-	 * @param string $path
1653
-	 * @return string
1654
-	 */
1655
-	public function getETag($path) {
1656
-		/**
1657
-		 * @var Storage\Storage $storage
1658
-		 * @var string $internalPath
1659
-		 */
1660
-		list($storage, $internalPath) = $this->resolvePath($path);
1661
-		if ($storage) {
1662
-			return $storage->getETag($internalPath);
1663
-		} else {
1664
-			return null;
1665
-		}
1666
-	}
1667
-
1668
-	/**
1669
-	 * Get the path of a file by id, relative to the view
1670
-	 *
1671
-	 * Note that the resulting path is not guarantied to be unique for the id, multiple paths can point to the same file
1672
-	 *
1673
-	 * @param int $id
1674
-	 * @throws NotFoundException
1675
-	 * @return string
1676
-	 */
1677
-	public function getPath($id) {
1678
-		$id = (int)$id;
1679
-		$manager = Filesystem::getMountManager();
1680
-		$mounts = $manager->findIn($this->fakeRoot);
1681
-		$mounts[] = $manager->find($this->fakeRoot);
1682
-		// reverse the array so we start with the storage this view is in
1683
-		// which is the most likely to contain the file we're looking for
1684
-		$mounts = array_reverse($mounts);
1685
-		foreach ($mounts as $mount) {
1686
-			/**
1687
-			 * @var \OC\Files\Mount\MountPoint $mount
1688
-			 */
1689
-			if ($mount->getStorage()) {
1690
-				$cache = $mount->getStorage()->getCache();
1691
-				$internalPath = $cache->getPathById($id);
1692
-				if (is_string($internalPath)) {
1693
-					$fullPath = $mount->getMountPoint() . $internalPath;
1694
-					if (!is_null($path = $this->getRelativePath($fullPath))) {
1695
-						return $path;
1696
-					}
1697
-				}
1698
-			}
1699
-		}
1700
-		throw new NotFoundException(sprintf('File with id "%s" has not been found.', $id));
1701
-	}
1702
-
1703
-	/**
1704
-	 * @param string $path
1705
-	 * @throws InvalidPathException
1706
-	 */
1707
-	private function assertPathLength($path) {
1708
-		$maxLen = min(PHP_MAXPATHLEN, 4000);
1709
-		// Check for the string length - performed using isset() instead of strlen()
1710
-		// because isset() is about 5x-40x faster.
1711
-		if (isset($path[$maxLen])) {
1712
-			$pathLen = strlen($path);
1713
-			throw new \OCP\Files\InvalidPathException("Path length($pathLen) exceeds max path length($maxLen): $path");
1714
-		}
1715
-	}
1716
-
1717
-	/**
1718
-	 * check if it is allowed to move a mount point to a given target.
1719
-	 * It is not allowed to move a mount point into a different mount point or
1720
-	 * into an already shared folder
1721
-	 *
1722
-	 * @param string $target path
1723
-	 * @return boolean
1724
-	 */
1725
-	private function isTargetAllowed($target) {
1726
-
1727
-		list($targetStorage, $targetInternalPath) = \OC\Files\Filesystem::resolvePath($target);
1728
-		if (!$targetStorage->instanceOfStorage('\OCP\Files\IHomeStorage')) {
1729
-			\OCP\Util::writeLog('files',
1730
-				'It is not allowed to move one mount point into another one',
1731
-				\OCP\Util::DEBUG);
1732
-			return false;
1733
-		}
1734
-
1735
-		// note: cannot use the view because the target is already locked
1736
-		$fileId = (int)$targetStorage->getCache()->getId($targetInternalPath);
1737
-		if ($fileId === -1) {
1738
-			// target might not exist, need to check parent instead
1739
-			$fileId = (int)$targetStorage->getCache()->getId(dirname($targetInternalPath));
1740
-		}
1741
-
1742
-		// check if any of the parents were shared by the current owner (include collections)
1743
-		$shares = \OCP\Share::getItemShared(
1744
-			'folder',
1745
-			$fileId,
1746
-			\OCP\Share::FORMAT_NONE,
1747
-			null,
1748
-			true
1749
-		);
1750
-
1751
-		if (count($shares) > 0) {
1752
-			\OCP\Util::writeLog('files',
1753
-				'It is not allowed to move one mount point into a shared folder',
1754
-				\OCP\Util::DEBUG);
1755
-			return false;
1756
-		}
1757
-
1758
-		return true;
1759
-	}
1760
-
1761
-	/**
1762
-	 * Get a fileinfo object for files that are ignored in the cache (part files)
1763
-	 *
1764
-	 * @param string $path
1765
-	 * @return \OCP\Files\FileInfo
1766
-	 */
1767
-	private function getPartFileInfo($path) {
1768
-		$mount = $this->getMount($path);
1769
-		$storage = $mount->getStorage();
1770
-		$internalPath = $mount->getInternalPath($this->getAbsolutePath($path));
1771
-		$owner = \OC::$server->getUserManager()->get($storage->getOwner($internalPath));
1772
-		return new FileInfo(
1773
-			$this->getAbsolutePath($path),
1774
-			$storage,
1775
-			$internalPath,
1776
-			[
1777
-				'fileid' => null,
1778
-				'mimetype' => $storage->getMimeType($internalPath),
1779
-				'name' => basename($path),
1780
-				'etag' => null,
1781
-				'size' => $storage->filesize($internalPath),
1782
-				'mtime' => $storage->filemtime($internalPath),
1783
-				'encrypted' => false,
1784
-				'permissions' => \OCP\Constants::PERMISSION_ALL
1785
-			],
1786
-			$mount,
1787
-			$owner
1788
-		);
1789
-	}
1790
-
1791
-	/**
1792
-	 * @param string $path
1793
-	 * @param string $fileName
1794
-	 * @throws InvalidPathException
1795
-	 */
1796
-	public function verifyPath($path, $fileName) {
1797
-
1798
-		$l10n = \OC::$server->getL10N('lib');
1799
-
1800
-		// verify empty and dot files
1801
-		$trimmed = trim($fileName);
1802
-		if ($trimmed === '') {
1803
-			throw new InvalidPathException($l10n->t('Empty filename is not allowed'));
1804
-		}
1805
-		if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) {
1806
-			throw new InvalidPathException($l10n->t('Dot files are not allowed'));
1807
-		}
1808
-
1809
-		// verify database - e.g. mysql only 3-byte chars
1810
-		if (preg_match('%(?:
84
+    /** @var string */
85
+    private $fakeRoot = '';
86
+
87
+    /**
88
+     * @var \OCP\Lock\ILockingProvider
89
+     */
90
+    private $lockingProvider;
91
+
92
+    private $lockingEnabled;
93
+
94
+    private $updaterEnabled = true;
95
+
96
+    private $userManager;
97
+
98
+    /**
99
+     * @param string $root
100
+     * @throws \Exception If $root contains an invalid path
101
+     */
102
+    public function __construct($root = '') {
103
+        if (is_null($root)) {
104
+            throw new \InvalidArgumentException('Root can\'t be null');
105
+        }
106
+        if (!Filesystem::isValidPath($root)) {
107
+            throw new \Exception();
108
+        }
109
+
110
+        $this->fakeRoot = $root;
111
+        $this->lockingProvider = \OC::$server->getLockingProvider();
112
+        $this->lockingEnabled = !($this->lockingProvider instanceof \OC\Lock\NoopLockingProvider);
113
+        $this->userManager = \OC::$server->getUserManager();
114
+    }
115
+
116
+    public function getAbsolutePath($path = '/') {
117
+        if ($path === null) {
118
+            return null;
119
+        }
120
+        $this->assertPathLength($path);
121
+        if ($path === '') {
122
+            $path = '/';
123
+        }
124
+        if ($path[0] !== '/') {
125
+            $path = '/' . $path;
126
+        }
127
+        return $this->fakeRoot . $path;
128
+    }
129
+
130
+    /**
131
+     * change the root to a fake root
132
+     *
133
+     * @param string $fakeRoot
134
+     * @return boolean|null
135
+     */
136
+    public function chroot($fakeRoot) {
137
+        if (!$fakeRoot == '') {
138
+            if ($fakeRoot[0] !== '/') {
139
+                $fakeRoot = '/' . $fakeRoot;
140
+            }
141
+        }
142
+        $this->fakeRoot = $fakeRoot;
143
+    }
144
+
145
+    /**
146
+     * get the fake root
147
+     *
148
+     * @return string
149
+     */
150
+    public function getRoot() {
151
+        return $this->fakeRoot;
152
+    }
153
+
154
+    /**
155
+     * get path relative to the root of the view
156
+     *
157
+     * @param string $path
158
+     * @return string
159
+     */
160
+    public function getRelativePath($path) {
161
+        $this->assertPathLength($path);
162
+        if ($this->fakeRoot == '') {
163
+            return $path;
164
+        }
165
+
166
+        if (rtrim($path, '/') === rtrim($this->fakeRoot, '/')) {
167
+            return '/';
168
+        }
169
+
170
+        // missing slashes can cause wrong matches!
171
+        $root = rtrim($this->fakeRoot, '/') . '/';
172
+
173
+        if (strpos($path, $root) !== 0) {
174
+            return null;
175
+        } else {
176
+            $path = substr($path, strlen($this->fakeRoot));
177
+            if (strlen($path) === 0) {
178
+                return '/';
179
+            } else {
180
+                return $path;
181
+            }
182
+        }
183
+    }
184
+
185
+    /**
186
+     * get the mountpoint of the storage object for a path
187
+     * ( note: because a storage is not always mounted inside the fakeroot, the
188
+     * returned mountpoint is relative to the absolute root of the filesystem
189
+     * and does not take the chroot into account )
190
+     *
191
+     * @param string $path
192
+     * @return string
193
+     */
194
+    public function getMountPoint($path) {
195
+        return Filesystem::getMountPoint($this->getAbsolutePath($path));
196
+    }
197
+
198
+    /**
199
+     * get the mountpoint of the storage object for a path
200
+     * ( note: because a storage is not always mounted inside the fakeroot, the
201
+     * returned mountpoint is relative to the absolute root of the filesystem
202
+     * and does not take the chroot into account )
203
+     *
204
+     * @param string $path
205
+     * @return \OCP\Files\Mount\IMountPoint
206
+     */
207
+    public function getMount($path) {
208
+        return Filesystem::getMountManager()->find($this->getAbsolutePath($path));
209
+    }
210
+
211
+    /**
212
+     * resolve a path to a storage and internal path
213
+     *
214
+     * @param string $path
215
+     * @return array an array consisting of the storage and the internal path
216
+     */
217
+    public function resolvePath($path) {
218
+        $a = $this->getAbsolutePath($path);
219
+        $p = Filesystem::normalizePath($a);
220
+        return Filesystem::resolvePath($p);
221
+    }
222
+
223
+    /**
224
+     * return the path to a local version of the file
225
+     * we need this because we can't know if a file is stored local or not from
226
+     * outside the filestorage and for some purposes a local file is needed
227
+     *
228
+     * @param string $path
229
+     * @return string
230
+     */
231
+    public function getLocalFile($path) {
232
+        $parent = substr($path, 0, strrpos($path, '/'));
233
+        $path = $this->getAbsolutePath($path);
234
+        list($storage, $internalPath) = Filesystem::resolvePath($path);
235
+        if (Filesystem::isValidPath($parent) and $storage) {
236
+            return $storage->getLocalFile($internalPath);
237
+        } else {
238
+            return null;
239
+        }
240
+    }
241
+
242
+    /**
243
+     * @param string $path
244
+     * @return string
245
+     */
246
+    public function getLocalFolder($path) {
247
+        $parent = substr($path, 0, strrpos($path, '/'));
248
+        $path = $this->getAbsolutePath($path);
249
+        list($storage, $internalPath) = Filesystem::resolvePath($path);
250
+        if (Filesystem::isValidPath($parent) and $storage) {
251
+            return $storage->getLocalFolder($internalPath);
252
+        } else {
253
+            return null;
254
+        }
255
+    }
256
+
257
+    /**
258
+     * the following functions operate with arguments and return values identical
259
+     * to those of their PHP built-in equivalents. Mostly they are merely wrappers
260
+     * for \OC\Files\Storage\Storage via basicOperation().
261
+     */
262
+    public function mkdir($path) {
263
+        return $this->basicOperation('mkdir', $path, array('create', 'write'));
264
+    }
265
+
266
+    /**
267
+     * remove mount point
268
+     *
269
+     * @param \OC\Files\Mount\MoveableMount $mount
270
+     * @param string $path relative to data/
271
+     * @return boolean
272
+     */
273
+    protected function removeMount($mount, $path) {
274
+        if ($mount instanceof MoveableMount) {
275
+            // cut of /user/files to get the relative path to data/user/files
276
+            $pathParts = explode('/', $path, 4);
277
+            $relPath = '/' . $pathParts[3];
278
+            $this->lockFile($relPath, ILockingProvider::LOCK_SHARED, true);
279
+            \OC_Hook::emit(
280
+                Filesystem::CLASSNAME, "umount",
281
+                array(Filesystem::signal_param_path => $relPath)
282
+            );
283
+            $this->changeLock($relPath, ILockingProvider::LOCK_EXCLUSIVE, true);
284
+            $result = $mount->removeMount();
285
+            $this->changeLock($relPath, ILockingProvider::LOCK_SHARED, true);
286
+            if ($result) {
287
+                \OC_Hook::emit(
288
+                    Filesystem::CLASSNAME, "post_umount",
289
+                    array(Filesystem::signal_param_path => $relPath)
290
+                );
291
+            }
292
+            $this->unlockFile($relPath, ILockingProvider::LOCK_SHARED, true);
293
+            return $result;
294
+        } else {
295
+            // do not allow deleting the storage's root / the mount point
296
+            // because for some storages it might delete the whole contents
297
+            // but isn't supposed to work that way
298
+            return false;
299
+        }
300
+    }
301
+
302
+    public function disableCacheUpdate() {
303
+        $this->updaterEnabled = false;
304
+    }
305
+
306
+    public function enableCacheUpdate() {
307
+        $this->updaterEnabled = true;
308
+    }
309
+
310
+    protected function writeUpdate(Storage $storage, $internalPath, $time = null) {
311
+        if ($this->updaterEnabled) {
312
+            if (is_null($time)) {
313
+                $time = time();
314
+            }
315
+            $storage->getUpdater()->update($internalPath, $time);
316
+        }
317
+    }
318
+
319
+    protected function removeUpdate(Storage $storage, $internalPath) {
320
+        if ($this->updaterEnabled) {
321
+            $storage->getUpdater()->remove($internalPath);
322
+        }
323
+    }
324
+
325
+    protected function renameUpdate(Storage $sourceStorage, Storage $targetStorage, $sourceInternalPath, $targetInternalPath) {
326
+        if ($this->updaterEnabled) {
327
+            $targetStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
328
+        }
329
+    }
330
+
331
+    /**
332
+     * @param string $path
333
+     * @return bool|mixed
334
+     */
335
+    public function rmdir($path) {
336
+        $absolutePath = $this->getAbsolutePath($path);
337
+        $mount = Filesystem::getMountManager()->find($absolutePath);
338
+        if ($mount->getInternalPath($absolutePath) === '') {
339
+            return $this->removeMount($mount, $absolutePath);
340
+        }
341
+        if ($this->is_dir($path)) {
342
+            $result = $this->basicOperation('rmdir', $path, array('delete'));
343
+        } else {
344
+            $result = false;
345
+        }
346
+
347
+        if (!$result && !$this->file_exists($path)) { //clear ghost files from the cache on delete
348
+            $storage = $mount->getStorage();
349
+            $internalPath = $mount->getInternalPath($absolutePath);
350
+            $storage->getUpdater()->remove($internalPath);
351
+        }
352
+        return $result;
353
+    }
354
+
355
+    /**
356
+     * @param string $path
357
+     * @return resource
358
+     */
359
+    public function opendir($path) {
360
+        return $this->basicOperation('opendir', $path, array('read'));
361
+    }
362
+
363
+    /**
364
+     * @param $handle
365
+     * @return mixed
366
+     */
367
+    public function readdir($handle) {
368
+        $fsLocal = new Storage\Local(array('datadir' => '/'));
369
+        return $fsLocal->readdir($handle);
370
+    }
371
+
372
+    /**
373
+     * @param string $path
374
+     * @return bool|mixed
375
+     */
376
+    public function is_dir($path) {
377
+        if ($path == '/') {
378
+            return true;
379
+        }
380
+        return $this->basicOperation('is_dir', $path);
381
+    }
382
+
383
+    /**
384
+     * @param string $path
385
+     * @return bool|mixed
386
+     */
387
+    public function is_file($path) {
388
+        if ($path == '/') {
389
+            return false;
390
+        }
391
+        return $this->basicOperation('is_file', $path);
392
+    }
393
+
394
+    /**
395
+     * @param string $path
396
+     * @return mixed
397
+     */
398
+    public function stat($path) {
399
+        return $this->basicOperation('stat', $path);
400
+    }
401
+
402
+    /**
403
+     * @param string $path
404
+     * @return mixed
405
+     */
406
+    public function filetype($path) {
407
+        return $this->basicOperation('filetype', $path);
408
+    }
409
+
410
+    /**
411
+     * @param string $path
412
+     * @return mixed
413
+     */
414
+    public function filesize($path) {
415
+        return $this->basicOperation('filesize', $path);
416
+    }
417
+
418
+    /**
419
+     * @param string $path
420
+     * @return bool|mixed
421
+     * @throws \OCP\Files\InvalidPathException
422
+     */
423
+    public function readfile($path) {
424
+        $this->assertPathLength($path);
425
+        @ob_end_clean();
426
+        $handle = $this->fopen($path, 'rb');
427
+        if ($handle) {
428
+            $chunkSize = 8192; // 8 kB chunks
429
+            while (!feof($handle)) {
430
+                echo fread($handle, $chunkSize);
431
+                flush();
432
+            }
433
+            $size = $this->filesize($path);
434
+            return $size;
435
+        }
436
+        return false;
437
+    }
438
+
439
+    /**
440
+     * @param string $path
441
+     * @param int $from
442
+     * @param int $to
443
+     * @return bool|mixed
444
+     * @throws \OCP\Files\InvalidPathException
445
+     * @throws \OCP\Files\UnseekableException
446
+     */
447
+    public function readfilePart($path, $from, $to) {
448
+        $this->assertPathLength($path);
449
+        @ob_end_clean();
450
+        $handle = $this->fopen($path, 'rb');
451
+        if ($handle) {
452
+            if (fseek($handle, $from) === 0) {
453
+                $chunkSize = 8192; // 8 kB chunks
454
+                $end = $to + 1;
455
+                while (!feof($handle) && ftell($handle) < $end) {
456
+                    $len = $end - ftell($handle);
457
+                    if ($len > $chunkSize) {
458
+                        $len = $chunkSize;
459
+                    }
460
+                    echo fread($handle, $len);
461
+                    flush();
462
+                }
463
+                $size = ftell($handle) - $from;
464
+                return $size;
465
+            }
466
+
467
+            throw new \OCP\Files\UnseekableException('fseek error');
468
+        }
469
+        return false;
470
+    }
471
+
472
+    /**
473
+     * @param string $path
474
+     * @return mixed
475
+     */
476
+    public function isCreatable($path) {
477
+        return $this->basicOperation('isCreatable', $path);
478
+    }
479
+
480
+    /**
481
+     * @param string $path
482
+     * @return mixed
483
+     */
484
+    public function isReadable($path) {
485
+        return $this->basicOperation('isReadable', $path);
486
+    }
487
+
488
+    /**
489
+     * @param string $path
490
+     * @return mixed
491
+     */
492
+    public function isUpdatable($path) {
493
+        return $this->basicOperation('isUpdatable', $path);
494
+    }
495
+
496
+    /**
497
+     * @param string $path
498
+     * @return bool|mixed
499
+     */
500
+    public function isDeletable($path) {
501
+        $absolutePath = $this->getAbsolutePath($path);
502
+        $mount = Filesystem::getMountManager()->find($absolutePath);
503
+        if ($mount->getInternalPath($absolutePath) === '') {
504
+            return $mount instanceof MoveableMount;
505
+        }
506
+        return $this->basicOperation('isDeletable', $path);
507
+    }
508
+
509
+    /**
510
+     * @param string $path
511
+     * @return mixed
512
+     */
513
+    public function isSharable($path) {
514
+        return $this->basicOperation('isSharable', $path);
515
+    }
516
+
517
+    /**
518
+     * @param string $path
519
+     * @return bool|mixed
520
+     */
521
+    public function file_exists($path) {
522
+        if ($path == '/') {
523
+            return true;
524
+        }
525
+        return $this->basicOperation('file_exists', $path);
526
+    }
527
+
528
+    /**
529
+     * @param string $path
530
+     * @return mixed
531
+     */
532
+    public function filemtime($path) {
533
+        return $this->basicOperation('filemtime', $path);
534
+    }
535
+
536
+    /**
537
+     * @param string $path
538
+     * @param int|string $mtime
539
+     * @return bool
540
+     */
541
+    public function touch($path, $mtime = null) {
542
+        if (!is_null($mtime) and !is_numeric($mtime)) {
543
+            $mtime = strtotime($mtime);
544
+        }
545
+
546
+        $hooks = array('touch');
547
+
548
+        if (!$this->file_exists($path)) {
549
+            $hooks[] = 'create';
550
+            $hooks[] = 'write';
551
+        }
552
+        $result = $this->basicOperation('touch', $path, $hooks, $mtime);
553
+        if (!$result) {
554
+            // If create file fails because of permissions on external storage like SMB folders,
555
+            // check file exists and return false if not.
556
+            if (!$this->file_exists($path)) {
557
+                return false;
558
+            }
559
+            if (is_null($mtime)) {
560
+                $mtime = time();
561
+            }
562
+            //if native touch fails, we emulate it by changing the mtime in the cache
563
+            $this->putFileInfo($path, array('mtime' => $mtime));
564
+        }
565
+        return true;
566
+    }
567
+
568
+    /**
569
+     * @param string $path
570
+     * @return mixed
571
+     */
572
+    public function file_get_contents($path) {
573
+        return $this->basicOperation('file_get_contents', $path, array('read'));
574
+    }
575
+
576
+    /**
577
+     * @param bool $exists
578
+     * @param string $path
579
+     * @param bool $run
580
+     */
581
+    protected function emit_file_hooks_pre($exists, $path, &$run) {
582
+        if (!$exists) {
583
+            \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_create, array(
584
+                Filesystem::signal_param_path => $this->getHookPath($path),
585
+                Filesystem::signal_param_run => &$run,
586
+            ));
587
+        } else {
588
+            \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_update, array(
589
+                Filesystem::signal_param_path => $this->getHookPath($path),
590
+                Filesystem::signal_param_run => &$run,
591
+            ));
592
+        }
593
+        \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_write, array(
594
+            Filesystem::signal_param_path => $this->getHookPath($path),
595
+            Filesystem::signal_param_run => &$run,
596
+        ));
597
+    }
598
+
599
+    /**
600
+     * @param bool $exists
601
+     * @param string $path
602
+     */
603
+    protected function emit_file_hooks_post($exists, $path) {
604
+        if (!$exists) {
605
+            \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_post_create, array(
606
+                Filesystem::signal_param_path => $this->getHookPath($path),
607
+            ));
608
+        } else {
609
+            \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_post_update, array(
610
+                Filesystem::signal_param_path => $this->getHookPath($path),
611
+            ));
612
+        }
613
+        \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_post_write, array(
614
+            Filesystem::signal_param_path => $this->getHookPath($path),
615
+        ));
616
+    }
617
+
618
+    /**
619
+     * @param string $path
620
+     * @param mixed $data
621
+     * @return bool|mixed
622
+     * @throws \Exception
623
+     */
624
+    public function file_put_contents($path, $data) {
625
+        if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier
626
+            $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
627
+            if (Filesystem::isValidPath($path)
628
+                and !Filesystem::isFileBlacklisted($path)
629
+            ) {
630
+                $path = $this->getRelativePath($absolutePath);
631
+
632
+                $this->lockFile($path, ILockingProvider::LOCK_SHARED);
633
+
634
+                $exists = $this->file_exists($path);
635
+                $run = true;
636
+                if ($this->shouldEmitHooks($path)) {
637
+                    $this->emit_file_hooks_pre($exists, $path, $run);
638
+                }
639
+                if (!$run) {
640
+                    $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
641
+                    return false;
642
+                }
643
+
644
+                $this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
645
+
646
+                /** @var \OC\Files\Storage\Storage $storage */
647
+                list($storage, $internalPath) = $this->resolvePath($path);
648
+                $target = $storage->fopen($internalPath, 'w');
649
+                if ($target) {
650
+                    list (, $result) = \OC_Helper::streamCopy($data, $target);
651
+                    fclose($target);
652
+                    fclose($data);
653
+
654
+                    $this->writeUpdate($storage, $internalPath);
655
+
656
+                    $this->changeLock($path, ILockingProvider::LOCK_SHARED);
657
+
658
+                    if ($this->shouldEmitHooks($path) && $result !== false) {
659
+                        $this->emit_file_hooks_post($exists, $path);
660
+                    }
661
+                    $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
662
+                    return $result;
663
+                } else {
664
+                    $this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
665
+                    return false;
666
+                }
667
+            } else {
668
+                return false;
669
+            }
670
+        } else {
671
+            $hooks = ($this->file_exists($path)) ? array('update', 'write') : array('create', 'write');
672
+            return $this->basicOperation('file_put_contents', $path, $hooks, $data);
673
+        }
674
+    }
675
+
676
+    /**
677
+     * @param string $path
678
+     * @return bool|mixed
679
+     */
680
+    public function unlink($path) {
681
+        if ($path === '' || $path === '/') {
682
+            // do not allow deleting the root
683
+            return false;
684
+        }
685
+        $postFix = (substr($path, -1, 1) === '/') ? '/' : '';
686
+        $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
687
+        $mount = Filesystem::getMountManager()->find($absolutePath . $postFix);
688
+        if ($mount and $mount->getInternalPath($absolutePath) === '') {
689
+            return $this->removeMount($mount, $absolutePath);
690
+        }
691
+        $result = $this->basicOperation('unlink', $path, array('delete'));
692
+        if (!$result && !$this->file_exists($path)) { //clear ghost files from the cache on delete
693
+            $storage = $mount->getStorage();
694
+            $internalPath = $mount->getInternalPath($absolutePath);
695
+            $storage->getUpdater()->remove($internalPath);
696
+            return true;
697
+        } else {
698
+            return $result;
699
+        }
700
+    }
701
+
702
+    /**
703
+     * @param string $directory
704
+     * @return bool|mixed
705
+     */
706
+    public function deleteAll($directory) {
707
+        return $this->rmdir($directory);
708
+    }
709
+
710
+    /**
711
+     * Rename/move a file or folder from the source path to target path.
712
+     *
713
+     * @param string $path1 source path
714
+     * @param string $path2 target path
715
+     *
716
+     * @return bool|mixed
717
+     */
718
+    public function rename($path1, $path2) {
719
+        $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1));
720
+        $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2));
721
+        $result = false;
722
+        if (
723
+            Filesystem::isValidPath($path2)
724
+            and Filesystem::isValidPath($path1)
725
+            and !Filesystem::isFileBlacklisted($path2)
726
+        ) {
727
+            $path1 = $this->getRelativePath($absolutePath1);
728
+            $path2 = $this->getRelativePath($absolutePath2);
729
+            $exists = $this->file_exists($path2);
730
+
731
+            if ($path1 == null or $path2 == null) {
732
+                return false;
733
+            }
734
+
735
+            $this->lockFile($path1, ILockingProvider::LOCK_SHARED, true);
736
+            try {
737
+                $this->lockFile($path2, ILockingProvider::LOCK_SHARED, true);
738
+            } catch (LockedException $e) {
739
+                $this->unlockFile($path1, ILockingProvider::LOCK_SHARED);
740
+                throw $e;
741
+            }
742
+
743
+            $run = true;
744
+            if ($this->shouldEmitHooks($path1) && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2))) {
745
+                // if it was a rename from a part file to a regular file it was a write and not a rename operation
746
+                $this->emit_file_hooks_pre($exists, $path2, $run);
747
+            } elseif ($this->shouldEmitHooks($path1)) {
748
+                \OC_Hook::emit(
749
+                    Filesystem::CLASSNAME, Filesystem::signal_rename,
750
+                    array(
751
+                        Filesystem::signal_param_oldpath => $this->getHookPath($path1),
752
+                        Filesystem::signal_param_newpath => $this->getHookPath($path2),
753
+                        Filesystem::signal_param_run => &$run
754
+                    )
755
+                );
756
+            }
757
+            if ($run) {
758
+                $this->verifyPath(dirname($path2), basename($path2));
759
+
760
+                $manager = Filesystem::getMountManager();
761
+                $mount1 = $this->getMount($path1);
762
+                $mount2 = $this->getMount($path2);
763
+                $storage1 = $mount1->getStorage();
764
+                $storage2 = $mount2->getStorage();
765
+                $internalPath1 = $mount1->getInternalPath($absolutePath1);
766
+                $internalPath2 = $mount2->getInternalPath($absolutePath2);
767
+
768
+                $this->changeLock($path1, ILockingProvider::LOCK_EXCLUSIVE, true);
769
+                $this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE, true);
770
+
771
+                if ($internalPath1 === '' and $mount1 instanceof MoveableMount) {
772
+                    if ($this->isTargetAllowed($absolutePath2)) {
773
+                        /**
774
+                         * @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount1
775
+                         */
776
+                        $sourceMountPoint = $mount1->getMountPoint();
777
+                        $result = $mount1->moveMount($absolutePath2);
778
+                        $manager->moveMount($sourceMountPoint, $mount1->getMountPoint());
779
+                    } else {
780
+                        $result = false;
781
+                    }
782
+                    // moving a file/folder within the same mount point
783
+                } elseif ($storage1 === $storage2) {
784
+                    if ($storage1) {
785
+                        $result = $storage1->rename($internalPath1, $internalPath2);
786
+                    } else {
787
+                        $result = false;
788
+                    }
789
+                    // moving a file/folder between storages (from $storage1 to $storage2)
790
+                } else {
791
+                    $result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2);
792
+                }
793
+
794
+                if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) {
795
+                    // if it was a rename from a part file to a regular file it was a write and not a rename operation
796
+
797
+                    $this->writeUpdate($storage2, $internalPath2);
798
+                } else if ($result) {
799
+                    if ($internalPath1 !== '') { // don't do a cache update for moved mounts
800
+                        $this->renameUpdate($storage1, $storage2, $internalPath1, $internalPath2);
801
+                    }
802
+                }
803
+
804
+                $this->changeLock($path1, ILockingProvider::LOCK_SHARED, true);
805
+                $this->changeLock($path2, ILockingProvider::LOCK_SHARED, true);
806
+
807
+                if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) {
808
+                    if ($this->shouldEmitHooks()) {
809
+                        $this->emit_file_hooks_post($exists, $path2);
810
+                    }
811
+                } elseif ($result) {
812
+                    if ($this->shouldEmitHooks($path1) and $this->shouldEmitHooks($path2)) {
813
+                        \OC_Hook::emit(
814
+                            Filesystem::CLASSNAME,
815
+                            Filesystem::signal_post_rename,
816
+                            array(
817
+                                Filesystem::signal_param_oldpath => $this->getHookPath($path1),
818
+                                Filesystem::signal_param_newpath => $this->getHookPath($path2)
819
+                            )
820
+                        );
821
+                    }
822
+                }
823
+            }
824
+            $this->unlockFile($path1, ILockingProvider::LOCK_SHARED, true);
825
+            $this->unlockFile($path2, ILockingProvider::LOCK_SHARED, true);
826
+        }
827
+        return $result;
828
+    }
829
+
830
+    /**
831
+     * Copy a file/folder from the source path to target path
832
+     *
833
+     * @param string $path1 source path
834
+     * @param string $path2 target path
835
+     * @param bool $preserveMtime whether to preserve mtime on the copy
836
+     *
837
+     * @return bool|mixed
838
+     */
839
+    public function copy($path1, $path2, $preserveMtime = false) {
840
+        $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1));
841
+        $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2));
842
+        $result = false;
843
+        if (
844
+            Filesystem::isValidPath($path2)
845
+            and Filesystem::isValidPath($path1)
846
+            and !Filesystem::isFileBlacklisted($path2)
847
+        ) {
848
+            $path1 = $this->getRelativePath($absolutePath1);
849
+            $path2 = $this->getRelativePath($absolutePath2);
850
+
851
+            if ($path1 == null or $path2 == null) {
852
+                return false;
853
+            }
854
+            $run = true;
855
+
856
+            $this->lockFile($path2, ILockingProvider::LOCK_SHARED);
857
+            $this->lockFile($path1, ILockingProvider::LOCK_SHARED);
858
+            $lockTypePath1 = ILockingProvider::LOCK_SHARED;
859
+            $lockTypePath2 = ILockingProvider::LOCK_SHARED;
860
+
861
+            try {
862
+
863
+                $exists = $this->file_exists($path2);
864
+                if ($this->shouldEmitHooks()) {
865
+                    \OC_Hook::emit(
866
+                        Filesystem::CLASSNAME,
867
+                        Filesystem::signal_copy,
868
+                        array(
869
+                            Filesystem::signal_param_oldpath => $this->getHookPath($path1),
870
+                            Filesystem::signal_param_newpath => $this->getHookPath($path2),
871
+                            Filesystem::signal_param_run => &$run
872
+                        )
873
+                    );
874
+                    $this->emit_file_hooks_pre($exists, $path2, $run);
875
+                }
876
+                if ($run) {
877
+                    $mount1 = $this->getMount($path1);
878
+                    $mount2 = $this->getMount($path2);
879
+                    $storage1 = $mount1->getStorage();
880
+                    $internalPath1 = $mount1->getInternalPath($absolutePath1);
881
+                    $storage2 = $mount2->getStorage();
882
+                    $internalPath2 = $mount2->getInternalPath($absolutePath2);
883
+
884
+                    $this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE);
885
+                    $lockTypePath2 = ILockingProvider::LOCK_EXCLUSIVE;
886
+
887
+                    if ($mount1->getMountPoint() == $mount2->getMountPoint()) {
888
+                        if ($storage1) {
889
+                            $result = $storage1->copy($internalPath1, $internalPath2);
890
+                        } else {
891
+                            $result = false;
892
+                        }
893
+                    } else {
894
+                        $result = $storage2->copyFromStorage($storage1, $internalPath1, $internalPath2);
895
+                    }
896
+
897
+                    $this->writeUpdate($storage2, $internalPath2);
898
+
899
+                    $this->changeLock($path2, ILockingProvider::LOCK_SHARED);
900
+                    $lockTypePath2 = ILockingProvider::LOCK_SHARED;
901
+
902
+                    if ($this->shouldEmitHooks() && $result !== false) {
903
+                        \OC_Hook::emit(
904
+                            Filesystem::CLASSNAME,
905
+                            Filesystem::signal_post_copy,
906
+                            array(
907
+                                Filesystem::signal_param_oldpath => $this->getHookPath($path1),
908
+                                Filesystem::signal_param_newpath => $this->getHookPath($path2)
909
+                            )
910
+                        );
911
+                        $this->emit_file_hooks_post($exists, $path2);
912
+                    }
913
+
914
+                }
915
+            } catch (\Exception $e) {
916
+                $this->unlockFile($path2, $lockTypePath2);
917
+                $this->unlockFile($path1, $lockTypePath1);
918
+                throw $e;
919
+            }
920
+
921
+            $this->unlockFile($path2, $lockTypePath2);
922
+            $this->unlockFile($path1, $lockTypePath1);
923
+
924
+        }
925
+        return $result;
926
+    }
927
+
928
+    /**
929
+     * @param string $path
930
+     * @param string $mode
931
+     * @return resource
932
+     */
933
+    public function fopen($path, $mode) {
934
+        $hooks = array();
935
+        switch ($mode) {
936
+            case 'r':
937
+            case 'rb':
938
+                $hooks[] = 'read';
939
+                break;
940
+            case 'r+':
941
+            case 'rb+':
942
+            case 'w+':
943
+            case 'wb+':
944
+            case 'x+':
945
+            case 'xb+':
946
+            case 'a+':
947
+            case 'ab+':
948
+                $hooks[] = 'read';
949
+                $hooks[] = 'write';
950
+                break;
951
+            case 'w':
952
+            case 'wb':
953
+            case 'x':
954
+            case 'xb':
955
+            case 'a':
956
+            case 'ab':
957
+                $hooks[] = 'write';
958
+                break;
959
+            default:
960
+                \OCP\Util::writeLog('core', 'invalid mode (' . $mode . ') for ' . $path, \OCP\Util::ERROR);
961
+        }
962
+
963
+        return $this->basicOperation('fopen', $path, $hooks, $mode);
964
+    }
965
+
966
+    /**
967
+     * @param string $path
968
+     * @return bool|string
969
+     * @throws \OCP\Files\InvalidPathException
970
+     */
971
+    public function toTmpFile($path) {
972
+        $this->assertPathLength($path);
973
+        if (Filesystem::isValidPath($path)) {
974
+            $source = $this->fopen($path, 'r');
975
+            if ($source) {
976
+                $extension = pathinfo($path, PATHINFO_EXTENSION);
977
+                $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($extension);
978
+                file_put_contents($tmpFile, $source);
979
+                return $tmpFile;
980
+            } else {
981
+                return false;
982
+            }
983
+        } else {
984
+            return false;
985
+        }
986
+    }
987
+
988
+    /**
989
+     * @param string $tmpFile
990
+     * @param string $path
991
+     * @return bool|mixed
992
+     * @throws \OCP\Files\InvalidPathException
993
+     */
994
+    public function fromTmpFile($tmpFile, $path) {
995
+        $this->assertPathLength($path);
996
+        if (Filesystem::isValidPath($path)) {
997
+
998
+            // Get directory that the file is going into
999
+            $filePath = dirname($path);
1000
+
1001
+            // Create the directories if any
1002
+            if (!$this->file_exists($filePath)) {
1003
+                $result = $this->createParentDirectories($filePath);
1004
+                if($result === false) {
1005
+                    return false;
1006
+                }
1007
+            }
1008
+
1009
+            $source = fopen($tmpFile, 'r');
1010
+            if ($source) {
1011
+                $result = $this->file_put_contents($path, $source);
1012
+                // $this->file_put_contents() might have already closed
1013
+                // the resource, so we check it, before trying to close it
1014
+                // to avoid messages in the error log.
1015
+                if (is_resource($source)) {
1016
+                    fclose($source);
1017
+                }
1018
+                unlink($tmpFile);
1019
+                return $result;
1020
+            } else {
1021
+                return false;
1022
+            }
1023
+        } else {
1024
+            return false;
1025
+        }
1026
+    }
1027
+
1028
+
1029
+    /**
1030
+     * @param string $path
1031
+     * @return mixed
1032
+     * @throws \OCP\Files\InvalidPathException
1033
+     */
1034
+    public function getMimeType($path) {
1035
+        $this->assertPathLength($path);
1036
+        return $this->basicOperation('getMimeType', $path);
1037
+    }
1038
+
1039
+    /**
1040
+     * @param string $type
1041
+     * @param string $path
1042
+     * @param bool $raw
1043
+     * @return bool|null|string
1044
+     */
1045
+    public function hash($type, $path, $raw = false) {
1046
+        $postFix = (substr($path, -1, 1) === '/') ? '/' : '';
1047
+        $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
1048
+        if (Filesystem::isValidPath($path)) {
1049
+            $path = $this->getRelativePath($absolutePath);
1050
+            if ($path == null) {
1051
+                return false;
1052
+            }
1053
+            if ($this->shouldEmitHooks($path)) {
1054
+                \OC_Hook::emit(
1055
+                    Filesystem::CLASSNAME,
1056
+                    Filesystem::signal_read,
1057
+                    array(Filesystem::signal_param_path => $this->getHookPath($path))
1058
+                );
1059
+            }
1060
+            list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
1061
+            if ($storage) {
1062
+                $result = $storage->hash($type, $internalPath, $raw);
1063
+                return $result;
1064
+            }
1065
+        }
1066
+        return null;
1067
+    }
1068
+
1069
+    /**
1070
+     * @param string $path
1071
+     * @return mixed
1072
+     * @throws \OCP\Files\InvalidPathException
1073
+     */
1074
+    public function free_space($path = '/') {
1075
+        $this->assertPathLength($path);
1076
+        return $this->basicOperation('free_space', $path);
1077
+    }
1078
+
1079
+    /**
1080
+     * abstraction layer for basic filesystem functions: wrapper for \OC\Files\Storage\Storage
1081
+     *
1082
+     * @param string $operation
1083
+     * @param string $path
1084
+     * @param array $hooks (optional)
1085
+     * @param mixed $extraParam (optional)
1086
+     * @return mixed
1087
+     * @throws \Exception
1088
+     *
1089
+     * This method takes requests for basic filesystem functions (e.g. reading & writing
1090
+     * files), processes hooks and proxies, sanitises paths, and finally passes them on to
1091
+     * \OC\Files\Storage\Storage for delegation to a storage backend for execution
1092
+     */
1093
+    private function basicOperation($operation, $path, $hooks = [], $extraParam = null) {
1094
+        $postFix = (substr($path, -1, 1) === '/') ? '/' : '';
1095
+        $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
1096
+        if (Filesystem::isValidPath($path)
1097
+            and !Filesystem::isFileBlacklisted($path)
1098
+        ) {
1099
+            $path = $this->getRelativePath($absolutePath);
1100
+            if ($path == null) {
1101
+                return false;
1102
+            }
1103
+
1104
+            if (in_array('write', $hooks) || in_array('delete', $hooks) || in_array('read', $hooks)) {
1105
+                // always a shared lock during pre-hooks so the hook can read the file
1106
+                $this->lockFile($path, ILockingProvider::LOCK_SHARED);
1107
+            }
1108
+
1109
+            $run = $this->runHooks($hooks, $path);
1110
+            /** @var \OC\Files\Storage\Storage $storage */
1111
+            list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
1112
+            if ($run and $storage) {
1113
+                if (in_array('write', $hooks) || in_array('delete', $hooks)) {
1114
+                    $this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
1115
+                }
1116
+                try {
1117
+                    if (!is_null($extraParam)) {
1118
+                        $result = $storage->$operation($internalPath, $extraParam);
1119
+                    } else {
1120
+                        $result = $storage->$operation($internalPath);
1121
+                    }
1122
+                } catch (\Exception $e) {
1123
+                    if (in_array('write', $hooks) || in_array('delete', $hooks)) {
1124
+                        $this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
1125
+                    } else if (in_array('read', $hooks)) {
1126
+                        $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
1127
+                    }
1128
+                    throw $e;
1129
+                }
1130
+
1131
+                if ($result && in_array('delete', $hooks) and $result) {
1132
+                    $this->removeUpdate($storage, $internalPath);
1133
+                }
1134
+                if ($result && in_array('write', $hooks) and $operation !== 'fopen') {
1135
+                    $this->writeUpdate($storage, $internalPath);
1136
+                }
1137
+                if ($result && in_array('touch', $hooks)) {
1138
+                    $this->writeUpdate($storage, $internalPath, $extraParam);
1139
+                }
1140
+
1141
+                if ((in_array('write', $hooks) || in_array('delete', $hooks)) && ($operation !== 'fopen' || $result === false)) {
1142
+                    $this->changeLock($path, ILockingProvider::LOCK_SHARED);
1143
+                }
1144
+
1145
+                $unlockLater = false;
1146
+                if ($this->lockingEnabled && $operation === 'fopen' && is_resource($result)) {
1147
+                    $unlockLater = true;
1148
+                    $result = CallbackWrapper::wrap($result, null, null, function () use ($hooks, $path) {
1149
+                        if (in_array('write', $hooks)) {
1150
+                            $this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
1151
+                        } else if (in_array('read', $hooks)) {
1152
+                            $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
1153
+                        }
1154
+                    });
1155
+                }
1156
+
1157
+                if ($this->shouldEmitHooks($path) && $result !== false) {
1158
+                    if ($operation != 'fopen') { //no post hooks for fopen, the file stream is still open
1159
+                        $this->runHooks($hooks, $path, true);
1160
+                    }
1161
+                }
1162
+
1163
+                if (!$unlockLater
1164
+                    && (in_array('write', $hooks) || in_array('delete', $hooks) || in_array('read', $hooks))
1165
+                ) {
1166
+                    $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
1167
+                }
1168
+                return $result;
1169
+            } else {
1170
+                $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
1171
+            }
1172
+        }
1173
+        return null;
1174
+    }
1175
+
1176
+    /**
1177
+     * get the path relative to the default root for hook usage
1178
+     *
1179
+     * @param string $path
1180
+     * @return string
1181
+     */
1182
+    private function getHookPath($path) {
1183
+        if (!Filesystem::getView()) {
1184
+            return $path;
1185
+        }
1186
+        return Filesystem::getView()->getRelativePath($this->getAbsolutePath($path));
1187
+    }
1188
+
1189
+    private function shouldEmitHooks($path = '') {
1190
+        if ($path && Cache\Scanner::isPartialFile($path)) {
1191
+            return false;
1192
+        }
1193
+        if (!Filesystem::$loaded) {
1194
+            return false;
1195
+        }
1196
+        $defaultRoot = Filesystem::getRoot();
1197
+        if ($defaultRoot === null) {
1198
+            return false;
1199
+        }
1200
+        if ($this->fakeRoot === $defaultRoot) {
1201
+            return true;
1202
+        }
1203
+        $fullPath = $this->getAbsolutePath($path);
1204
+
1205
+        if ($fullPath === $defaultRoot) {
1206
+            return true;
1207
+        }
1208
+
1209
+        return (strlen($fullPath) > strlen($defaultRoot)) && (substr($fullPath, 0, strlen($defaultRoot) + 1) === $defaultRoot . '/');
1210
+    }
1211
+
1212
+    /**
1213
+     * @param string[] $hooks
1214
+     * @param string $path
1215
+     * @param bool $post
1216
+     * @return bool
1217
+     */
1218
+    private function runHooks($hooks, $path, $post = false) {
1219
+        $relativePath = $path;
1220
+        $path = $this->getHookPath($path);
1221
+        $prefix = ($post) ? 'post_' : '';
1222
+        $run = true;
1223
+        if ($this->shouldEmitHooks($relativePath)) {
1224
+            foreach ($hooks as $hook) {
1225
+                if ($hook != 'read') {
1226
+                    \OC_Hook::emit(
1227
+                        Filesystem::CLASSNAME,
1228
+                        $prefix . $hook,
1229
+                        array(
1230
+                            Filesystem::signal_param_run => &$run,
1231
+                            Filesystem::signal_param_path => $path
1232
+                        )
1233
+                    );
1234
+                } elseif (!$post) {
1235
+                    \OC_Hook::emit(
1236
+                        Filesystem::CLASSNAME,
1237
+                        $prefix . $hook,
1238
+                        array(
1239
+                            Filesystem::signal_param_path => $path
1240
+                        )
1241
+                    );
1242
+                }
1243
+            }
1244
+        }
1245
+        return $run;
1246
+    }
1247
+
1248
+    /**
1249
+     * check if a file or folder has been updated since $time
1250
+     *
1251
+     * @param string $path
1252
+     * @param int $time
1253
+     * @return bool
1254
+     */
1255
+    public function hasUpdated($path, $time) {
1256
+        return $this->basicOperation('hasUpdated', $path, array(), $time);
1257
+    }
1258
+
1259
+    /**
1260
+     * @param string $ownerId
1261
+     * @return \OC\User\User
1262
+     */
1263
+    private function getUserObjectForOwner($ownerId) {
1264
+        $owner = $this->userManager->get($ownerId);
1265
+        if ($owner instanceof IUser) {
1266
+            return $owner;
1267
+        } else {
1268
+            return new User($ownerId, null);
1269
+        }
1270
+    }
1271
+
1272
+    /**
1273
+     * Get file info from cache
1274
+     *
1275
+     * If the file is not in cached it will be scanned
1276
+     * If the file has changed on storage the cache will be updated
1277
+     *
1278
+     * @param \OC\Files\Storage\Storage $storage
1279
+     * @param string $internalPath
1280
+     * @param string $relativePath
1281
+     * @return array|bool
1282
+     */
1283
+    private function getCacheEntry($storage, $internalPath, $relativePath) {
1284
+        $cache = $storage->getCache($internalPath);
1285
+        $data = $cache->get($internalPath);
1286
+        $watcher = $storage->getWatcher($internalPath);
1287
+
1288
+        try {
1289
+            // if the file is not in the cache or needs to be updated, trigger the scanner and reload the data
1290
+            if (!$data || $data['size'] === -1) {
1291
+                $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
1292
+                if (!$storage->file_exists($internalPath)) {
1293
+                    $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
1294
+                    return false;
1295
+                }
1296
+                $scanner = $storage->getScanner($internalPath);
1297
+                $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
1298
+                $data = $cache->get($internalPath);
1299
+                $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
1300
+            } else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->needsUpdate($internalPath, $data)) {
1301
+                $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
1302
+                $watcher->update($internalPath, $data);
1303
+                $storage->getPropagator()->propagateChange($internalPath, time());
1304
+                $data = $cache->get($internalPath);
1305
+                $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
1306
+            }
1307
+        } catch (LockedException $e) {
1308
+            // if the file is locked we just use the old cache info
1309
+        }
1310
+
1311
+        return $data;
1312
+    }
1313
+
1314
+    /**
1315
+     * get the filesystem info
1316
+     *
1317
+     * @param string $path
1318
+     * @param boolean|string $includeMountPoints true to add mountpoint sizes,
1319
+     * 'ext' to add only ext storage mount point sizes. Defaults to true.
1320
+     * defaults to true
1321
+     * @return \OC\Files\FileInfo|false False if file does not exist
1322
+     */
1323
+    public function getFileInfo($path, $includeMountPoints = true) {
1324
+        $this->assertPathLength($path);
1325
+        if (!Filesystem::isValidPath($path)) {
1326
+            return false;
1327
+        }
1328
+        if (Cache\Scanner::isPartialFile($path)) {
1329
+            return $this->getPartFileInfo($path);
1330
+        }
1331
+        $relativePath = $path;
1332
+        $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
1333
+
1334
+        $mount = Filesystem::getMountManager()->find($path);
1335
+        $storage = $mount->getStorage();
1336
+        $internalPath = $mount->getInternalPath($path);
1337
+        if ($storage) {
1338
+            $data = $this->getCacheEntry($storage, $internalPath, $relativePath);
1339
+
1340
+            if (!$data instanceof ICacheEntry) {
1341
+                return false;
1342
+            }
1343
+
1344
+            if ($mount instanceof MoveableMount && $internalPath === '') {
1345
+                $data['permissions'] |= \OCP\Constants::PERMISSION_DELETE;
1346
+            }
1347
+
1348
+            $owner = $this->getUserObjectForOwner($storage->getOwner($internalPath));
1349
+            $info = new FileInfo($path, $storage, $internalPath, $data, $mount, $owner);
1350
+
1351
+            if ($data and isset($data['fileid'])) {
1352
+                if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {
1353
+                    //add the sizes of other mount points to the folder
1354
+                    $extOnly = ($includeMountPoints === 'ext');
1355
+                    $mounts = Filesystem::getMountManager()->findIn($path);
1356
+                    foreach ($mounts as $mount) {
1357
+                        $subStorage = $mount->getStorage();
1358
+                        if ($subStorage) {
1359
+                            // exclude shared storage ?
1360
+                            if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) {
1361
+                                continue;
1362
+                            }
1363
+                            $subCache = $subStorage->getCache('');
1364
+                            $rootEntry = $subCache->get('');
1365
+                            $info->addSubEntry($rootEntry, $mount->getMountPoint());
1366
+                        }
1367
+                    }
1368
+                }
1369
+            }
1370
+
1371
+            return $info;
1372
+        }
1373
+
1374
+        return false;
1375
+    }
1376
+
1377
+    /**
1378
+     * get the content of a directory
1379
+     *
1380
+     * @param string $directory path under datadirectory
1381
+     * @param string $mimetype_filter limit returned content to this mimetype or mimepart
1382
+     * @return FileInfo[]
1383
+     */
1384
+    public function getDirectoryContent($directory, $mimetype_filter = '') {
1385
+        $this->assertPathLength($directory);
1386
+        if (!Filesystem::isValidPath($directory)) {
1387
+            return [];
1388
+        }
1389
+        $path = $this->getAbsolutePath($directory);
1390
+        $path = Filesystem::normalizePath($path);
1391
+        $mount = $this->getMount($directory);
1392
+        $storage = $mount->getStorage();
1393
+        $internalPath = $mount->getInternalPath($path);
1394
+        if ($storage) {
1395
+            $cache = $storage->getCache($internalPath);
1396
+            $user = \OC_User::getUser();
1397
+
1398
+            $data = $this->getCacheEntry($storage, $internalPath, $directory);
1399
+
1400
+            if (!$data instanceof ICacheEntry || !isset($data['fileid']) || !($data->getPermissions() && Constants::PERMISSION_READ)) {
1401
+                return [];
1402
+            }
1403
+
1404
+            $folderId = $data['fileid'];
1405
+            $contents = $cache->getFolderContentsById($folderId); //TODO: mimetype_filter
1406
+
1407
+            $sharingDisabled = \OCP\Util::isSharingDisabledForUser();
1408
+            /**
1409
+             * @var \OC\Files\FileInfo[] $files
1410
+             */
1411
+            $files = array_map(function (ICacheEntry $content) use ($path, $storage, $mount, $sharingDisabled) {
1412
+                if ($sharingDisabled) {
1413
+                    $content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
1414
+                }
1415
+                $owner = $this->getUserObjectForOwner($storage->getOwner($content['path']));
1416
+                return new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner);
1417
+            }, $contents);
1418
+
1419
+            //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
1420
+            $mounts = Filesystem::getMountManager()->findIn($path);
1421
+            $dirLength = strlen($path);
1422
+            foreach ($mounts as $mount) {
1423
+                $mountPoint = $mount->getMountPoint();
1424
+                $subStorage = $mount->getStorage();
1425
+                if ($subStorage) {
1426
+                    $subCache = $subStorage->getCache('');
1427
+
1428
+                    $rootEntry = $subCache->get('');
1429
+                    if (!$rootEntry) {
1430
+                        $subScanner = $subStorage->getScanner('');
1431
+                        try {
1432
+                            $subScanner->scanFile('');
1433
+                        } catch (\OCP\Files\StorageNotAvailableException $e) {
1434
+                            continue;
1435
+                        } catch (\OCP\Files\StorageInvalidException $e) {
1436
+                            continue;
1437
+                        } catch (\Exception $e) {
1438
+                            // sometimes when the storage is not available it can be any exception
1439
+                            \OCP\Util::writeLog(
1440
+                                'core',
1441
+                                'Exception while scanning storage "' . $subStorage->getId() . '": ' .
1442
+                                get_class($e) . ': ' . $e->getMessage(),
1443
+                                \OCP\Util::ERROR
1444
+                            );
1445
+                            continue;
1446
+                        }
1447
+                        $rootEntry = $subCache->get('');
1448
+                    }
1449
+
1450
+                    if ($rootEntry && ($rootEntry->getPermissions() && Constants::PERMISSION_READ)) {
1451
+                        $relativePath = trim(substr($mountPoint, $dirLength), '/');
1452
+                        if ($pos = strpos($relativePath, '/')) {
1453
+                            //mountpoint inside subfolder add size to the correct folder
1454
+                            $entryName = substr($relativePath, 0, $pos);
1455
+                            foreach ($files as &$entry) {
1456
+                                if ($entry->getName() === $entryName) {
1457
+                                    $entry->addSubEntry($rootEntry, $mountPoint);
1458
+                                }
1459
+                            }
1460
+                        } else { //mountpoint in this folder, add an entry for it
1461
+                            $rootEntry['name'] = $relativePath;
1462
+                            $rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file';
1463
+                            $permissions = $rootEntry['permissions'];
1464
+                            // do not allow renaming/deleting the mount point if they are not shared files/folders
1465
+                            // for shared files/folders we use the permissions given by the owner
1466
+                            if ($mount instanceof MoveableMount) {
1467
+                                $rootEntry['permissions'] = $permissions | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
1468
+                            } else {
1469
+                                $rootEntry['permissions'] = $permissions & (\OCP\Constants::PERMISSION_ALL - (\OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE));
1470
+                            }
1471
+
1472
+                            //remove any existing entry with the same name
1473
+                            foreach ($files as $i => $file) {
1474
+                                if ($file['name'] === $rootEntry['name']) {
1475
+                                    unset($files[$i]);
1476
+                                    break;
1477
+                                }
1478
+                            }
1479
+                            $rootEntry['path'] = substr(Filesystem::normalizePath($path . '/' . $rootEntry['name']), strlen($user) + 2); // full path without /$user/
1480
+
1481
+                            // if sharing was disabled for the user we remove the share permissions
1482
+                            if (\OCP\Util::isSharingDisabledForUser()) {
1483
+                                $rootEntry['permissions'] = $rootEntry['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
1484
+                            }
1485
+
1486
+                            $owner = $this->getUserObjectForOwner($subStorage->getOwner(''));
1487
+                            $files[] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry, $mount, $owner);
1488
+                        }
1489
+                    }
1490
+                }
1491
+            }
1492
+
1493
+            if ($mimetype_filter) {
1494
+                $files = array_filter($files, function (FileInfo $file) use ($mimetype_filter) {
1495
+                    if (strpos($mimetype_filter, '/')) {
1496
+                        return $file->getMimetype() === $mimetype_filter;
1497
+                    } else {
1498
+                        return $file->getMimePart() === $mimetype_filter;
1499
+                    }
1500
+                });
1501
+            }
1502
+
1503
+            return $files;
1504
+        } else {
1505
+            return [];
1506
+        }
1507
+    }
1508
+
1509
+    /**
1510
+     * change file metadata
1511
+     *
1512
+     * @param string $path
1513
+     * @param array|\OCP\Files\FileInfo $data
1514
+     * @return int
1515
+     *
1516
+     * returns the fileid of the updated file
1517
+     */
1518
+    public function putFileInfo($path, $data) {
1519
+        $this->assertPathLength($path);
1520
+        if ($data instanceof FileInfo) {
1521
+            $data = $data->getData();
1522
+        }
1523
+        $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
1524
+        /**
1525
+         * @var \OC\Files\Storage\Storage $storage
1526
+         * @var string $internalPath
1527
+         */
1528
+        list($storage, $internalPath) = Filesystem::resolvePath($path);
1529
+        if ($storage) {
1530
+            $cache = $storage->getCache($path);
1531
+
1532
+            if (!$cache->inCache($internalPath)) {
1533
+                $scanner = $storage->getScanner($internalPath);
1534
+                $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
1535
+            }
1536
+
1537
+            return $cache->put($internalPath, $data);
1538
+        } else {
1539
+            return -1;
1540
+        }
1541
+    }
1542
+
1543
+    /**
1544
+     * search for files with the name matching $query
1545
+     *
1546
+     * @param string $query
1547
+     * @return FileInfo[]
1548
+     */
1549
+    public function search($query) {
1550
+        return $this->searchCommon('search', array('%' . $query . '%'));
1551
+    }
1552
+
1553
+    /**
1554
+     * search for files with the name matching $query
1555
+     *
1556
+     * @param string $query
1557
+     * @return FileInfo[]
1558
+     */
1559
+    public function searchRaw($query) {
1560
+        return $this->searchCommon('search', array($query));
1561
+    }
1562
+
1563
+    /**
1564
+     * search for files by mimetype
1565
+     *
1566
+     * @param string $mimetype
1567
+     * @return FileInfo[]
1568
+     */
1569
+    public function searchByMime($mimetype) {
1570
+        return $this->searchCommon('searchByMime', array($mimetype));
1571
+    }
1572
+
1573
+    /**
1574
+     * search for files by tag
1575
+     *
1576
+     * @param string|int $tag name or tag id
1577
+     * @param string $userId owner of the tags
1578
+     * @return FileInfo[]
1579
+     */
1580
+    public function searchByTag($tag, $userId) {
1581
+        return $this->searchCommon('searchByTag', array($tag, $userId));
1582
+    }
1583
+
1584
+    /**
1585
+     * @param string $method cache method
1586
+     * @param array $args
1587
+     * @return FileInfo[]
1588
+     */
1589
+    private function searchCommon($method, $args) {
1590
+        $files = array();
1591
+        $rootLength = strlen($this->fakeRoot);
1592
+
1593
+        $mount = $this->getMount('');
1594
+        $mountPoint = $mount->getMountPoint();
1595
+        $storage = $mount->getStorage();
1596
+        if ($storage) {
1597
+            $cache = $storage->getCache('');
1598
+
1599
+            $results = call_user_func_array(array($cache, $method), $args);
1600
+            foreach ($results as $result) {
1601
+                if (substr($mountPoint . $result['path'], 0, $rootLength + 1) === $this->fakeRoot . '/') {
1602
+                    $internalPath = $result['path'];
1603
+                    $path = $mountPoint . $result['path'];
1604
+                    $result['path'] = substr($mountPoint . $result['path'], $rootLength);
1605
+                    $owner = \OC::$server->getUserManager()->get($storage->getOwner($internalPath));
1606
+                    $files[] = new FileInfo($path, $storage, $internalPath, $result, $mount, $owner);
1607
+                }
1608
+            }
1609
+
1610
+            $mounts = Filesystem::getMountManager()->findIn($this->fakeRoot);
1611
+            foreach ($mounts as $mount) {
1612
+                $mountPoint = $mount->getMountPoint();
1613
+                $storage = $mount->getStorage();
1614
+                if ($storage) {
1615
+                    $cache = $storage->getCache('');
1616
+
1617
+                    $relativeMountPoint = substr($mountPoint, $rootLength);
1618
+                    $results = call_user_func_array(array($cache, $method), $args);
1619
+                    if ($results) {
1620
+                        foreach ($results as $result) {
1621
+                            $internalPath = $result['path'];
1622
+                            $result['path'] = rtrim($relativeMountPoint . $result['path'], '/');
1623
+                            $path = rtrim($mountPoint . $internalPath, '/');
1624
+                            $owner = \OC::$server->getUserManager()->get($storage->getOwner($internalPath));
1625
+                            $files[] = new FileInfo($path, $storage, $internalPath, $result, $mount, $owner);
1626
+                        }
1627
+                    }
1628
+                }
1629
+            }
1630
+        }
1631
+        return $files;
1632
+    }
1633
+
1634
+    /**
1635
+     * Get the owner for a file or folder
1636
+     *
1637
+     * @param string $path
1638
+     * @return string the user id of the owner
1639
+     * @throws NotFoundException
1640
+     */
1641
+    public function getOwner($path) {
1642
+        $info = $this->getFileInfo($path);
1643
+        if (!$info) {
1644
+            throw new NotFoundException($path . ' not found while trying to get owner');
1645
+        }
1646
+        return $info->getOwner()->getUID();
1647
+    }
1648
+
1649
+    /**
1650
+     * get the ETag for a file or folder
1651
+     *
1652
+     * @param string $path
1653
+     * @return string
1654
+     */
1655
+    public function getETag($path) {
1656
+        /**
1657
+         * @var Storage\Storage $storage
1658
+         * @var string $internalPath
1659
+         */
1660
+        list($storage, $internalPath) = $this->resolvePath($path);
1661
+        if ($storage) {
1662
+            return $storage->getETag($internalPath);
1663
+        } else {
1664
+            return null;
1665
+        }
1666
+    }
1667
+
1668
+    /**
1669
+     * Get the path of a file by id, relative to the view
1670
+     *
1671
+     * Note that the resulting path is not guarantied to be unique for the id, multiple paths can point to the same file
1672
+     *
1673
+     * @param int $id
1674
+     * @throws NotFoundException
1675
+     * @return string
1676
+     */
1677
+    public function getPath($id) {
1678
+        $id = (int)$id;
1679
+        $manager = Filesystem::getMountManager();
1680
+        $mounts = $manager->findIn($this->fakeRoot);
1681
+        $mounts[] = $manager->find($this->fakeRoot);
1682
+        // reverse the array so we start with the storage this view is in
1683
+        // which is the most likely to contain the file we're looking for
1684
+        $mounts = array_reverse($mounts);
1685
+        foreach ($mounts as $mount) {
1686
+            /**
1687
+             * @var \OC\Files\Mount\MountPoint $mount
1688
+             */
1689
+            if ($mount->getStorage()) {
1690
+                $cache = $mount->getStorage()->getCache();
1691
+                $internalPath = $cache->getPathById($id);
1692
+                if (is_string($internalPath)) {
1693
+                    $fullPath = $mount->getMountPoint() . $internalPath;
1694
+                    if (!is_null($path = $this->getRelativePath($fullPath))) {
1695
+                        return $path;
1696
+                    }
1697
+                }
1698
+            }
1699
+        }
1700
+        throw new NotFoundException(sprintf('File with id "%s" has not been found.', $id));
1701
+    }
1702
+
1703
+    /**
1704
+     * @param string $path
1705
+     * @throws InvalidPathException
1706
+     */
1707
+    private function assertPathLength($path) {
1708
+        $maxLen = min(PHP_MAXPATHLEN, 4000);
1709
+        // Check for the string length - performed using isset() instead of strlen()
1710
+        // because isset() is about 5x-40x faster.
1711
+        if (isset($path[$maxLen])) {
1712
+            $pathLen = strlen($path);
1713
+            throw new \OCP\Files\InvalidPathException("Path length($pathLen) exceeds max path length($maxLen): $path");
1714
+        }
1715
+    }
1716
+
1717
+    /**
1718
+     * check if it is allowed to move a mount point to a given target.
1719
+     * It is not allowed to move a mount point into a different mount point or
1720
+     * into an already shared folder
1721
+     *
1722
+     * @param string $target path
1723
+     * @return boolean
1724
+     */
1725
+    private function isTargetAllowed($target) {
1726
+
1727
+        list($targetStorage, $targetInternalPath) = \OC\Files\Filesystem::resolvePath($target);
1728
+        if (!$targetStorage->instanceOfStorage('\OCP\Files\IHomeStorage')) {
1729
+            \OCP\Util::writeLog('files',
1730
+                'It is not allowed to move one mount point into another one',
1731
+                \OCP\Util::DEBUG);
1732
+            return false;
1733
+        }
1734
+
1735
+        // note: cannot use the view because the target is already locked
1736
+        $fileId = (int)$targetStorage->getCache()->getId($targetInternalPath);
1737
+        if ($fileId === -1) {
1738
+            // target might not exist, need to check parent instead
1739
+            $fileId = (int)$targetStorage->getCache()->getId(dirname($targetInternalPath));
1740
+        }
1741
+
1742
+        // check if any of the parents were shared by the current owner (include collections)
1743
+        $shares = \OCP\Share::getItemShared(
1744
+            'folder',
1745
+            $fileId,
1746
+            \OCP\Share::FORMAT_NONE,
1747
+            null,
1748
+            true
1749
+        );
1750
+
1751
+        if (count($shares) > 0) {
1752
+            \OCP\Util::writeLog('files',
1753
+                'It is not allowed to move one mount point into a shared folder',
1754
+                \OCP\Util::DEBUG);
1755
+            return false;
1756
+        }
1757
+
1758
+        return true;
1759
+    }
1760
+
1761
+    /**
1762
+     * Get a fileinfo object for files that are ignored in the cache (part files)
1763
+     *
1764
+     * @param string $path
1765
+     * @return \OCP\Files\FileInfo
1766
+     */
1767
+    private function getPartFileInfo($path) {
1768
+        $mount = $this->getMount($path);
1769
+        $storage = $mount->getStorage();
1770
+        $internalPath = $mount->getInternalPath($this->getAbsolutePath($path));
1771
+        $owner = \OC::$server->getUserManager()->get($storage->getOwner($internalPath));
1772
+        return new FileInfo(
1773
+            $this->getAbsolutePath($path),
1774
+            $storage,
1775
+            $internalPath,
1776
+            [
1777
+                'fileid' => null,
1778
+                'mimetype' => $storage->getMimeType($internalPath),
1779
+                'name' => basename($path),
1780
+                'etag' => null,
1781
+                'size' => $storage->filesize($internalPath),
1782
+                'mtime' => $storage->filemtime($internalPath),
1783
+                'encrypted' => false,
1784
+                'permissions' => \OCP\Constants::PERMISSION_ALL
1785
+            ],
1786
+            $mount,
1787
+            $owner
1788
+        );
1789
+    }
1790
+
1791
+    /**
1792
+     * @param string $path
1793
+     * @param string $fileName
1794
+     * @throws InvalidPathException
1795
+     */
1796
+    public function verifyPath($path, $fileName) {
1797
+
1798
+        $l10n = \OC::$server->getL10N('lib');
1799
+
1800
+        // verify empty and dot files
1801
+        $trimmed = trim($fileName);
1802
+        if ($trimmed === '') {
1803
+            throw new InvalidPathException($l10n->t('Empty filename is not allowed'));
1804
+        }
1805
+        if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) {
1806
+            throw new InvalidPathException($l10n->t('Dot files are not allowed'));
1807
+        }
1808
+
1809
+        // verify database - e.g. mysql only 3-byte chars
1810
+        if (preg_match('%(?:
1811 1811
       \xF0[\x90-\xBF][\x80-\xBF]{2}      # planes 1-3
1812 1812
     | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
1813 1813
     | \xF4[\x80-\x8F][\x80-\xBF]{2}      # plane 16
1814 1814
 )%xs', $fileName)) {
1815
-			throw new InvalidPathException($l10n->t('4-byte characters are not supported in file names'));
1816
-		}
1817
-
1818
-		try {
1819
-			/** @type \OCP\Files\Storage $storage */
1820
-			list($storage, $internalPath) = $this->resolvePath($path);
1821
-			$storage->verifyPath($internalPath, $fileName);
1822
-		} catch (ReservedWordException $ex) {
1823
-			throw new InvalidPathException($l10n->t('File name is a reserved word'));
1824
-		} catch (InvalidCharacterInPathException $ex) {
1825
-			throw new InvalidPathException($l10n->t('File name contains at least one invalid character'));
1826
-		} catch (FileNameTooLongException $ex) {
1827
-			throw new InvalidPathException($l10n->t('File name is too long'));
1828
-		}
1829
-	}
1830
-
1831
-	/**
1832
-	 * get all parent folders of $path
1833
-	 *
1834
-	 * @param string $path
1835
-	 * @return string[]
1836
-	 */
1837
-	private function getParents($path) {
1838
-		$path = trim($path, '/');
1839
-		if (!$path) {
1840
-			return [];
1841
-		}
1842
-
1843
-		$parts = explode('/', $path);
1844
-
1845
-		// remove the single file
1846
-		array_pop($parts);
1847
-		$result = array('/');
1848
-		$resultPath = '';
1849
-		foreach ($parts as $part) {
1850
-			if ($part) {
1851
-				$resultPath .= '/' . $part;
1852
-				$result[] = $resultPath;
1853
-			}
1854
-		}
1855
-		return $result;
1856
-	}
1857
-
1858
-	/**
1859
-	 * Returns the mount point for which to lock
1860
-	 *
1861
-	 * @param string $absolutePath absolute path
1862
-	 * @param bool $useParentMount true to return parent mount instead of whatever
1863
-	 * is mounted directly on the given path, false otherwise
1864
-	 * @return \OC\Files\Mount\MountPoint mount point for which to apply locks
1865
-	 */
1866
-	private function getMountForLock($absolutePath, $useParentMount = false) {
1867
-		$results = [];
1868
-		$mount = Filesystem::getMountManager()->find($absolutePath);
1869
-		if (!$mount) {
1870
-			return $results;
1871
-		}
1872
-
1873
-		if ($useParentMount) {
1874
-			// find out if something is mounted directly on the path
1875
-			$internalPath = $mount->getInternalPath($absolutePath);
1876
-			if ($internalPath === '') {
1877
-				// resolve the parent mount instead
1878
-				$mount = Filesystem::getMountManager()->find(dirname($absolutePath));
1879
-			}
1880
-		}
1881
-
1882
-		return $mount;
1883
-	}
1884
-
1885
-	/**
1886
-	 * Lock the given path
1887
-	 *
1888
-	 * @param string $path the path of the file to lock, relative to the view
1889
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
1890
-	 * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
1891
-	 *
1892
-	 * @return bool False if the path is excluded from locking, true otherwise
1893
-	 * @throws \OCP\Lock\LockedException if the path is already locked
1894
-	 */
1895
-	private function lockPath($path, $type, $lockMountPoint = false) {
1896
-		$absolutePath = $this->getAbsolutePath($path);
1897
-		$absolutePath = Filesystem::normalizePath($absolutePath);
1898
-		if (!$this->shouldLockFile($absolutePath)) {
1899
-			return false;
1900
-		}
1901
-
1902
-		$mount = $this->getMountForLock($absolutePath, $lockMountPoint);
1903
-		if ($mount) {
1904
-			try {
1905
-				$storage = $mount->getStorage();
1906
-				if ($storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
1907
-					$storage->acquireLock(
1908
-						$mount->getInternalPath($absolutePath),
1909
-						$type,
1910
-						$this->lockingProvider
1911
-					);
1912
-				}
1913
-			} catch (\OCP\Lock\LockedException $e) {
1914
-				// rethrow with the a human-readable path
1915
-				throw new \OCP\Lock\LockedException(
1916
-					$this->getPathRelativeToFiles($absolutePath),
1917
-					$e
1918
-				);
1919
-			}
1920
-		}
1921
-
1922
-		return true;
1923
-	}
1924
-
1925
-	/**
1926
-	 * Change the lock type
1927
-	 *
1928
-	 * @param string $path the path of the file to lock, relative to the view
1929
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
1930
-	 * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
1931
-	 *
1932
-	 * @return bool False if the path is excluded from locking, true otherwise
1933
-	 * @throws \OCP\Lock\LockedException if the path is already locked
1934
-	 */
1935
-	public function changeLock($path, $type, $lockMountPoint = false) {
1936
-		$path = Filesystem::normalizePath($path);
1937
-		$absolutePath = $this->getAbsolutePath($path);
1938
-		$absolutePath = Filesystem::normalizePath($absolutePath);
1939
-		if (!$this->shouldLockFile($absolutePath)) {
1940
-			return false;
1941
-		}
1942
-
1943
-		$mount = $this->getMountForLock($absolutePath, $lockMountPoint);
1944
-		if ($mount) {
1945
-			try {
1946
-				$storage = $mount->getStorage();
1947
-				if ($storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
1948
-					$storage->changeLock(
1949
-						$mount->getInternalPath($absolutePath),
1950
-						$type,
1951
-						$this->lockingProvider
1952
-					);
1953
-				}
1954
-			} catch (\OCP\Lock\LockedException $e) {
1955
-				// rethrow with the a human-readable path
1956
-				throw new \OCP\Lock\LockedException(
1957
-					$this->getPathRelativeToFiles($absolutePath),
1958
-					$e
1959
-				);
1960
-			}
1961
-		}
1962
-
1963
-		return true;
1964
-	}
1965
-
1966
-	/**
1967
-	 * Unlock the given path
1968
-	 *
1969
-	 * @param string $path the path of the file to unlock, relative to the view
1970
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
1971
-	 * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
1972
-	 *
1973
-	 * @return bool False if the path is excluded from locking, true otherwise
1974
-	 */
1975
-	private function unlockPath($path, $type, $lockMountPoint = false) {
1976
-		$absolutePath = $this->getAbsolutePath($path);
1977
-		$absolutePath = Filesystem::normalizePath($absolutePath);
1978
-		if (!$this->shouldLockFile($absolutePath)) {
1979
-			return false;
1980
-		}
1981
-
1982
-		$mount = $this->getMountForLock($absolutePath, $lockMountPoint);
1983
-		if ($mount) {
1984
-			$storage = $mount->getStorage();
1985
-			if ($storage && $storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
1986
-				$storage->releaseLock(
1987
-					$mount->getInternalPath($absolutePath),
1988
-					$type,
1989
-					$this->lockingProvider
1990
-				);
1991
-			}
1992
-		}
1993
-
1994
-		return true;
1995
-	}
1996
-
1997
-	/**
1998
-	 * Lock a path and all its parents up to the root of the view
1999
-	 *
2000
-	 * @param string $path the path of the file to lock relative to the view
2001
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
2002
-	 * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
2003
-	 *
2004
-	 * @return bool False if the path is excluded from locking, true otherwise
2005
-	 */
2006
-	public function lockFile($path, $type, $lockMountPoint = false) {
2007
-		$absolutePath = $this->getAbsolutePath($path);
2008
-		$absolutePath = Filesystem::normalizePath($absolutePath);
2009
-		if (!$this->shouldLockFile($absolutePath)) {
2010
-			return false;
2011
-		}
2012
-
2013
-		$this->lockPath($path, $type, $lockMountPoint);
2014
-
2015
-		$parents = $this->getParents($path);
2016
-		foreach ($parents as $parent) {
2017
-			$this->lockPath($parent, ILockingProvider::LOCK_SHARED);
2018
-		}
2019
-
2020
-		return true;
2021
-	}
2022
-
2023
-	/**
2024
-	 * Unlock a path and all its parents up to the root of the view
2025
-	 *
2026
-	 * @param string $path the path of the file to lock relative to the view
2027
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
2028
-	 * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
2029
-	 *
2030
-	 * @return bool False if the path is excluded from locking, true otherwise
2031
-	 */
2032
-	public function unlockFile($path, $type, $lockMountPoint = false) {
2033
-		$absolutePath = $this->getAbsolutePath($path);
2034
-		$absolutePath = Filesystem::normalizePath($absolutePath);
2035
-		if (!$this->shouldLockFile($absolutePath)) {
2036
-			return false;
2037
-		}
2038
-
2039
-		$this->unlockPath($path, $type, $lockMountPoint);
2040
-
2041
-		$parents = $this->getParents($path);
2042
-		foreach ($parents as $parent) {
2043
-			$this->unlockPath($parent, ILockingProvider::LOCK_SHARED);
2044
-		}
2045
-
2046
-		return true;
2047
-	}
2048
-
2049
-	/**
2050
-	 * Only lock files in data/user/files/
2051
-	 *
2052
-	 * @param string $path Absolute path to the file/folder we try to (un)lock
2053
-	 * @return bool
2054
-	 */
2055
-	protected function shouldLockFile($path) {
2056
-		$path = Filesystem::normalizePath($path);
2057
-
2058
-		$pathSegments = explode('/', $path);
2059
-		if (isset($pathSegments[2])) {
2060
-			// E.g.: /username/files/path-to-file
2061
-			return ($pathSegments[2] === 'files') && (count($pathSegments) > 3);
2062
-		}
2063
-
2064
-		return true;
2065
-	}
2066
-
2067
-	/**
2068
-	 * Shortens the given absolute path to be relative to
2069
-	 * "$user/files".
2070
-	 *
2071
-	 * @param string $absolutePath absolute path which is under "files"
2072
-	 *
2073
-	 * @return string path relative to "files" with trimmed slashes or null
2074
-	 * if the path was NOT relative to files
2075
-	 *
2076
-	 * @throws \InvalidArgumentException if the given path was not under "files"
2077
-	 * @since 8.1.0
2078
-	 */
2079
-	public function getPathRelativeToFiles($absolutePath) {
2080
-		$path = Filesystem::normalizePath($absolutePath);
2081
-		$parts = explode('/', trim($path, '/'), 3);
2082
-		// "$user", "files", "path/to/dir"
2083
-		if (!isset($parts[1]) || $parts[1] !== 'files') {
2084
-			throw new \InvalidArgumentException('$absolutePath must be relative to "files"');
2085
-		}
2086
-		if (isset($parts[2])) {
2087
-			return $parts[2];
2088
-		}
2089
-		return '';
2090
-	}
2091
-
2092
-	/**
2093
-	 * @param string $filename
2094
-	 * @return array
2095
-	 * @throws \OC\User\NoUserException
2096
-	 * @throws NotFoundException
2097
-	 */
2098
-	public function getUidAndFilename($filename) {
2099
-		$info = $this->getFileInfo($filename);
2100
-		if (!$info instanceof \OCP\Files\FileInfo) {
2101
-			throw new NotFoundException($this->getAbsolutePath($filename) . ' not found');
2102
-		}
2103
-		$uid = $info->getOwner()->getUID();
2104
-		if ($uid != \OCP\User::getUser()) {
2105
-			Filesystem::initMountPoints($uid);
2106
-			$ownerView = new View('/' . $uid . '/files');
2107
-			try {
2108
-				$filename = $ownerView->getPath($info['fileid']);
2109
-			} catch (NotFoundException $e) {
2110
-				throw new NotFoundException('File with id ' . $info['fileid'] . ' not found for user ' . $uid);
2111
-			}
2112
-		}
2113
-		return [$uid, $filename];
2114
-	}
2115
-
2116
-	/**
2117
-	 * Creates parent non-existing folders
2118
-	 *
2119
-	 * @param string $filePath
2120
-	 * @return bool
2121
-	 */
2122
-	private function createParentDirectories($filePath) {
2123
-		$directoryParts = explode('/', $filePath);
2124
-		$directoryParts = array_filter($directoryParts);
2125
-		foreach($directoryParts as $key => $part) {
2126
-			$currentPathElements = array_slice($directoryParts, 0, $key);
2127
-			$currentPath = '/' . implode('/', $currentPathElements);
2128
-			if($this->is_file($currentPath)) {
2129
-				return false;
2130
-			}
2131
-			if(!$this->file_exists($currentPath)) {
2132
-				$this->mkdir($currentPath);
2133
-			}
2134
-		}
2135
-
2136
-		return true;
2137
-	}
1815
+            throw new InvalidPathException($l10n->t('4-byte characters are not supported in file names'));
1816
+        }
1817
+
1818
+        try {
1819
+            /** @type \OCP\Files\Storage $storage */
1820
+            list($storage, $internalPath) = $this->resolvePath($path);
1821
+            $storage->verifyPath($internalPath, $fileName);
1822
+        } catch (ReservedWordException $ex) {
1823
+            throw new InvalidPathException($l10n->t('File name is a reserved word'));
1824
+        } catch (InvalidCharacterInPathException $ex) {
1825
+            throw new InvalidPathException($l10n->t('File name contains at least one invalid character'));
1826
+        } catch (FileNameTooLongException $ex) {
1827
+            throw new InvalidPathException($l10n->t('File name is too long'));
1828
+        }
1829
+    }
1830
+
1831
+    /**
1832
+     * get all parent folders of $path
1833
+     *
1834
+     * @param string $path
1835
+     * @return string[]
1836
+     */
1837
+    private function getParents($path) {
1838
+        $path = trim($path, '/');
1839
+        if (!$path) {
1840
+            return [];
1841
+        }
1842
+
1843
+        $parts = explode('/', $path);
1844
+
1845
+        // remove the single file
1846
+        array_pop($parts);
1847
+        $result = array('/');
1848
+        $resultPath = '';
1849
+        foreach ($parts as $part) {
1850
+            if ($part) {
1851
+                $resultPath .= '/' . $part;
1852
+                $result[] = $resultPath;
1853
+            }
1854
+        }
1855
+        return $result;
1856
+    }
1857
+
1858
+    /**
1859
+     * Returns the mount point for which to lock
1860
+     *
1861
+     * @param string $absolutePath absolute path
1862
+     * @param bool $useParentMount true to return parent mount instead of whatever
1863
+     * is mounted directly on the given path, false otherwise
1864
+     * @return \OC\Files\Mount\MountPoint mount point for which to apply locks
1865
+     */
1866
+    private function getMountForLock($absolutePath, $useParentMount = false) {
1867
+        $results = [];
1868
+        $mount = Filesystem::getMountManager()->find($absolutePath);
1869
+        if (!$mount) {
1870
+            return $results;
1871
+        }
1872
+
1873
+        if ($useParentMount) {
1874
+            // find out if something is mounted directly on the path
1875
+            $internalPath = $mount->getInternalPath($absolutePath);
1876
+            if ($internalPath === '') {
1877
+                // resolve the parent mount instead
1878
+                $mount = Filesystem::getMountManager()->find(dirname($absolutePath));
1879
+            }
1880
+        }
1881
+
1882
+        return $mount;
1883
+    }
1884
+
1885
+    /**
1886
+     * Lock the given path
1887
+     *
1888
+     * @param string $path the path of the file to lock, relative to the view
1889
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
1890
+     * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
1891
+     *
1892
+     * @return bool False if the path is excluded from locking, true otherwise
1893
+     * @throws \OCP\Lock\LockedException if the path is already locked
1894
+     */
1895
+    private function lockPath($path, $type, $lockMountPoint = false) {
1896
+        $absolutePath = $this->getAbsolutePath($path);
1897
+        $absolutePath = Filesystem::normalizePath($absolutePath);
1898
+        if (!$this->shouldLockFile($absolutePath)) {
1899
+            return false;
1900
+        }
1901
+
1902
+        $mount = $this->getMountForLock($absolutePath, $lockMountPoint);
1903
+        if ($mount) {
1904
+            try {
1905
+                $storage = $mount->getStorage();
1906
+                if ($storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
1907
+                    $storage->acquireLock(
1908
+                        $mount->getInternalPath($absolutePath),
1909
+                        $type,
1910
+                        $this->lockingProvider
1911
+                    );
1912
+                }
1913
+            } catch (\OCP\Lock\LockedException $e) {
1914
+                // rethrow with the a human-readable path
1915
+                throw new \OCP\Lock\LockedException(
1916
+                    $this->getPathRelativeToFiles($absolutePath),
1917
+                    $e
1918
+                );
1919
+            }
1920
+        }
1921
+
1922
+        return true;
1923
+    }
1924
+
1925
+    /**
1926
+     * Change the lock type
1927
+     *
1928
+     * @param string $path the path of the file to lock, relative to the view
1929
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
1930
+     * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
1931
+     *
1932
+     * @return bool False if the path is excluded from locking, true otherwise
1933
+     * @throws \OCP\Lock\LockedException if the path is already locked
1934
+     */
1935
+    public function changeLock($path, $type, $lockMountPoint = false) {
1936
+        $path = Filesystem::normalizePath($path);
1937
+        $absolutePath = $this->getAbsolutePath($path);
1938
+        $absolutePath = Filesystem::normalizePath($absolutePath);
1939
+        if (!$this->shouldLockFile($absolutePath)) {
1940
+            return false;
1941
+        }
1942
+
1943
+        $mount = $this->getMountForLock($absolutePath, $lockMountPoint);
1944
+        if ($mount) {
1945
+            try {
1946
+                $storage = $mount->getStorage();
1947
+                if ($storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
1948
+                    $storage->changeLock(
1949
+                        $mount->getInternalPath($absolutePath),
1950
+                        $type,
1951
+                        $this->lockingProvider
1952
+                    );
1953
+                }
1954
+            } catch (\OCP\Lock\LockedException $e) {
1955
+                // rethrow with the a human-readable path
1956
+                throw new \OCP\Lock\LockedException(
1957
+                    $this->getPathRelativeToFiles($absolutePath),
1958
+                    $e
1959
+                );
1960
+            }
1961
+        }
1962
+
1963
+        return true;
1964
+    }
1965
+
1966
+    /**
1967
+     * Unlock the given path
1968
+     *
1969
+     * @param string $path the path of the file to unlock, relative to the view
1970
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
1971
+     * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
1972
+     *
1973
+     * @return bool False if the path is excluded from locking, true otherwise
1974
+     */
1975
+    private function unlockPath($path, $type, $lockMountPoint = false) {
1976
+        $absolutePath = $this->getAbsolutePath($path);
1977
+        $absolutePath = Filesystem::normalizePath($absolutePath);
1978
+        if (!$this->shouldLockFile($absolutePath)) {
1979
+            return false;
1980
+        }
1981
+
1982
+        $mount = $this->getMountForLock($absolutePath, $lockMountPoint);
1983
+        if ($mount) {
1984
+            $storage = $mount->getStorage();
1985
+            if ($storage && $storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
1986
+                $storage->releaseLock(
1987
+                    $mount->getInternalPath($absolutePath),
1988
+                    $type,
1989
+                    $this->lockingProvider
1990
+                );
1991
+            }
1992
+        }
1993
+
1994
+        return true;
1995
+    }
1996
+
1997
+    /**
1998
+     * Lock a path and all its parents up to the root of the view
1999
+     *
2000
+     * @param string $path the path of the file to lock relative to the view
2001
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
2002
+     * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
2003
+     *
2004
+     * @return bool False if the path is excluded from locking, true otherwise
2005
+     */
2006
+    public function lockFile($path, $type, $lockMountPoint = false) {
2007
+        $absolutePath = $this->getAbsolutePath($path);
2008
+        $absolutePath = Filesystem::normalizePath($absolutePath);
2009
+        if (!$this->shouldLockFile($absolutePath)) {
2010
+            return false;
2011
+        }
2012
+
2013
+        $this->lockPath($path, $type, $lockMountPoint);
2014
+
2015
+        $parents = $this->getParents($path);
2016
+        foreach ($parents as $parent) {
2017
+            $this->lockPath($parent, ILockingProvider::LOCK_SHARED);
2018
+        }
2019
+
2020
+        return true;
2021
+    }
2022
+
2023
+    /**
2024
+     * Unlock a path and all its parents up to the root of the view
2025
+     *
2026
+     * @param string $path the path of the file to lock relative to the view
2027
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
2028
+     * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage
2029
+     *
2030
+     * @return bool False if the path is excluded from locking, true otherwise
2031
+     */
2032
+    public function unlockFile($path, $type, $lockMountPoint = false) {
2033
+        $absolutePath = $this->getAbsolutePath($path);
2034
+        $absolutePath = Filesystem::normalizePath($absolutePath);
2035
+        if (!$this->shouldLockFile($absolutePath)) {
2036
+            return false;
2037
+        }
2038
+
2039
+        $this->unlockPath($path, $type, $lockMountPoint);
2040
+
2041
+        $parents = $this->getParents($path);
2042
+        foreach ($parents as $parent) {
2043
+            $this->unlockPath($parent, ILockingProvider::LOCK_SHARED);
2044
+        }
2045
+
2046
+        return true;
2047
+    }
2048
+
2049
+    /**
2050
+     * Only lock files in data/user/files/
2051
+     *
2052
+     * @param string $path Absolute path to the file/folder we try to (un)lock
2053
+     * @return bool
2054
+     */
2055
+    protected function shouldLockFile($path) {
2056
+        $path = Filesystem::normalizePath($path);
2057
+
2058
+        $pathSegments = explode('/', $path);
2059
+        if (isset($pathSegments[2])) {
2060
+            // E.g.: /username/files/path-to-file
2061
+            return ($pathSegments[2] === 'files') && (count($pathSegments) > 3);
2062
+        }
2063
+
2064
+        return true;
2065
+    }
2066
+
2067
+    /**
2068
+     * Shortens the given absolute path to be relative to
2069
+     * "$user/files".
2070
+     *
2071
+     * @param string $absolutePath absolute path which is under "files"
2072
+     *
2073
+     * @return string path relative to "files" with trimmed slashes or null
2074
+     * if the path was NOT relative to files
2075
+     *
2076
+     * @throws \InvalidArgumentException if the given path was not under "files"
2077
+     * @since 8.1.0
2078
+     */
2079
+    public function getPathRelativeToFiles($absolutePath) {
2080
+        $path = Filesystem::normalizePath($absolutePath);
2081
+        $parts = explode('/', trim($path, '/'), 3);
2082
+        // "$user", "files", "path/to/dir"
2083
+        if (!isset($parts[1]) || $parts[1] !== 'files') {
2084
+            throw new \InvalidArgumentException('$absolutePath must be relative to "files"');
2085
+        }
2086
+        if (isset($parts[2])) {
2087
+            return $parts[2];
2088
+        }
2089
+        return '';
2090
+    }
2091
+
2092
+    /**
2093
+     * @param string $filename
2094
+     * @return array
2095
+     * @throws \OC\User\NoUserException
2096
+     * @throws NotFoundException
2097
+     */
2098
+    public function getUidAndFilename($filename) {
2099
+        $info = $this->getFileInfo($filename);
2100
+        if (!$info instanceof \OCP\Files\FileInfo) {
2101
+            throw new NotFoundException($this->getAbsolutePath($filename) . ' not found');
2102
+        }
2103
+        $uid = $info->getOwner()->getUID();
2104
+        if ($uid != \OCP\User::getUser()) {
2105
+            Filesystem::initMountPoints($uid);
2106
+            $ownerView = new View('/' . $uid . '/files');
2107
+            try {
2108
+                $filename = $ownerView->getPath($info['fileid']);
2109
+            } catch (NotFoundException $e) {
2110
+                throw new NotFoundException('File with id ' . $info['fileid'] . ' not found for user ' . $uid);
2111
+            }
2112
+        }
2113
+        return [$uid, $filename];
2114
+    }
2115
+
2116
+    /**
2117
+     * Creates parent non-existing folders
2118
+     *
2119
+     * @param string $filePath
2120
+     * @return bool
2121
+     */
2122
+    private function createParentDirectories($filePath) {
2123
+        $directoryParts = explode('/', $filePath);
2124
+        $directoryParts = array_filter($directoryParts);
2125
+        foreach($directoryParts as $key => $part) {
2126
+            $currentPathElements = array_slice($directoryParts, 0, $key);
2127
+            $currentPath = '/' . implode('/', $currentPathElements);
2128
+            if($this->is_file($currentPath)) {
2129
+                return false;
2130
+            }
2131
+            if(!$this->file_exists($currentPath)) {
2132
+                $this->mkdir($currentPath);
2133
+            }
2134
+        }
2135
+
2136
+        return true;
2137
+    }
2138 2138
 }
Please login to merge, or discard this patch.
Spacing   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -122,9 +122,9 @@  discard block
 block discarded – undo
122 122
 			$path = '/';
123 123
 		}
124 124
 		if ($path[0] !== '/') {
125
-			$path = '/' . $path;
125
+			$path = '/'.$path;
126 126
 		}
127
-		return $this->fakeRoot . $path;
127
+		return $this->fakeRoot.$path;
128 128
 	}
129 129
 
130 130
 	/**
@@ -136,7 +136,7 @@  discard block
 block discarded – undo
136 136
 	public function chroot($fakeRoot) {
137 137
 		if (!$fakeRoot == '') {
138 138
 			if ($fakeRoot[0] !== '/') {
139
-				$fakeRoot = '/' . $fakeRoot;
139
+				$fakeRoot = '/'.$fakeRoot;
140 140
 			}
141 141
 		}
142 142
 		$this->fakeRoot = $fakeRoot;
@@ -168,7 +168,7 @@  discard block
 block discarded – undo
168 168
 		}
169 169
 
170 170
 		// missing slashes can cause wrong matches!
171
-		$root = rtrim($this->fakeRoot, '/') . '/';
171
+		$root = rtrim($this->fakeRoot, '/').'/';
172 172
 
173 173
 		if (strpos($path, $root) !== 0) {
174 174
 			return null;
@@ -274,7 +274,7 @@  discard block
 block discarded – undo
274 274
 		if ($mount instanceof MoveableMount) {
275 275
 			// cut of /user/files to get the relative path to data/user/files
276 276
 			$pathParts = explode('/', $path, 4);
277
-			$relPath = '/' . $pathParts[3];
277
+			$relPath = '/'.$pathParts[3];
278 278
 			$this->lockFile($relPath, ILockingProvider::LOCK_SHARED, true);
279 279
 			\OC_Hook::emit(
280 280
 				Filesystem::CLASSNAME, "umount",
@@ -684,7 +684,7 @@  discard block
 block discarded – undo
684 684
 		}
685 685
 		$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
686 686
 		$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
687
-		$mount = Filesystem::getMountManager()->find($absolutePath . $postFix);
687
+		$mount = Filesystem::getMountManager()->find($absolutePath.$postFix);
688 688
 		if ($mount and $mount->getInternalPath($absolutePath) === '') {
689 689
 			return $this->removeMount($mount, $absolutePath);
690 690
 		}
@@ -957,7 +957,7 @@  discard block
 block discarded – undo
957 957
 				$hooks[] = 'write';
958 958
 				break;
959 959
 			default:
960
-				\OCP\Util::writeLog('core', 'invalid mode (' . $mode . ') for ' . $path, \OCP\Util::ERROR);
960
+				\OCP\Util::writeLog('core', 'invalid mode ('.$mode.') for '.$path, \OCP\Util::ERROR);
961 961
 		}
962 962
 
963 963
 		return $this->basicOperation('fopen', $path, $hooks, $mode);
@@ -1001,7 +1001,7 @@  discard block
 block discarded – undo
1001 1001
 			// Create the directories if any
1002 1002
 			if (!$this->file_exists($filePath)) {
1003 1003
 				$result = $this->createParentDirectories($filePath);
1004
-				if($result === false) {
1004
+				if ($result === false) {
1005 1005
 					return false;
1006 1006
 				}
1007 1007
 			}
@@ -1057,7 +1057,7 @@  discard block
 block discarded – undo
1057 1057
 					array(Filesystem::signal_param_path => $this->getHookPath($path))
1058 1058
 				);
1059 1059
 			}
1060
-			list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
1060
+			list($storage, $internalPath) = Filesystem::resolvePath($absolutePath.$postFix);
1061 1061
 			if ($storage) {
1062 1062
 				$result = $storage->hash($type, $internalPath, $raw);
1063 1063
 				return $result;
@@ -1108,7 +1108,7 @@  discard block
 block discarded – undo
1108 1108
 
1109 1109
 			$run = $this->runHooks($hooks, $path);
1110 1110
 			/** @var \OC\Files\Storage\Storage $storage */
1111
-			list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
1111
+			list($storage, $internalPath) = Filesystem::resolvePath($absolutePath.$postFix);
1112 1112
 			if ($run and $storage) {
1113 1113
 				if (in_array('write', $hooks) || in_array('delete', $hooks)) {
1114 1114
 					$this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
@@ -1145,7 +1145,7 @@  discard block
 block discarded – undo
1145 1145
 				$unlockLater = false;
1146 1146
 				if ($this->lockingEnabled && $operation === 'fopen' && is_resource($result)) {
1147 1147
 					$unlockLater = true;
1148
-					$result = CallbackWrapper::wrap($result, null, null, function () use ($hooks, $path) {
1148
+					$result = CallbackWrapper::wrap($result, null, null, function() use ($hooks, $path) {
1149 1149
 						if (in_array('write', $hooks)) {
1150 1150
 							$this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
1151 1151
 						} else if (in_array('read', $hooks)) {
@@ -1206,7 +1206,7 @@  discard block
 block discarded – undo
1206 1206
 			return true;
1207 1207
 		}
1208 1208
 
1209
-		return (strlen($fullPath) > strlen($defaultRoot)) && (substr($fullPath, 0, strlen($defaultRoot) + 1) === $defaultRoot . '/');
1209
+		return (strlen($fullPath) > strlen($defaultRoot)) && (substr($fullPath, 0, strlen($defaultRoot) + 1) === $defaultRoot.'/');
1210 1210
 	}
1211 1211
 
1212 1212
 	/**
@@ -1225,7 +1225,7 @@  discard block
 block discarded – undo
1225 1225
 				if ($hook != 'read') {
1226 1226
 					\OC_Hook::emit(
1227 1227
 						Filesystem::CLASSNAME,
1228
-						$prefix . $hook,
1228
+						$prefix.$hook,
1229 1229
 						array(
1230 1230
 							Filesystem::signal_param_run => &$run,
1231 1231
 							Filesystem::signal_param_path => $path
@@ -1234,7 +1234,7 @@  discard block
 block discarded – undo
1234 1234
 				} elseif (!$post) {
1235 1235
 					\OC_Hook::emit(
1236 1236
 						Filesystem::CLASSNAME,
1237
-						$prefix . $hook,
1237
+						$prefix.$hook,
1238 1238
 						array(
1239 1239
 							Filesystem::signal_param_path => $path
1240 1240
 						)
@@ -1329,7 +1329,7 @@  discard block
 block discarded – undo
1329 1329
 			return $this->getPartFileInfo($path);
1330 1330
 		}
1331 1331
 		$relativePath = $path;
1332
-		$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
1332
+		$path = Filesystem::normalizePath($this->fakeRoot.'/'.$path);
1333 1333
 
1334 1334
 		$mount = Filesystem::getMountManager()->find($path);
1335 1335
 		$storage = $mount->getStorage();
@@ -1408,12 +1408,12 @@  discard block
 block discarded – undo
1408 1408
 			/**
1409 1409
 			 * @var \OC\Files\FileInfo[] $files
1410 1410
 			 */
1411
-			$files = array_map(function (ICacheEntry $content) use ($path, $storage, $mount, $sharingDisabled) {
1411
+			$files = array_map(function(ICacheEntry $content) use ($path, $storage, $mount, $sharingDisabled) {
1412 1412
 				if ($sharingDisabled) {
1413 1413
 					$content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
1414 1414
 				}
1415 1415
 				$owner = $this->getUserObjectForOwner($storage->getOwner($content['path']));
1416
-				return new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner);
1416
+				return new FileInfo($path.'/'.$content['name'], $storage, $content['path'], $content, $mount, $owner);
1417 1417
 			}, $contents);
1418 1418
 
1419 1419
 			//add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
@@ -1438,8 +1438,8 @@  discard block
 block discarded – undo
1438 1438
 							// sometimes when the storage is not available it can be any exception
1439 1439
 							\OCP\Util::writeLog(
1440 1440
 								'core',
1441
-								'Exception while scanning storage "' . $subStorage->getId() . '": ' .
1442
-								get_class($e) . ': ' . $e->getMessage(),
1441
+								'Exception while scanning storage "'.$subStorage->getId().'": '.
1442
+								get_class($e).': '.$e->getMessage(),
1443 1443
 								\OCP\Util::ERROR
1444 1444
 							);
1445 1445
 							continue;
@@ -1476,7 +1476,7 @@  discard block
 block discarded – undo
1476 1476
 									break;
1477 1477
 								}
1478 1478
 							}
1479
-							$rootEntry['path'] = substr(Filesystem::normalizePath($path . '/' . $rootEntry['name']), strlen($user) + 2); // full path without /$user/
1479
+							$rootEntry['path'] = substr(Filesystem::normalizePath($path.'/'.$rootEntry['name']), strlen($user) + 2); // full path without /$user/
1480 1480
 
1481 1481
 							// if sharing was disabled for the user we remove the share permissions
1482 1482
 							if (\OCP\Util::isSharingDisabledForUser()) {
@@ -1484,14 +1484,14 @@  discard block
 block discarded – undo
1484 1484
 							}
1485 1485
 
1486 1486
 							$owner = $this->getUserObjectForOwner($subStorage->getOwner(''));
1487
-							$files[] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry, $mount, $owner);
1487
+							$files[] = new FileInfo($path.'/'.$rootEntry['name'], $subStorage, '', $rootEntry, $mount, $owner);
1488 1488
 						}
1489 1489
 					}
1490 1490
 				}
1491 1491
 			}
1492 1492
 
1493 1493
 			if ($mimetype_filter) {
1494
-				$files = array_filter($files, function (FileInfo $file) use ($mimetype_filter) {
1494
+				$files = array_filter($files, function(FileInfo $file) use ($mimetype_filter) {
1495 1495
 					if (strpos($mimetype_filter, '/')) {
1496 1496
 						return $file->getMimetype() === $mimetype_filter;
1497 1497
 					} else {
@@ -1520,7 +1520,7 @@  discard block
 block discarded – undo
1520 1520
 		if ($data instanceof FileInfo) {
1521 1521
 			$data = $data->getData();
1522 1522
 		}
1523
-		$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
1523
+		$path = Filesystem::normalizePath($this->fakeRoot.'/'.$path);
1524 1524
 		/**
1525 1525
 		 * @var \OC\Files\Storage\Storage $storage
1526 1526
 		 * @var string $internalPath
@@ -1547,7 +1547,7 @@  discard block
 block discarded – undo
1547 1547
 	 * @return FileInfo[]
1548 1548
 	 */
1549 1549
 	public function search($query) {
1550
-		return $this->searchCommon('search', array('%' . $query . '%'));
1550
+		return $this->searchCommon('search', array('%'.$query.'%'));
1551 1551
 	}
1552 1552
 
1553 1553
 	/**
@@ -1598,10 +1598,10 @@  discard block
 block discarded – undo
1598 1598
 
1599 1599
 			$results = call_user_func_array(array($cache, $method), $args);
1600 1600
 			foreach ($results as $result) {
1601
-				if (substr($mountPoint . $result['path'], 0, $rootLength + 1) === $this->fakeRoot . '/') {
1601
+				if (substr($mountPoint.$result['path'], 0, $rootLength + 1) === $this->fakeRoot.'/') {
1602 1602
 					$internalPath = $result['path'];
1603
-					$path = $mountPoint . $result['path'];
1604
-					$result['path'] = substr($mountPoint . $result['path'], $rootLength);
1603
+					$path = $mountPoint.$result['path'];
1604
+					$result['path'] = substr($mountPoint.$result['path'], $rootLength);
1605 1605
 					$owner = \OC::$server->getUserManager()->get($storage->getOwner($internalPath));
1606 1606
 					$files[] = new FileInfo($path, $storage, $internalPath, $result, $mount, $owner);
1607 1607
 				}
@@ -1619,8 +1619,8 @@  discard block
 block discarded – undo
1619 1619
 					if ($results) {
1620 1620
 						foreach ($results as $result) {
1621 1621
 							$internalPath = $result['path'];
1622
-							$result['path'] = rtrim($relativeMountPoint . $result['path'], '/');
1623
-							$path = rtrim($mountPoint . $internalPath, '/');
1622
+							$result['path'] = rtrim($relativeMountPoint.$result['path'], '/');
1623
+							$path = rtrim($mountPoint.$internalPath, '/');
1624 1624
 							$owner = \OC::$server->getUserManager()->get($storage->getOwner($internalPath));
1625 1625
 							$files[] = new FileInfo($path, $storage, $internalPath, $result, $mount, $owner);
1626 1626
 						}
@@ -1641,7 +1641,7 @@  discard block
 block discarded – undo
1641 1641
 	public function getOwner($path) {
1642 1642
 		$info = $this->getFileInfo($path);
1643 1643
 		if (!$info) {
1644
-			throw new NotFoundException($path . ' not found while trying to get owner');
1644
+			throw new NotFoundException($path.' not found while trying to get owner');
1645 1645
 		}
1646 1646
 		return $info->getOwner()->getUID();
1647 1647
 	}
@@ -1675,7 +1675,7 @@  discard block
 block discarded – undo
1675 1675
 	 * @return string
1676 1676
 	 */
1677 1677
 	public function getPath($id) {
1678
-		$id = (int)$id;
1678
+		$id = (int) $id;
1679 1679
 		$manager = Filesystem::getMountManager();
1680 1680
 		$mounts = $manager->findIn($this->fakeRoot);
1681 1681
 		$mounts[] = $manager->find($this->fakeRoot);
@@ -1690,7 +1690,7 @@  discard block
 block discarded – undo
1690 1690
 				$cache = $mount->getStorage()->getCache();
1691 1691
 				$internalPath = $cache->getPathById($id);
1692 1692
 				if (is_string($internalPath)) {
1693
-					$fullPath = $mount->getMountPoint() . $internalPath;
1693
+					$fullPath = $mount->getMountPoint().$internalPath;
1694 1694
 					if (!is_null($path = $this->getRelativePath($fullPath))) {
1695 1695
 						return $path;
1696 1696
 					}
@@ -1733,10 +1733,10 @@  discard block
 block discarded – undo
1733 1733
 		}
1734 1734
 
1735 1735
 		// note: cannot use the view because the target is already locked
1736
-		$fileId = (int)$targetStorage->getCache()->getId($targetInternalPath);
1736
+		$fileId = (int) $targetStorage->getCache()->getId($targetInternalPath);
1737 1737
 		if ($fileId === -1) {
1738 1738
 			// target might not exist, need to check parent instead
1739
-			$fileId = (int)$targetStorage->getCache()->getId(dirname($targetInternalPath));
1739
+			$fileId = (int) $targetStorage->getCache()->getId(dirname($targetInternalPath));
1740 1740
 		}
1741 1741
 
1742 1742
 		// check if any of the parents were shared by the current owner (include collections)
@@ -1848,7 +1848,7 @@  discard block
 block discarded – undo
1848 1848
 		$resultPath = '';
1849 1849
 		foreach ($parts as $part) {
1850 1850
 			if ($part) {
1851
-				$resultPath .= '/' . $part;
1851
+				$resultPath .= '/'.$part;
1852 1852
 				$result[] = $resultPath;
1853 1853
 			}
1854 1854
 		}
@@ -2098,16 +2098,16 @@  discard block
 block discarded – undo
2098 2098
 	public function getUidAndFilename($filename) {
2099 2099
 		$info = $this->getFileInfo($filename);
2100 2100
 		if (!$info instanceof \OCP\Files\FileInfo) {
2101
-			throw new NotFoundException($this->getAbsolutePath($filename) . ' not found');
2101
+			throw new NotFoundException($this->getAbsolutePath($filename).' not found');
2102 2102
 		}
2103 2103
 		$uid = $info->getOwner()->getUID();
2104 2104
 		if ($uid != \OCP\User::getUser()) {
2105 2105
 			Filesystem::initMountPoints($uid);
2106
-			$ownerView = new View('/' . $uid . '/files');
2106
+			$ownerView = new View('/'.$uid.'/files');
2107 2107
 			try {
2108 2108
 				$filename = $ownerView->getPath($info['fileid']);
2109 2109
 			} catch (NotFoundException $e) {
2110
-				throw new NotFoundException('File with id ' . $info['fileid'] . ' not found for user ' . $uid);
2110
+				throw new NotFoundException('File with id '.$info['fileid'].' not found for user '.$uid);
2111 2111
 			}
2112 2112
 		}
2113 2113
 		return [$uid, $filename];
@@ -2122,13 +2122,13 @@  discard block
 block discarded – undo
2122 2122
 	private function createParentDirectories($filePath) {
2123 2123
 		$directoryParts = explode('/', $filePath);
2124 2124
 		$directoryParts = array_filter($directoryParts);
2125
-		foreach($directoryParts as $key => $part) {
2125
+		foreach ($directoryParts as $key => $part) {
2126 2126
 			$currentPathElements = array_slice($directoryParts, 0, $key);
2127
-			$currentPath = '/' . implode('/', $currentPathElements);
2128
-			if($this->is_file($currentPath)) {
2127
+			$currentPath = '/'.implode('/', $currentPathElements);
2128
+			if ($this->is_file($currentPath)) {
2129 2129
 				return false;
2130 2130
 			}
2131
-			if(!$this->file_exists($currentPath)) {
2131
+			if (!$this->file_exists($currentPath)) {
2132 2132
 				$this->mkdir($currentPath);
2133 2133
 			}
2134 2134
 		}
Please login to merge, or discard this patch.
lib/private/Repair/RemoveOldShares.php 2 patches
Doc Comments   -1 removed lines patch added patch discarded remove patch
@@ -37,7 +37,6 @@
 block discarded – undo
37 37
 	/**
38 38
 	 * RemoveOldCalendarShares constructor.
39 39
 	 *
40
-	 * @param IDBConnection $db
41 40
 	 */
42 41
 	public function __construct(IDBConnection $connection) {
43 42
 		$this->connection = $connection;
Please login to merge, or discard this patch.
Indentation   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -32,73 +32,73 @@
 block discarded – undo
32 32
  */
33 33
 class RemoveOldShares implements IRepairStep {
34 34
 
35
-	/** @var IDBConnection */
36
-	protected $connection;
37
-
38
-	/**
39
-	 * RemoveOldCalendarShares constructor.
40
-	 *
41
-	 * @param IDBConnection $db
42
-	 */
43
-	public function __construct(IDBConnection $connection) {
44
-		$this->connection = $connection;
45
-	}
46
-
47
-	/**
48
-	 * @return string
49
-	 */
50
-	public function getName() {
51
-		return 'Remove old (< 9.0) calendar/contact shares';
52
-	}
53
-
54
-	/**
55
-	 * @param IOutput $output
56
-	 */
57
-	public function run(IOutput $output) {
58
-		$output->startProgress(4);
59
-
60
-		$this->removeCalendarShares($output);
61
-		$this->removeContactShares($output);
62
-
63
-		$output->finishProgress();
64
-	}
65
-
66
-	/**
67
-	 * @param IOutput $output
68
-	 */
69
-	private function removeCalendarShares(IOutput $output) {
70
-		$qb = $this->connection->getQueryBuilder();
71
-		$qb->delete('share')
72
-			->where($qb->expr()->eq('item_type', $qb->createNamedParameter('calendar')));
73
-		$qb->execute();
74
-
75
-		$output->advance();
76
-
77
-		$qb = $this->connection->getQueryBuilder();
78
-		$qb->delete('share')
79
-			->where($qb->expr()->eq('item_type', $qb->createNamedParameter('event')));
80
-		$qb->execute();
81
-
82
-		$output->advance();
83
-	}
84
-
85
-	/**
86
-	 * @param IOutput $output
87
-	 */
88
-	private function removeContactShares(IOutput $output) {
89
-		$qb = $this->connection->getQueryBuilder();
90
-		$qb->delete('share')
91
-			->where($qb->expr()->eq('item_type', $qb->createNamedParameter('contact')));
92
-		$qb->execute();
93
-
94
-		$output->advance();
95
-
96
-		$qb = $this->connection->getQueryBuilder();
97
-		$qb->delete('share')
98
-			->where($qb->expr()->eq('item_type', $qb->createNamedParameter('addressbook')));
99
-		$qb->execute();
100
-
101
-		$output->advance();
102
-	}
35
+    /** @var IDBConnection */
36
+    protected $connection;
37
+
38
+    /**
39
+     * RemoveOldCalendarShares constructor.
40
+     *
41
+     * @param IDBConnection $db
42
+     */
43
+    public function __construct(IDBConnection $connection) {
44
+        $this->connection = $connection;
45
+    }
46
+
47
+    /**
48
+     * @return string
49
+     */
50
+    public function getName() {
51
+        return 'Remove old (< 9.0) calendar/contact shares';
52
+    }
53
+
54
+    /**
55
+     * @param IOutput $output
56
+     */
57
+    public function run(IOutput $output) {
58
+        $output->startProgress(4);
59
+
60
+        $this->removeCalendarShares($output);
61
+        $this->removeContactShares($output);
62
+
63
+        $output->finishProgress();
64
+    }
65
+
66
+    /**
67
+     * @param IOutput $output
68
+     */
69
+    private function removeCalendarShares(IOutput $output) {
70
+        $qb = $this->connection->getQueryBuilder();
71
+        $qb->delete('share')
72
+            ->where($qb->expr()->eq('item_type', $qb->createNamedParameter('calendar')));
73
+        $qb->execute();
74
+
75
+        $output->advance();
76
+
77
+        $qb = $this->connection->getQueryBuilder();
78
+        $qb->delete('share')
79
+            ->where($qb->expr()->eq('item_type', $qb->createNamedParameter('event')));
80
+        $qb->execute();
81
+
82
+        $output->advance();
83
+    }
84
+
85
+    /**
86
+     * @param IOutput $output
87
+     */
88
+    private function removeContactShares(IOutput $output) {
89
+        $qb = $this->connection->getQueryBuilder();
90
+        $qb->delete('share')
91
+            ->where($qb->expr()->eq('item_type', $qb->createNamedParameter('contact')));
92
+        $qb->execute();
93
+
94
+        $output->advance();
95
+
96
+        $qb = $this->connection->getQueryBuilder();
97
+        $qb->delete('share')
98
+            ->where($qb->expr()->eq('item_type', $qb->createNamedParameter('addressbook')));
99
+        $qb->execute();
100
+
101
+        $output->advance();
102
+    }
103 103
 }
104 104
 
Please login to merge, or discard this patch.