Line | Branch | Exec | Source |
---|---|---|---|
1 | /* Copyright 2023-2024 Jan-Michael Brummer | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU Lesser General Public License as published by | ||
5 | * the Free Software Foundation, either version 3 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU Lesser General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU Lesser General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <libsoup/soup.h> | ||
18 | #include <json-glib/json-glib.h> | ||
19 | |||
20 | #include "msg-authorizer.h" | ||
21 | #include "msg-error.h" | ||
22 | #include "msg-input-stream.h" | ||
23 | #include "msg-private.h" | ||
24 | #include "msg-service.h" | ||
25 | #include "drive/msg-drive.h" | ||
26 | #include "drive/msg-drive-item.h" | ||
27 | #include "drive/msg-drive-item-file.h" | ||
28 | #include "drive/msg-drive-service.h" | ||
29 | |||
30 | struct _MsgDriveService { | ||
31 | MsgService parent_instance; | ||
32 | |||
33 | MsgDriveType type; | ||
34 | }; | ||
35 | |||
36 |
6/7✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 66 times.
|
150 | G_DEFINE_TYPE (MsgDriveService, msg_drive_service, MSG_TYPE_SERVICE); |
37 | |||
38 | static gboolean | ||
39 | 16 | is_valid_name (const char *name) | |
40 | { | ||
41 | 16 | g_auto (GStrv) split = NULL; | |
42 | 16 | const char *invalid_names[] = { | |
43 | ".lock", | ||
44 | "CON", | ||
45 | "PRN", | ||
46 | "AUX", | ||
47 | "NUL", | ||
48 | "COM0", | ||
49 | "COM1", | ||
50 | "COM2", | ||
51 | "COM3", | ||
52 | "COM4", | ||
53 | "COM5", | ||
54 | "COM6", | ||
55 | "COM7", | ||
56 | "COM8", | ||
57 | "COM9", | ||
58 | "LPT0", | ||
59 | "LPT1", | ||
60 | "LPT2", | ||
61 | "LPT3", | ||
62 | "LPT4", | ||
63 | "LPT5", | ||
64 | "LPT6", | ||
65 | "LPT7", | ||
66 | "LPT8", | ||
67 | "LPT9", | ||
68 | "_vti_", | ||
69 | "desktop.ini", | ||
70 | NULL | ||
71 | }; | ||
72 | 32 | g_autofree char *lower_name = g_utf8_strdown (name, -1); | |
73 | |||
74 | /* Check for invalid names */ | ||
75 |
2/2✓ Branch 0 taken 432 times.
✓ Branch 1 taken 16 times.
|
448 | for (int i = 0; invalid_names[i] != NULL; i++) { |
76 |
1/2✓ Branch 2 taken 432 times.
✗ Branch 3 not taken.
|
864 | g_autofree char *invalid_name = g_utf8_strdown (invalid_names[i], -1); |
77 | |||
78 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 432 times.
|
432 | if (g_strcmp0 (lower_name, invalid_name) == 0) |
79 | ✗ | return FALSE; | |
80 | } | ||
81 | |||
82 | /* Leading or Trailing whitespaces are invalid */ | ||
83 |
8/16✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 16 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 16 times.
✓ Branch 14 taken 16 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 16 times.
|
16 | if (g_str_has_prefix (name, " ") || g_str_has_suffix (name, " ")) |
84 | ✗ | return FALSE; | |
85 | |||
86 | /* Must not start with ~$ */ | ||
87 |
4/8✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 16 times.
|
16 | if (g_str_has_prefix (name, "~$")) |
88 | ✗ | return FALSE; | |
89 | |||
90 | /* _vti_ cannot be part of the name */ | ||
91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (strstr (name, "_vti_")) |
92 | ✗ | return FALSE; | |
93 | |||
94 | /* Not allowed chars: " * : < > ? / \ | */ | ||
95 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (strchr (name, '"') || |
96 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | strchr (name, '*') || |
97 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | strchr (name, ':') || |
98 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | strchr (name, '<') || |
99 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | strchr (name, '>') || |
100 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | strchr (name, '?') || |
101 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | strchr (name, '/') || |
102 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | strchr (name, '\\') || |
103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | strchr (name, '|')) |
104 | ✗ | return FALSE; | |
105 | |||
106 | /* "forms" on root level for a library */ | ||
107 | 16 | split = g_strsplit (name, "/", -1); | |
108 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
16 | if (g_strv_length (split) == 2 && g_strcmp0 (split[1], "forms") == 0) |
109 | ✗ | return FALSE; | |
110 | |||
111 | 16 | return TRUE; | |
112 | } | ||
113 | |||
114 | static void | ||
115 | 2 | msg_drive_service_init (__attribute__ ((unused)) MsgDriveService *self) | |
116 | { | ||
117 | 2 | } | |
118 | |||
119 | static void | ||
120 | 3 | msg_drive_service_class_init (__attribute__ ((unused)) MsgDriveServiceClass *class) | |
121 | { | ||
122 | 3 | } | |
123 | |||
124 | /** | ||
125 | * msg_drive_service_new: | ||
126 | * @authorizer: A authorizer | ||
127 | * | ||
128 | * Creates a new `MsgDriveService` using #MsgAuthorizer. | ||
129 | * | ||
130 | * Returns: the newly created `MsgDriveService` | ||
131 | */ | ||
132 | MsgDriveService * | ||
133 | 2 | msg_drive_service_new (MsgAuthorizer *authorizer) | |
134 | { | ||
135 | 2 | return g_object_new (MSG_TYPE_DRIVE_SERVICE, "authorizer", authorizer, NULL); | |
136 | } | ||
137 | |||
138 | /** | ||
139 | * msg_drive_service_get_drives: | ||
140 | * @self: a #MsgDriveService | ||
141 | * @cancellable: a #GCancellable | ||
142 | * @error: a #GError | ||
143 | * | ||
144 | * Queries the Microsoft Graph API for all the drives of the currently logged in user | ||
145 | * | ||
146 | * Returns: (element-type MsgDrive) (transfer full): all drives the user can access | ||
147 | */ | ||
148 | GList * | ||
149 | 10 | msg_drive_service_get_drives (MsgDriveService *self, | |
150 | GCancellable *cancellable, | ||
151 | GError **error) | ||
152 | { | ||
153 | 10 | g_autofree char *url = NULL; | |
154 | 10 | JsonObject *root_object = NULL; | |
155 | 10 | JsonArray *array = NULL; | |
156 | 10 | guint array_length = 0, index = 0; | |
157 | 10 | g_autolist (MsgDrive) list = NULL; | |
158 | 10 | g_autoptr (GBytes) response = NULL; | |
159 | 10 | g_autoptr (JsonParser) parser = NULL; | |
160 | |||
161 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
162 | ✗ | return NULL; | |
163 | |||
164 | 10 | url = g_strconcat (MSG_API_ENDPOINT, "/me/drives", NULL); | |
165 | |||
166 | do { | ||
167 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | g_autoptr (SoupMessage) message = NULL; |
168 | |||
169 | 10 | message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE); | |
170 | 10 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!parser) |
172 | ✗ | return NULL; | |
173 | |||
174 | 10 | array = json_object_get_array_member (root_object, "value"); | |
175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | g_assert (array != NULL); |
176 | |||
177 | 10 | array_length = json_array_get_length (array); | |
178 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
20 | for (index = 0; index < array_length; index++) { |
179 | 10 | MsgDrive *drive = NULL; | |
180 | 10 | JsonObject *drive_object = NULL; | |
181 | 10 | g_autoptr (GError) local_error = NULL; | |
182 | |||
183 | 10 | drive_object = json_array_get_object_element (array, index); | |
184 | 10 | drive = msg_drive_new_from_json (drive_object, &local_error); | |
185 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (drive) { |
186 | 10 | self->type = msg_drive_get_drive_type (drive); | |
187 | 10 | list = g_list_append (list, drive); | |
188 | } else { | ||
189 | ✗ | g_warning ("Could not parse drive object: %s", local_error->message); | |
190 | } | ||
191 | } | ||
192 | |||
193 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | g_clear_pointer (&url, g_free); |
194 | 10 | url = msg_service_get_next_link (root_object); | |
195 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | } while (url != NULL); |
196 | |||
197 | 10 | return g_steal_pointer (&list); | |
198 | } | ||
199 | |||
200 | /** | ||
201 | * msg_drive_service_get_root: | ||
202 | * @self: a #MsgDriveService | ||
203 | * @drive: a #MsgDrive | ||
204 | * @cancellable: a #GCancellable | ||
205 | * @error: a #GError | ||
206 | * | ||
207 | * Get root item of selected drive | ||
208 | * | ||
209 | * Returns: (transfer full): root 'MsgDriveItem' | ||
210 | */ | ||
211 | MsgDriveItem * | ||
212 | 9 | msg_drive_service_get_root (MsgDriveService *self, | |
213 | MsgDrive *drive, | ||
214 | GCancellable *cancellable, | ||
215 | GError **error) | ||
216 | { | ||
217 | 9 | g_autofree char *url = NULL; | |
218 | 9 | g_autoptr (SoupMessage) message = NULL; | |
219 | 9 | JsonObject *root_object = NULL; | |
220 | 9 | g_autoptr (GBytes) response = NULL; | |
221 | 9 | g_autoptr (JsonParser) parser = NULL; | |
222 | |||
223 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
224 | ✗ | return NULL; | |
225 | |||
226 | 9 | url = g_strconcat (MSG_API_ENDPOINT, "/drives/", msg_drive_get_id (drive), "/root?select=id,remoteItem,file,folder,parentReference,name,createdBy,lastModifiedBy,createdDateTime,lastModifiedDateTime,size", NULL); | |
227 | 9 | message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE); | |
228 | 9 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (!parser) |
230 | ✗ | return NULL; | |
231 | |||
232 | 9 | return msg_drive_item_new_from_json (root_object, error); | |
233 | } | ||
234 | |||
235 | /** | ||
236 | * msg_drive_service_download_item: | ||
237 | * @self: a #MsgDriveService | ||
238 | * @item: a #MsgDriveItem | ||
239 | * @cancellable: a #GCancellable | ||
240 | * @error: a #GError | ||
241 | * | ||
242 | * Download item | ||
243 | * | ||
244 | * Returns: (transfer full): input stream of drive item | ||
245 | */ | ||
246 | GInputStream * | ||
247 | 2 | msg_drive_service_download_item (MsgDriveService *self, | |
248 | MsgDriveItem *item, | ||
249 | GCancellable *cancellable, | ||
250 | GError **error) | ||
251 | { | ||
252 | 2 | g_autofree char *url = NULL; | |
253 | 2 | const char *drive_id = NULL; | |
254 | 2 | const char *id = NULL; | |
255 | |||
256 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (!MSG_IS_DRIVE_ITEM_FILE (item)) { |
257 | ✗ | g_warning ("Download only allowed for files"); | |
258 | ✗ | return NULL; | |
259 | } | ||
260 | |||
261 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
262 | ✗ | return NULL; | |
263 | |||
264 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (!msg_drive_item_is_shared (item)) { |
265 | 2 | drive_id = msg_drive_item_get_drive_id (item); | |
266 | 2 | id = msg_drive_item_get_id (item); | |
267 | } else { | ||
268 | ✗ | drive_id = msg_drive_item_get_remote_drive_id (item); | |
269 | ✗ | id = msg_drive_item_get_remote_id (item); | |
270 | } | ||
271 | |||
272 | 2 | url = g_strconcat (MSG_API_ENDPOINT, | |
273 | "/drives/", | ||
274 | drive_id, | ||
275 | "/items/", | ||
276 | id, | ||
277 | "/content", | ||
278 | NULL); | ||
279 | |||
280 | 2 | return msg_input_stream_new (MSG_SERVICE (self), url); | |
281 | } | ||
282 | |||
283 | /** | ||
284 | * msg_drive_service_list_children: | ||
285 | * @self: a #MsgDriveService | ||
286 | * @item: a #MsgDriveItem | ||
287 | * @cancellable: a #GCancellable | ||
288 | * @error: a #GError | ||
289 | * | ||
290 | * Get a list of all files in folder item | ||
291 | * | ||
292 | * Returns: (element-type MsgDriveItem) (transfer full): all items in folder | ||
293 | */ | ||
294 | GList * | ||
295 | 1 | msg_drive_service_list_children (MsgDriveService *self, | |
296 | MsgDriveItem *item, | ||
297 | GCancellable *cancellable, | ||
298 | GError **error) | ||
299 | { | ||
300 | 1 | g_autoptr (MsgDriveItem) child_item = NULL; | |
301 | 1 | g_autofree char *url = NULL; | |
302 | 1 | JsonObject *root_object = NULL; | |
303 | 1 | JsonArray *array = NULL; | |
304 | 1 | guint array_length = 0, index = 0; | |
305 | 1 | JsonObject *item_object = NULL; | |
306 | 1 | g_autolist (MsgDriveItem) children = NULL; | |
307 | 1 | g_autoptr (GBytes) response = NULL; | |
308 | 1 | g_autoptr (JsonParser) parser = NULL; | |
309 | 1 | gboolean add_prefer_header = self->type == MSG_DRIVE_TYPE_BUSINESS; | |
310 | 1 | const char *drive_id = NULL; | |
311 | 1 | const char *id = NULL; | |
312 | |||
313 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
314 | ✗ | return NULL; | |
315 | |||
316 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (!msg_drive_item_is_shared (item)) { |
317 | 1 | drive_id = msg_drive_item_get_drive_id (item); | |
318 | 1 | id = msg_drive_item_get_id (item); | |
319 | } else { | ||
320 | ✗ | drive_id = msg_drive_item_get_remote_drive_id (item); | |
321 | ✗ | id = msg_drive_item_get_remote_id (item); | |
322 | } | ||
323 | |||
324 | 1 | url = g_strconcat (MSG_API_ENDPOINT, | |
325 | "/drives/", | ||
326 | drive_id, | ||
327 | "/items/", | ||
328 | id, | ||
329 | "/children", | ||
330 | "?$expand=thumbnails", | ||
331 | "&select=id,remoteItem,file,folder,parentReference,name,createdBy,lastModifiedBy,createdDateTime,lastModifiedDateTime,size", | ||
332 | NULL); | ||
333 | |||
334 | do { | ||
335 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | g_autoptr (SoupMessage) message = NULL; |
336 | |||
337 | 1 | message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL /*msg_drive_item_get_etag (item)*/, FALSE); | |
338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (add_prefer_header) |
339 | ✗ | soup_message_headers_append (soup_message_get_request_headers (message), "Prefer", "Include-Feature=AddToOneDrive"); | |
340 | |||
341 | 1 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!parser) |
343 | ✗ | return NULL; | |
344 | |||
345 | 1 | array = json_object_get_array_member (root_object, "value"); | |
346 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | g_assert (array != NULL); |
347 | |||
348 | 1 | array_length = json_array_get_length (array); | |
349 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
|
6 | for (index = 0; index < array_length; index++) { |
350 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | g_autoptr (GError) local_error = NULL; |
351 | 5 | item_object = json_array_get_object_element (array, index); | |
352 | |||
353 | 5 | child_item = msg_drive_item_new_from_json (item_object, &local_error); | |
354 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (local_error) { |
355 | ✗ | g_warning ("Could not read child item: %s", local_error->message); | |
356 | ✗ | continue; | |
357 | } | ||
358 | |||
359 | 5 | children = g_list_prepend (children, g_steal_pointer (&child_item)); | |
360 | } | ||
361 | |||
362 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | g_clear_pointer (&url, g_free); |
363 | 1 | url = msg_service_get_next_link (root_object); | |
364 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | } while (url != NULL); |
365 | |||
366 | 1 | return g_steal_pointer (&children); | |
367 | } | ||
368 | |||
369 | /** | ||
370 | * msg_drive_service_rename: | ||
371 | * @self: a #MsgDriveService | ||
372 | * @item: a #MsgDriveItem | ||
373 | * @new_name: new name of item | ||
374 | * @cancellable: a #GCancellable | ||
375 | * @error: a #GError | ||
376 | * | ||
377 | * Sets a new drive item name | ||
378 | * | ||
379 | * Returns: (transfer full): the renamed `MsgDriveItem` | ||
380 | */ | ||
381 | MsgDriveItem * | ||
382 | 1 | msg_drive_service_rename (MsgDriveService *self, | |
383 | MsgDriveItem *item, | ||
384 | const char *new_name, | ||
385 | GCancellable *cancellable, | ||
386 | GError **error) | ||
387 | { | ||
388 | 1 | g_autoptr (SoupMessage) message = NULL; | |
389 | 1 | g_autoptr (JsonBuilder) builder = NULL; | |
390 | 1 | g_autoptr (JsonNode) rename_node = NULL; | |
391 | 1 | g_autofree char *url = NULL; | |
392 | 1 | g_autofree char *json = NULL; | |
393 | 1 | JsonObject *root_object = NULL; | |
394 | 1 | g_autoptr (GBytes) response = NULL; | |
395 | 1 | g_autoptr (GBytes) body = NULL; | |
396 | 1 | g_autoptr (JsonParser) parser = NULL; | |
397 | |||
398 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!is_valid_name (new_name)) { |
399 | ✗ | g_set_error (error, | |
400 | msg_error_quark (), | ||
401 | MSG_ERROR_FAILED, | ||
402 | "Invalid characters in name"); | ||
403 | ✗ | return NULL; | |
404 | } | ||
405 | |||
406 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
407 | ✗ | return NULL; | |
408 | |||
409 | 1 | url = g_strconcat (MSG_API_ENDPOINT, | |
410 | "/drives/", | ||
411 | msg_drive_item_get_drive_id (item), | ||
412 | "/items/", | ||
413 | msg_drive_item_get_id (item), | ||
414 | NULL); | ||
415 | |||
416 | 1 | message = msg_service_build_message (MSG_SERVICE (self), "PATCH", url, NULL, FALSE); | |
417 | |||
418 | 1 | builder = json_builder_new (); | |
419 | 1 | json_builder_begin_object (builder); | |
420 | 1 | json_builder_set_member_name (builder, "name"); | |
421 | 1 | json_builder_add_string_value (builder, new_name); | |
422 | 1 | json_builder_end_object (builder); | |
423 | 1 | rename_node = json_builder_get_root (builder); | |
424 | 1 | json = json_to_string (rename_node, TRUE); | |
425 | |||
426 | 1 | body = g_bytes_new (json, strlen (json)); | |
427 | 1 | soup_message_set_request_body_from_bytes (message, "application/json", body); | |
428 | |||
429 | 1 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
430 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!parser) |
431 | ✗ | return NULL; | |
432 | |||
433 | 1 | return msg_drive_item_new_from_json (root_object, error); | |
434 | } | ||
435 | |||
436 | /** | ||
437 | * msg_drive_service_download_url: | ||
438 | * @self: a #MsgDriveService | ||
439 | * @url: url to download | ||
440 | * @cancellable: a #GCancellable | ||
441 | * @error: a #GError | ||
442 | * | ||
443 | * Download url | ||
444 | * | ||
445 | * Returns: (transfer full): a new `GInputStream` for url | ||
446 | */ | ||
447 | GInputStream * | ||
448 | 1 | msg_drive_service_download_url (MsgDriveService *self, | |
449 | const char *url, | ||
450 | GCancellable *cancellable, | ||
451 | GError **error) | ||
452 | { | ||
453 | 2 | g_autoptr (SoupMessage) message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE); | |
454 | |||
455 | 1 | return msg_service_send (MSG_SERVICE (self), message, cancellable, error); | |
456 | } | ||
457 | |||
458 | /** | ||
459 | * msg_drive_service_create_folder: | ||
460 | * @self: a drive service | ||
461 | * @parent: parent drive item | ||
462 | * @name: name of new folder | ||
463 | * @cancellable: a cancellable | ||
464 | * @error: a error | ||
465 | * | ||
466 | * Creates a new folder called name under parent. | ||
467 | * | ||
468 | * Returns: (transfer full): a newly created `MsgDriveItem` | ||
469 | */ | ||
470 | MsgDriveItem * | ||
471 | 8 | msg_drive_service_create_folder (MsgDriveService *self, | |
472 | MsgDriveItem *parent, | ||
473 | const char *name, | ||
474 | GCancellable *cancellable, | ||
475 | GError **error) | ||
476 | { | ||
477 | 8 | g_autofree char *url = NULL; | |
478 | 8 | g_autoptr (SoupMessage) message = NULL; | |
479 | 8 | g_autofree char *json = NULL; | |
480 | 8 | g_autoptr (JsonBuilder) builder = NULL; | |
481 | 8 | g_autoptr (JsonNode) create_node = NULL; | |
482 | 8 | JsonObject *root_object = NULL; | |
483 | 8 | g_autoptr (GBytes) response = NULL; | |
484 | 8 | g_autoptr (GBytes) body = NULL; | |
485 | 8 | g_autoptr (JsonParser) parser = NULL; | |
486 | |||
487 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
488 | ✗ | return NULL; | |
489 | |||
490 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if (!is_valid_name (name)) { |
491 | ✗ | g_set_error (error, | |
492 | msg_error_quark (), | ||
493 | MSG_ERROR_FAILED, | ||
494 | "Invalid characters in name"); | ||
495 | ✗ | return NULL; | |
496 | } | ||
497 | |||
498 | 8 | url = g_strconcat (MSG_API_ENDPOINT, | |
499 | "/drives/", | ||
500 | msg_drive_item_get_drive_id (parent), | ||
501 | "/items/", | ||
502 | msg_drive_item_get_id (parent), | ||
503 | "/children", | ||
504 | NULL); | ||
505 | |||
506 | 8 | message = msg_service_build_message (MSG_SERVICE (self), "POST", url, NULL, FALSE); | |
507 | |||
508 | 8 | builder = json_builder_new (); | |
509 | 8 | json_builder_begin_object (builder); | |
510 | 8 | json_builder_set_member_name (builder, "name"); | |
511 | 8 | json_builder_add_string_value (builder, name); | |
512 | 8 | json_builder_set_member_name (builder, "@microsoft.graph.conflictBehavior"); | |
513 | 8 | json_builder_add_string_value (builder, "rename"); | |
514 | 8 | json_builder_set_member_name (builder, "folder"); | |
515 | 8 | json_builder_begin_object (builder); | |
516 | 8 | json_builder_end_object (builder); | |
517 | 8 | json_builder_end_object (builder); | |
518 | 8 | create_node = json_builder_get_root (builder); | |
519 | 8 | json = json_to_string (create_node, TRUE); | |
520 | |||
521 | 8 | body = g_bytes_new (json, strlen (json)); | |
522 | 8 | soup_message_set_request_body_from_bytes (message, "application/json", body); | |
523 | |||
524 | 8 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
525 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!parser) |
526 | ✗ | return NULL; | |
527 | |||
528 | 8 | return msg_drive_item_new_from_json (root_object, error); | |
529 | } | ||
530 | |||
531 | /** | ||
532 | * msg_drive_service_delete: | ||
533 | * @self: a drive service | ||
534 | * @item: a #MsgDriveItem | ||
535 | * @cancellable: a cancellable | ||
536 | * @error: a error | ||
537 | * | ||
538 | * Deletes item. | ||
539 | * | ||
540 | * Returns: %TRUE when item has been deleted, otherwise %FALSE | ||
541 | */ | ||
542 | gboolean | ||
543 | 11 | msg_drive_service_delete (MsgDriveService *self, | |
544 | MsgDriveItem *item, | ||
545 | GCancellable *cancellable, | ||
546 | GError **error) | ||
547 | { | ||
548 | 11 | g_autoptr (SoupMessage) message = NULL; | |
549 | 11 | g_autofree char *url = NULL; | |
550 | 11 | g_autoptr (GBytes) bytes = NULL; | |
551 | |||
552 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
|
11 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
553 | ✗ | return FALSE; | |
554 | |||
555 | 11 | url = g_strconcat (MSG_API_ENDPOINT, | |
556 | "/drives/", | ||
557 | msg_drive_item_get_drive_id (item), | ||
558 | "/items/", | ||
559 | msg_drive_item_get_id (item), | ||
560 | NULL); | ||
561 | |||
562 | 11 | message = msg_service_build_message (MSG_SERVICE (self), "DELETE", url, NULL, FALSE); | |
563 | |||
564 | 11 | bytes = msg_service_send_and_read (MSG_SERVICE (self), message, cancellable, error); | |
565 | 11 | return bytes != NULL; | |
566 | } | ||
567 | |||
568 | /** | ||
569 | * msg_drive_service_update: | ||
570 | * @self: a drive service | ||
571 | * @item: a drive item | ||
572 | * @cancellable: a cancellable | ||
573 | * @error: a error | ||
574 | * | ||
575 | * Creates an update stream for drive item in order to update it's content. | ||
576 | * | ||
577 | * Returns: (transfer full): an output stream | ||
578 | */ | ||
579 | GOutputStream * | ||
580 | 7 | msg_drive_service_update (MsgDriveService *self, | |
581 | MsgDriveItem *item, | ||
582 | GCancellable *cancellable, | ||
583 | GError **error) | ||
584 | { | ||
585 | 7 | GOutputStream *stream = NULL; | |
586 | 7 | g_autofree char *url = NULL; | |
587 | 7 | g_autoptr (JsonBuilder) builder = NULL; | |
588 | 7 | g_autoptr (JsonNode) create_node = NULL; | |
589 | 7 | g_autoptr (SoupMessage) message = NULL; | |
590 | 7 | JsonObject *root_object = NULL; | |
591 | 7 | g_autofree char *json = NULL; | |
592 | 7 | g_autoptr (GBytes) response = NULL; | |
593 | 7 | g_autoptr (GBytes) body = NULL; | |
594 | const char *upload_url; | ||
595 | 7 | g_autoptr (JsonParser) parser = NULL; | |
596 | |||
597 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
7 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
598 | ✗ | return NULL; | |
599 | |||
600 | 7 | url = g_strconcat (MSG_API_ENDPOINT, | |
601 | "/drives/", | ||
602 | msg_drive_item_get_drive_id (item), | ||
603 | "/items/", | ||
604 | msg_drive_item_get_id (item), | ||
605 | "/createUploadSession", | ||
606 | NULL); | ||
607 | |||
608 | 7 | message = msg_service_build_message (MSG_SERVICE (self), "POST", url, NULL, FALSE); | |
609 | 7 | builder = json_builder_new (); | |
610 | 7 | json_builder_begin_object (builder); | |
611 | 7 | json_builder_set_member_name (builder, "@microsoft.graph.conflictBehavior"); | |
612 | 7 | json_builder_add_string_value (builder, "rename"); | |
613 | 7 | json_builder_end_object (builder); | |
614 | 7 | create_node = json_builder_get_root (builder); | |
615 | 7 | json = json_to_string (create_node, TRUE); | |
616 | |||
617 | 7 | body = g_bytes_new (json, strlen (json)); | |
618 | 7 | soup_message_set_request_body_from_bytes (message, "application/json", body); | |
619 | |||
620 | 7 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
621 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!parser) |
622 | ✗ | return NULL; | |
623 | |||
624 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | if (!json_object_has_member (root_object, "uploadUrl")) { |
625 | ✗ | g_set_error (error, | |
626 | msg_error_quark (), | ||
627 | MSG_ERROR_FAILED, | ||
628 | "No uploadUrl found"); | ||
629 | ✗ | return NULL; | |
630 | } | ||
631 | |||
632 | 7 | upload_url = json_object_get_string_member (root_object, "uploadUrl"); | |
633 | |||
634 | 7 | stream = g_memory_output_stream_new_resizable (); | |
635 | 7 | g_object_set_data_full (G_OBJECT (stream), "ms-graph-upload-url", g_strdup (upload_url), g_free); | |
636 | 7 | g_object_set_data (G_OBJECT (stream), "ms-graph-item", item); | |
637 | |||
638 | 7 | return stream; | |
639 | } | ||
640 | |||
641 | /** | ||
642 | * msg_drive_service_update_finish: | ||
643 | * @self: a #MsgDriveService | ||
644 | * @item: a #MsgDriveItem | ||
645 | * @stream: stream where data is store and needs to be transfered | ||
646 | * @cancellable: a #GCancellable | ||
647 | * @error: a #GError | ||
648 | * | ||
649 | * Finish a update session of given #item. | ||
650 | * | ||
651 | * Returns: (transfer full): a new #MsgDriveItem or %NULL on error. | ||
652 | */ | ||
653 | MsgDriveItem * | ||
654 | 7 | msg_drive_service_update_finish (MsgDriveService *self, | |
655 | MsgDriveItem *item, | ||
656 | GOutputStream *stream, | ||
657 | GCancellable *cancellable, | ||
658 | GError **error) | ||
659 | { | ||
660 | 7 | g_autoptr (GBytes) bytes; | |
661 | 7 | g_autofree char *url = NULL; | |
662 | 7 | g_autoptr (SoupMessage) message = NULL; | |
663 | 7 | JsonObject *root_object = NULL; | |
664 | 7 | g_autoptr (GBytes) response = NULL; | |
665 | 7 | g_autoptr (JsonParser) parser = NULL; | |
666 | |||
667 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
7 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
668 | ✗ | return NULL; | |
669 | |||
670 | 7 | url = g_strconcat (MSG_API_ENDPOINT, | |
671 | "/drives/", | ||
672 | msg_drive_item_get_drive_id (item), | ||
673 | "/items/", | ||
674 | msg_drive_item_get_id (item), | ||
675 | "/content", | ||
676 | NULL); | ||
677 | |||
678 | 7 | g_output_stream_close (stream, NULL, NULL); | |
679 | 7 | bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream)); | |
680 | |||
681 | 7 | message = msg_service_build_message (MSG_SERVICE (self), "PUT", url, NULL, FALSE); | |
682 | 7 | soup_message_set_request_body_from_bytes (message, "application/octet-stream", bytes); | |
683 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | g_clear_object (&stream); |
684 | |||
685 | 7 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
686 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!parser) |
687 | ✗ | return NULL; | |
688 | |||
689 | 7 | return msg_drive_item_new_from_json (root_object, error); | |
690 | } | ||
691 | |||
692 | /** | ||
693 | * msg_drive_service_add_item_to_folder: | ||
694 | * @self: a msg drive service | ||
695 | * @parent: parent drive item | ||
696 | * @item: drive item to add | ||
697 | * @cancellable: a cancellable | ||
698 | * @error: a error | ||
699 | * | ||
700 | * Adds item to parent folder | ||
701 | * | ||
702 | * Returns: (transfer full): a new drive item | ||
703 | */ | ||
704 | MsgDriveItem * | ||
705 | 7 | msg_drive_service_add_item_to_folder (MsgDriveService *self, | |
706 | MsgDriveItem *parent, | ||
707 | MsgDriveItem *item, | ||
708 | GCancellable *cancellable, | ||
709 | GError **error) | ||
710 | { | ||
711 | 7 | g_autofree char *url = NULL; | |
712 | 7 | g_autoptr (SoupMessage) message = NULL; | |
713 | 7 | g_autofree char *escaped_name = NULL; | |
714 | 7 | JsonObject *root_object = NULL; | |
715 | 7 | g_autoptr (GBytes) response = NULL; | |
716 | 7 | g_autoptr (GBytes) body = NULL; | |
717 | 7 | g_autoptr (JsonParser) parser = NULL; | |
718 | |||
719 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
7 | if (!is_valid_name (msg_drive_item_get_name (item))) { |
720 | ✗ | g_set_error (error, | |
721 | msg_error_quark (), | ||
722 | MSG_ERROR_FAILED, | ||
723 | "Invalid characters in name"); | ||
724 | ✗ | return NULL; | |
725 | } | ||
726 | |||
727 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
7 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
728 | ✗ | return FALSE; | |
729 | |||
730 | 7 | escaped_name = g_uri_escape_string (msg_drive_item_get_name (item), NULL, TRUE); | |
731 | 7 | url = g_strconcat (MSG_API_ENDPOINT, | |
732 | "/drives/", | ||
733 | msg_drive_item_get_drive_id (parent), | ||
734 | "/items/", | ||
735 | msg_drive_item_get_id (parent), | ||
736 | ":/", | ||
737 | escaped_name, | ||
738 | ":/content", | ||
739 | NULL); | ||
740 | |||
741 | 7 | message = msg_service_build_message (MSG_SERVICE (self), "PUT", url, NULL, FALSE); | |
742 | 7 | body = g_bytes_new ("", 0); | |
743 | 7 | soup_message_set_request_body_from_bytes (message, "text/plain", body); | |
744 | |||
745 | 7 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
746 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!parser) |
747 | ✗ | return FALSE; | |
748 | |||
749 | 7 | return msg_drive_item_new_from_json (root_object, error); | |
750 | } | ||
751 | |||
752 | /** | ||
753 | * msg_drive_service_get_shared_with_me: | ||
754 | * @self: a #MsgDriveService | ||
755 | * @cancellable: a #GCancellable | ||
756 | * @error: a #GError | ||
757 | * | ||
758 | * Requests all shared with me items | ||
759 | * | ||
760 | * Returns: (element-type MsgDriveItem) (transfer full): shared with me list | ||
761 | */ | ||
762 | GList * | ||
763 | 1 | msg_drive_service_get_shared_with_me (MsgDriveService *self, | |
764 | GCancellable *cancellable, | ||
765 | GError **error) | ||
766 | { | ||
767 | 1 | g_autoptr (MsgDriveItem) child_item = NULL; | |
768 | 1 | g_autofree char *url = NULL; | |
769 | 1 | JsonObject *root_object = NULL; | |
770 | 1 | JsonArray *array = NULL; | |
771 | 1 | guint array_length = 0, index = 0; | |
772 | 1 | JsonObject *item_object = NULL; | |
773 | 1 | g_autolist (MsgDriveItem) children = NULL; | |
774 | 1 | g_autoptr (GBytes) response = NULL; | |
775 | 1 | g_autoptr (JsonParser) parser = NULL; | |
776 | |||
777 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
778 | ✗ | return NULL; | |
779 | |||
780 | 1 | url = g_strconcat (MSG_API_ENDPOINT, | |
781 | "/me/drive/sharedWithMe", | ||
782 | "?select=id,remoteItem,file,folder,parentReference,name,createdBy,lastModifiedBy,createdDateTime,lastModifiedDateTime,size", | ||
783 | NULL); | ||
784 | do { | ||
785 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | g_autoptr (SoupMessage) message = NULL; |
786 | |||
787 | 1 | message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE); | |
788 | 1 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
789 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!parser) |
790 | ✗ | return NULL; | |
791 | |||
792 | 1 | array = json_object_get_array_member (root_object, "value"); | |
793 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | g_assert (array != NULL); |
794 | |||
795 | 1 | array_length = json_array_get_length (array); | |
796 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (index = 0; index < array_length; index++) { |
797 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | g_autoptr (GError) local_error = NULL; |
798 | 4 | item_object = json_array_get_object_element (array, index); | |
799 | |||
800 | 4 | child_item = msg_drive_item_new_from_json (item_object, &local_error); | |
801 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (local_error) { |
802 | ✗ | g_warning ("Could not load shared with me item: %s", local_error->message); | |
803 | ✗ | continue; | |
804 | } | ||
805 | |||
806 | 4 | children = g_list_prepend (children, g_steal_pointer (&child_item)); | |
807 | } | ||
808 | |||
809 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | g_clear_pointer (&url, g_free); |
810 | 1 | url = msg_service_get_next_link (root_object); | |
811 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | } while (url != NULL); |
812 | |||
813 | 1 | return g_steal_pointer (&children); | |
814 | } | ||
815 | |||
816 | /** | ||
817 | * msg_drive_service_copy_file: | ||
818 | * @self: #MsgDriveService | ||
819 | * @file: source #MsgDriveItem | ||
820 | * @destination: destination directory #MsgDriveItem | ||
821 | * @cancellable: a #GCancellable | ||
822 | * @error: a #GError | ||
823 | * | ||
824 | * Copy a file async on remote server to a new directory. | ||
825 | * | ||
826 | * Returns: %TRUE if accepted, %FALSE on error | ||
827 | */ | ||
828 | gboolean | ||
829 | 1 | msg_drive_service_copy_file (MsgDriveService *self, | |
830 | MsgDriveItem *file, | ||
831 | MsgDriveItem *destination, | ||
832 | GCancellable *cancellable, | ||
833 | GError **error) | ||
834 | { | ||
835 | 1 | g_autofree char *url = NULL; | |
836 | 1 | g_autoptr (SoupMessage) message = NULL; | |
837 | 1 | g_autofree char *json = NULL; | |
838 | 1 | g_autoptr (JsonBuilder) builder = NULL; | |
839 | 1 | g_autoptr (JsonNode) create_node = NULL; | |
840 | 1 | GError *local_error = NULL; | |
841 | 1 | g_autoptr (GBytes) response = NULL; | |
842 | 1 | g_autoptr (GBytes) body = NULL; | |
843 | 1 | g_autoptr (JsonParser) parser = NULL; | |
844 | |||
845 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, &local_error)) { |
846 | ✗ | g_propagate_error (error, g_steal_pointer (&local_error)); | |
847 | ✗ | return FALSE; | |
848 | } | ||
849 | |||
850 | 1 | url = g_strconcat (MSG_API_ENDPOINT, | |
851 | "/drives/", | ||
852 | msg_drive_item_get_drive_id (file), | ||
853 | "/items/", | ||
854 | msg_drive_item_get_id (file), | ||
855 | "/copy", | ||
856 | NULL); | ||
857 | |||
858 | 1 | message = msg_service_build_message (MSG_SERVICE (self), "POST", url, NULL, FALSE); | |
859 | |||
860 | 1 | builder = json_builder_new (); | |
861 | 1 | json_builder_begin_object (builder); | |
862 | |||
863 | 1 | json_builder_set_member_name (builder, "parentReference"); | |
864 | 1 | json_builder_begin_object (builder); | |
865 | 1 | json_builder_set_member_name (builder, "driveId"); | |
866 | 1 | json_builder_add_string_value (builder, msg_drive_item_get_drive_id (destination)); | |
867 | 1 | json_builder_set_member_name (builder, "id"); | |
868 | 1 | json_builder_add_string_value (builder, msg_drive_item_get_id (destination)); | |
869 | 1 | json_builder_end_object (builder); | |
870 | |||
871 | 1 | json_builder_end_object (builder); | |
872 | 1 | create_node = json_builder_get_root (builder); | |
873 | 1 | json = json_to_string (create_node, TRUE); | |
874 | |||
875 | 1 | body = g_bytes_new (json, strlen (json)); | |
876 | 1 | soup_message_set_request_body_from_bytes (message, "application/json", body); | |
877 | |||
878 | 1 | response = msg_service_send_and_read (MSG_SERVICE (self), message, cancellable, &local_error); | |
879 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (local_error) { |
880 | ✗ | g_propagate_error (error, g_steal_pointer (&local_error)); | |
881 | ✗ | return FALSE; | |
882 | } | ||
883 | |||
884 | 1 | return TRUE; | |
885 | } | ||
886 | |||
887 | /** | ||
888 | * msg_drive_service_move_file: | ||
889 | * @self: #MsgDriveService | ||
890 | * @file: source #MsgDriveItem | ||
891 | * @destination: destination directory #MsgDriveItem | ||
892 | * @cancellable: a #GCancellable | ||
893 | * @error: a #GError | ||
894 | * | ||
895 | * Move a file async on remote server to a new directory. | ||
896 | * | ||
897 | * Returns: (transfer full): moved #MsgDriveItem | ||
898 | */ | ||
899 | MsgDriveItem * | ||
900 | ✗ | msg_drive_service_move_file (MsgDriveService *self, | |
901 | MsgDriveItem *file, | ||
902 | MsgDriveItem *destination, | ||
903 | GCancellable *cancellable, | ||
904 | GError **error) | ||
905 | { | ||
906 | ✗ | g_autofree char *url = NULL; | |
907 | ✗ | g_autoptr (SoupMessage) message = NULL; | |
908 | ✗ | g_autofree char *json = NULL; | |
909 | ✗ | g_autoptr (JsonBuilder) builder = NULL; | |
910 | ✗ | g_autoptr (JsonNode) create_node = NULL; | |
911 | ✗ | GError *local_error = NULL; | |
912 | ✗ | g_autoptr (GBytes) response = NULL; | |
913 | ✗ | g_autoptr (GBytes) body = NULL; | |
914 | ✗ | g_autoptr (JsonParser) parser = NULL; | |
915 | ✗ | MsgDriveItem *item = NULL; | |
916 | ✗ | JsonObject *root_object = NULL; | |
917 | |||
918 | ✗ | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, &local_error)) { | |
919 | ✗ | g_propagate_error (error, g_steal_pointer (&local_error)); | |
920 | ✗ | return NULL; | |
921 | } | ||
922 | |||
923 | ✗ | url = g_strconcat (MSG_API_ENDPOINT, | |
924 | "/drives/", | ||
925 | msg_drive_item_get_drive_id (file), | ||
926 | "/items/", | ||
927 | msg_drive_item_get_id (file), | ||
928 | NULL); | ||
929 | |||
930 | ✗ | message = msg_service_build_message (MSG_SERVICE (self), "PATCH", url, NULL, FALSE); | |
931 | |||
932 | ✗ | builder = json_builder_new (); | |
933 | ✗ | json_builder_begin_object (builder); | |
934 | |||
935 | ✗ | json_builder_set_member_name (builder, "parentReference"); | |
936 | ✗ | json_builder_begin_object (builder); | |
937 | ✗ | json_builder_set_member_name (builder, "id"); | |
938 | ✗ | json_builder_add_string_value (builder, msg_drive_item_get_id (destination)); | |
939 | ✗ | json_builder_end_object (builder); | |
940 | |||
941 | ✗ | json_builder_end_object (builder); | |
942 | ✗ | create_node = json_builder_get_root (builder); | |
943 | ✗ | json = json_to_string (create_node, TRUE); | |
944 | |||
945 | ✗ | body = g_bytes_new (json, strlen (json)); | |
946 | ✗ | soup_message_set_request_body_from_bytes (message, "application/json", body); | |
947 | |||
948 | ✗ | response = msg_service_send_and_read (MSG_SERVICE (self), message, cancellable, &local_error); | |
949 | ✗ | if (local_error) { | |
950 | ✗ | g_propagate_error (error, g_steal_pointer (&local_error)); | |
951 | ✗ | return NULL; | |
952 | } | ||
953 | |||
954 | ✗ | parser = msg_service_parse_response (response, &root_object, &local_error); | |
955 | ✗ | if (local_error != NULL) { | |
956 | ✗ | g_propagate_error (error, g_steal_pointer (&local_error)); | |
957 | ✗ | return NULL; | |
958 | } | ||
959 | |||
960 | ✗ | item = msg_drive_item_new_from_json (root_object, &local_error); | |
961 | ✗ | if (local_error) { | |
962 | ✗ | g_propagate_error (error, g_steal_pointer (&local_error)); | |
963 | ✗ | return FALSE; | |
964 | } | ||
965 | |||
966 | ✗ | return item; | |
967 | } | ||
968 |