GCC Code Coverage Report


Directory: src/
File: src/drive/msg-drive-service.c
Date: 2024-05-18 00:53:33
Exec Total Coverage
Lines: 275 350 78.6%
Functions: 19 20 95.0%
Branches: 53 103 51.5%

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
34
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);
35
36 static void
37 2 msg_drive_service_init (__attribute__ ((unused)) MsgDriveService *self)
38 {
39 2 }
40
41 static void
42 3 msg_drive_service_class_init (__attribute__ ((unused)) MsgDriveServiceClass *class)
43 {
44 3 }
45
46 /**
47 * msg_drive_service_new:
48 * @authorizer: A authorizer
49 *
50 * Creates a new `MsgDriveService` using #MsgAuthorizer.
51 *
52 * Returns: the newly created `MsgDriveService`
53 */
54 MsgDriveService *
55 2 msg_drive_service_new (MsgAuthorizer *authorizer)
56 {
57 2 return g_object_new (MSG_TYPE_DRIVE_SERVICE, "authorizer", authorizer, NULL);
58 }
59
60 /**
61 * msg_drive_service_get_drives:
62 * @self: a #MsgDriveService
63 * @cancellable: a #GCancellable
64 * @error: a #GError
65 *
66 * Queries the Microsoft Graph API for all the drives of the currently logged in user
67 *
68 * Returns: (element-type MsgDrive) (transfer full): all drives the user can access
69 */
70 GList *
71 10 msg_drive_service_get_drives (MsgDriveService *self,
72 GCancellable *cancellable,
73 GError **error)
74 {
75 10 g_autofree char *url = NULL;
76 10 JsonObject *root_object = NULL;
77 10 JsonArray *array = NULL;
78 10 guint array_length = 0, index = 0;
79 10 g_autolist (MsgDrive) list = NULL;
80 10 g_autoptr (GBytes) response = NULL;
81 10 g_autoptr (JsonParser) parser = NULL;
82
83
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
84 return NULL;
85
86 10 url = g_strconcat (MSG_API_ENDPOINT, "/me/drives", NULL);
87
88 do {
89
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 g_autoptr (SoupMessage) message = NULL;
90
91 10 message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE);
92 10 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
93
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!parser)
94 return NULL;
95
96 10 array = json_object_get_array_member (root_object, "value");
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 g_assert (array != NULL);
98
99 10 array_length = json_array_get_length (array);
100
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (index = 0; index < array_length; index++) {
101 10 MsgDrive *drive = NULL;
102 10 JsonObject *drive_object = NULL;
103 10 g_autoptr (GError) local_error = NULL;
104
105 10 drive_object = json_array_get_object_element (array, index);
106 10 drive = msg_drive_new_from_json (drive_object, &local_error);
107
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (drive) {
108 10 list = g_list_append (list, drive);
109 } else {
110 g_warning ("Could not parse drive object: %s", local_error->message);
111 }
112 }
113
114
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 g_clear_pointer (&url, g_free);
115 10 url = msg_service_get_next_link (root_object);
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 } while (url != NULL);
117
118 10 return g_steal_pointer (&list);
119 }
120
121 /**
122 * msg_drive_service_get_root:
123 * @self: a #MsgDriveService
124 * @drive: a #MsgDrive
125 * @cancellable: a #GCancellable
126 * @error: a #GError
127 *
128 * Get root item of selected drive
129 *
130 * Returns: (transfer full): root 'MsgDriveItem'
131 */
132 MsgDriveItem *
133 9 msg_drive_service_get_root (MsgDriveService *self,
134 MsgDrive *drive,
135 GCancellable *cancellable,
136 GError **error)
137 {
138 9 g_autofree char *url = NULL;
139 9 g_autoptr (SoupMessage) message = NULL;
140 9 JsonObject *root_object = NULL;
141 9 g_autoptr (GBytes) response = NULL;
142 9 g_autoptr (JsonParser) parser = NULL;
143
144
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
145 return NULL;
146
147 9 url = g_strconcat (MSG_API_ENDPOINT, "/drives/", msg_drive_get_id (drive), "/root", NULL);
148 9 message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE);
149 9 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!parser)
151 return NULL;
152
153 9 return msg_drive_item_new_from_json (root_object, error);
154 }
155
156 /**
157 * msg_drive_service_download_item:
158 * @self: a #MsgDriveService
159 * @item: a #MsgDriveItem
160 * @cancellable: a #GCancellable
161 * @error: a #GError
162 *
163 * Download item
164 *
165 * Returns: (transfer full): input stream of drive item
166 */
167 GInputStream *
168 2 msg_drive_service_download_item (MsgDriveService *self,
169 MsgDriveItem *item,
170 GCancellable *cancellable,
171 GError **error)
172 {
173 2 g_autofree char *url = NULL;
174
175
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!MSG_IS_DRIVE_ITEM_FILE (item)) {
176 g_warning ("Download only allowed for files");
177 return NULL;
178 }
179
180
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
181 return NULL;
182
183 2 url = g_strconcat (MSG_API_ENDPOINT,
184 "/drives/",
185 msg_drive_item_get_drive_id (item),
186 "/items/",
187 msg_drive_item_get_id (item),
188 "/content",
189 NULL);
190
191 2 return msg_input_stream_new (MSG_SERVICE (self), url);
192 }
193
194 /**
195 * msg_drive_service_list_children:
196 * @self: a #MsgDriveService
197 * @item: a #MsgDriveItem
198 * @cancellable: a #GCancellable
199 * @error: a #GError
200 *
201 * Get a list of all files in folder item
202 *
203 * Returns: (element-type MsgDriveItem) (transfer full): all items in folder
204 */
205 GList *
206 1 msg_drive_service_list_children (MsgDriveService *self,
207 MsgDriveItem *item,
208 GCancellable *cancellable,
209 GError **error)
210 {
211 1 g_autoptr (MsgDriveItem) child_item = NULL;
212 1 g_autofree char *url = NULL;
213 1 JsonObject *root_object = NULL;
214 1 JsonArray *array = NULL;
215 1 guint array_length = 0, index = 0;
216 1 JsonObject *item_object = NULL;
217 1 g_autolist (MsgDriveItem) children = NULL;
218 1 g_autoptr (GBytes) response = NULL;
219 1 g_autoptr (JsonParser) parser = NULL;
220
221
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
222 return NULL;
223
224 1 url = g_strconcat (MSG_API_ENDPOINT,
225 "/drives/",
226 msg_drive_item_get_drive_id (item),
227 "/items/",
228 msg_drive_item_get_id (item),
229 "/children",
230 "?$expand=thumbnails",
231 NULL);
232
233 do {
234
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 g_autoptr (SoupMessage) message = NULL;
235
236 1 message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL /*msg_drive_item_get_etag (item)*/, FALSE);
237 1 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!parser)
239 return NULL;
240
241 1 array = json_object_get_array_member (root_object, "value");
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 g_assert (array != NULL);
243
244 1 array_length = json_array_get_length (array);
245
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 for (index = 0; index < array_length; index++) {
246
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 g_autoptr (GError) local_error = NULL;
247 6 item_object = json_array_get_object_element (array, index);
248
249 6 child_item = msg_drive_item_new_from_json (item_object, &local_error);
250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (local_error) {
251 g_warning ("Could not read child item: %s", local_error->message);
252 continue;
253 }
254
255 6 children = g_list_prepend (children, g_steal_pointer (&child_item));
256 }
257
258
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 g_clear_pointer (&url, g_free);
259 1 url = msg_service_get_next_link (root_object);
260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } while (url != NULL);
261
262 1 return g_steal_pointer (&children);
263 }
264
265 /**
266 * msg_drive_service_rename:
267 * @self: a #MsgDriveService
268 * @item: a #MsgDriveItem
269 * @new_name: new name of item
270 * @cancellable: a #GCancellable
271 * @error: a #GError
272 *
273 * Sets a new drive item name
274 *
275 * Returns: (transfer full): the renamed `MsgDriveItem`
276 */
277 MsgDriveItem *
278 1 msg_drive_service_rename (MsgDriveService *self,
279 MsgDriveItem *item,
280 const char *new_name,
281 GCancellable *cancellable,
282 GError **error)
283 {
284 1 g_autoptr (SoupMessage) message = NULL;
285 1 g_autoptr (JsonBuilder) builder = NULL;
286 1 g_autoptr (JsonNode) rename_node = NULL;
287 1 g_autofree char *url = NULL;
288 1 g_autofree char *json = NULL;
289 1 JsonObject *root_object = NULL;
290 1 g_autoptr (GBytes) response = NULL;
291 1 GBytes *body = NULL;
292 1 g_autoptr (JsonParser) parser = NULL;
293
294
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
295 return NULL;
296
297 1 url = g_strconcat (MSG_API_ENDPOINT,
298 "/drives/",
299 msg_drive_item_get_drive_id (item),
300 "/items/",
301 msg_drive_item_get_id (item),
302 NULL);
303
304 1 message = msg_service_build_message (MSG_SERVICE (self), "PATCH", url, NULL, FALSE);
305
306 1 builder = json_builder_new ();
307 1 json_builder_begin_object (builder);
308 1 json_builder_set_member_name (builder, "name");
309 1 json_builder_add_string_value (builder, new_name);
310 1 json_builder_end_object (builder);
311 1 rename_node = json_builder_get_root (builder);
312 1 json = json_to_string (rename_node, TRUE);
313
314 1 body = g_bytes_new (json, strlen (json));
315 1 soup_message_set_request_body_from_bytes (message, "application/json", body);
316
317 1 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!parser)
319 return NULL;
320
321 1 return msg_drive_item_new_from_json (root_object, error);
322 }
323
324 /**
325 * msg_drive_service_download_url:
326 * @self: a #MsgDriveService
327 * @url: url to download
328 * @cancellable: a #GCancellable
329 * @error: a #GError
330 *
331 * Download url
332 *
333 * Returns: (transfer full): a new `GInputStream` for url
334 */
335 GInputStream *
336 1 msg_drive_service_download_url (MsgDriveService *self,
337 const char *url,
338 GCancellable *cancellable,
339 GError **error)
340 {
341 1 SoupMessage *message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE);
342
343 1 return msg_service_send (MSG_SERVICE (self), message, cancellable, error);
344 }
345
346 /**
347 * msg_drive_service_create_folder:
348 * @self: a drive service
349 * @parent: parent drive item
350 * @name: name of new folder
351 * @cancellable: a cancellable
352 * @error: a error
353 *
354 * Creates a new folder called name under parent.
355 *
356 * Returns: (transfer full): a newly created `MsgDriveItem`
357 */
358 MsgDriveItem *
359 8 msg_drive_service_create_folder (MsgDriveService *self,
360 MsgDriveItem *parent,
361 const char *name,
362 GCancellable *cancellable,
363 GError **error)
364 {
365 8 g_autofree char *url = NULL;
366 8 g_autoptr (SoupMessage) message = NULL;
367 8 g_autofree char *json = NULL;
368 8 g_autoptr (JsonBuilder) builder = NULL;
369 8 g_autoptr (JsonNode) create_node = NULL;
370 8 JsonObject *root_object = NULL;
371 8 g_autoptr (GBytes) response = NULL;
372 8 GBytes *body = NULL;
373 8 g_autoptr (JsonParser) parser = NULL;
374
375
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
376 return NULL;
377
378 8 url = g_strconcat (MSG_API_ENDPOINT,
379 "/drives/",
380 msg_drive_item_get_drive_id (parent),
381 "/items/",
382 msg_drive_item_get_id (parent),
383 "/children",
384 NULL);
385
386 8 message = msg_service_build_message (MSG_SERVICE (self), "POST", url, NULL, FALSE);
387
388 8 builder = json_builder_new ();
389 8 json_builder_begin_object (builder);
390 8 json_builder_set_member_name (builder, "name");
391 8 json_builder_add_string_value (builder, name);
392 8 json_builder_set_member_name (builder, "@microsoft.graph.conflictBehavior");
393 8 json_builder_add_string_value (builder, "rename");
394 8 json_builder_set_member_name (builder, "folder");
395 8 json_builder_begin_object (builder);
396 8 json_builder_end_object (builder);
397 8 json_builder_end_object (builder);
398 8 create_node = json_builder_get_root (builder);
399 8 json = json_to_string (create_node, TRUE);
400
401 8 body = g_bytes_new (json, strlen (json));
402 8 soup_message_set_request_body_from_bytes (message, "application/json", body);
403
404 8 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!parser)
406 return NULL;
407
408 8 return msg_drive_item_new_from_json (root_object, error);
409 }
410
411 /**
412 * msg_drive_service_delete:
413 * @self: a drive service
414 * @item: a #MsgDriveItem
415 * @cancellable: a cancellable
416 * @error: a error
417 *
418 * Deletes item.
419 *
420 * Returns: %TRUE when item has been deleted, otherwise %FALSE
421 */
422 gboolean
423 11 msg_drive_service_delete (MsgDriveService *self,
424 MsgDriveItem *item,
425 GCancellable *cancellable,
426 GError **error)
427 {
428 11 g_autoptr (SoupMessage) message = NULL;
429 11 g_autofree char *url = NULL;
430 11 g_autoptr (GBytes) bytes = NULL;
431
432
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
433 return FALSE;
434
435 11 url = g_strconcat (MSG_API_ENDPOINT,
436 "/drives/",
437 msg_drive_item_get_drive_id (item),
438 "/items/",
439 msg_drive_item_get_id (item),
440 NULL);
441
442 11 message = msg_service_build_message (MSG_SERVICE (self), "DELETE", url, NULL, FALSE);
443
444 11 bytes = msg_service_send_and_read (MSG_SERVICE (self), message, cancellable, error);
445 11 return bytes != NULL;
446 }
447
448 /**
449 * msg_drive_service_update:
450 * @self: a drive service
451 * @item: a drive item
452 * @cancellable: a cancellable
453 * @error: a error
454 *
455 * Creates an update stream for drive item in order to update it's content.
456 *
457 * Returns: (transfer full): an output stream
458 */
459 GOutputStream *
460 7 msg_drive_service_update (MsgDriveService *self,
461 MsgDriveItem *item,
462 GCancellable *cancellable,
463 GError **error)
464 {
465 7 GOutputStream *stream = NULL;
466 7 g_autofree char *url = NULL;
467 7 g_autoptr (JsonBuilder) builder = NULL;
468 7 g_autoptr (JsonNode) create_node = NULL;
469 7 g_autoptr (SoupMessage) message = NULL;
470 7 JsonObject *root_object = NULL;
471 7 g_autofree char *json = NULL;
472 7 g_autoptr (GBytes) response = NULL;
473 7 GBytes *body = NULL;
474 const char *upload_url;
475 7 g_autoptr (JsonParser) parser = NULL;
476
477
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
478 return NULL;
479
480 7 url = g_strconcat (MSG_API_ENDPOINT,
481 "/drives/",
482 msg_drive_item_get_drive_id (item),
483 "/items/",
484 msg_drive_item_get_id (item),
485 "/createUploadSession",
486 NULL);
487
488 7 message = msg_service_build_message (MSG_SERVICE (self), "POST", url, NULL, FALSE);
489 7 builder = json_builder_new ();
490 7 json_builder_begin_object (builder);
491 7 json_builder_set_member_name (builder, "@microsoft.graph.conflictBehavior");
492 7 json_builder_add_string_value (builder, "rename");
493 7 json_builder_end_object (builder);
494 7 create_node = json_builder_get_root (builder);
495 7 json = json_to_string (create_node, TRUE);
496
497 7 body = g_bytes_new (json, strlen (json));
498 7 soup_message_set_request_body_from_bytes (message, "application/json", body);
499
500 7 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!parser)
502 return NULL;
503
504
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (!json_object_has_member (root_object, "uploadUrl")) {
505 g_set_error (error,
506 msg_error_quark (),
507 MSG_ERROR_FAILED,
508 "No uploadUrl found");
509 return NULL;
510 }
511
512 7 upload_url = json_object_get_string_member (root_object, "uploadUrl");
513
514 7 stream = g_memory_output_stream_new (NULL, 0, g_try_realloc, g_free);
515 7 g_object_set_data (G_OBJECT (stream), "ms-graph-upload-url", g_strdup (upload_url));
516 7 g_object_set_data (G_OBJECT (stream), "ms-graph-item", item);
517
518 7 return stream;
519 }
520
521 /**
522 * msg_drive_service_update_finish:
523 * @self: a #MsgDriveService
524 * @item: a #MsgDriveItem
525 * @stream: stream where data is store and needs to be transfered
526 * @cancellable: a #GCancellable
527 * @error: a #GError
528 *
529 * Finish a update session of given #item.
530 *
531 * Returns: (transfer full): a new #MsgDriveItem or %NULL on error.
532 */
533 MsgDriveItem *
534 7 msg_drive_service_update_finish (MsgDriveService *self,
535 MsgDriveItem *item,
536 GOutputStream *stream,
537 GCancellable *cancellable,
538 GError **error)
539 {
540 GBytes *bytes;
541 7 g_autofree char *url = NULL;
542 7 SoupMessage *message = NULL;
543 7 JsonObject *root_object = NULL;
544 gconstpointer data;
545 gsize len;
546 7 g_autoptr (GBytes) response = NULL;
547 7 GBytes *body = NULL;
548 7 g_autoptr (JsonParser) parser = NULL;
549
550
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
551 return NULL;
552
553 7 url = g_strconcat (MSG_API_ENDPOINT,
554 "/drives/",
555 msg_drive_item_get_drive_id (item),
556 "/items/",
557 msg_drive_item_get_id (item),
558 "/content",
559 NULL);
560
561 7 g_output_stream_close (stream, NULL, NULL);
562 7 bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
563 7 data = g_bytes_get_data (bytes, &len);
564
565 7 message = msg_service_build_message (MSG_SERVICE (self), "PUT", url, NULL, FALSE);
566 7 body = g_bytes_new (data, len);
567 7 soup_message_set_request_body_from_bytes (message, "application/octet-stream", body);
568
569 7 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!parser)
571 return NULL;
572
573 7 return msg_drive_item_new_from_json (root_object, error);
574 }
575
576 /**
577 * msg_drive_service_add_item_to_folder:
578 * @self: a msg drive service
579 * @parent: parent drive item
580 * @item: drive item to add
581 * @cancellable: a cancellable
582 * @error: a error
583 *
584 * Adds item to parent folder
585 *
586 * Returns: (transfer full): a new drive item
587 */
588 MsgDriveItem *
589 7 msg_drive_service_add_item_to_folder (MsgDriveService *self,
590 MsgDriveItem *parent,
591 MsgDriveItem *item,
592 GCancellable *cancellable,
593 GError **error)
594 {
595 7 g_autofree char *url = NULL;
596 7 g_autoptr (SoupMessage) message = NULL;
597 7 g_autofree char *escaped_name = NULL;
598 7 JsonObject *root_object = NULL;
599 7 g_autoptr (GBytes) response = NULL;
600 7 GBytes *body = NULL;
601 7 g_autoptr (JsonParser) parser = NULL;
602
603
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
604 return FALSE;
605
606 7 escaped_name = g_uri_escape_string (msg_drive_item_get_name (item), NULL, TRUE);
607 7 url = g_strconcat (MSG_API_ENDPOINT,
608 "/drives/",
609 msg_drive_item_get_drive_id (parent),
610 "/items/",
611 msg_drive_item_get_id (parent),
612 ":/",
613 escaped_name,
614 ":/content",
615 NULL);
616
617 7 message = msg_service_build_message (MSG_SERVICE (self), "PUT", url, NULL, FALSE);
618 7 body = g_bytes_new ("", 0);
619 7 soup_message_set_request_body_from_bytes (message, "text/plain", body);
620
621 7 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!parser)
623 return FALSE;
624
625 7 return msg_drive_item_new_from_json (root_object, error);
626 }
627
628 /**
629 * msg_drive_service_get_shared_with_me:
630 * @self: a #MsgDriveService
631 * @cancellable: a #GCancellable
632 * @error: a #GError
633 *
634 * Requests all shared with me items
635 *
636 * Returns: (element-type MsgDriveItem) (transfer full): shared with me list
637 */
638 GList *
639 1 msg_drive_service_get_shared_with_me (MsgDriveService *self,
640 GCancellable *cancellable,
641 GError **error)
642 {
643 1 g_autoptr (MsgDriveItem) child_item = NULL;
644 1 g_autofree char *url = NULL;
645 1 JsonObject *root_object = NULL;
646 1 JsonArray *array = NULL;
647 1 guint array_length = 0, index = 0;
648 1 JsonObject *item_object = NULL;
649 1 g_autolist (MsgDriveItem) children = NULL;
650 1 g_autoptr (GBytes) response = NULL;
651 1 g_autoptr (JsonParser) parser = NULL;
652
653
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
654 return NULL;
655
656 1 url = g_strconcat (MSG_API_ENDPOINT,
657 "/me/drive/sharedWithMe",
658 NULL);
659 do {
660
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 g_autoptr (SoupMessage) message = NULL;
661
662 1 message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE);
663 1 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!parser)
665 return NULL;
666
667 1 array = json_object_get_array_member (root_object, "value");
668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 g_assert (array != NULL);
669
670 1 array_length = json_array_get_length (array);
671
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (index = 0; index < array_length; index++) {
672
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 g_autoptr (GError) local_error = NULL;
673 4 item_object = json_array_get_object_element (array, index);
674
675 4 child_item = msg_drive_item_new_from_json (item_object, &local_error);
676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (local_error) {
677 g_warning ("Could not load shared with me item: %s", local_error->message);
678 continue;
679 }
680
681 4 children = g_list_prepend (children, g_steal_pointer (&child_item));
682 }
683
684
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 g_clear_pointer (&url, g_free);
685 1 url = msg_service_get_next_link (root_object);
686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } while (url != NULL);
687
688 1 return g_steal_pointer (&children);
689 }
690
691 /**
692 * msg_drive_service_copy_file:
693 * @self: #MsgDriveService
694 * @file: source #MsgDriveItem
695 * @destination: destination directory #MsgDriveItem
696 * @cancellable: a #GCancellable
697 * @error: a #GError
698 *
699 * Copy a file async on remote server to a new directory.
700 *
701 * Returns: %TRUE if accepted, %FALSE on error
702 */
703 gboolean
704 1 msg_drive_service_copy_file (MsgDriveService *self,
705 MsgDriveItem *file,
706 MsgDriveItem *destination,
707 GCancellable *cancellable,
708 GError **error)
709 {
710 1 g_autofree char *url = NULL;
711 1 g_autoptr (SoupMessage) message = NULL;
712 1 g_autofree char *json = NULL;
713 1 g_autoptr (JsonBuilder) builder = NULL;
714 1 g_autoptr (JsonNode) create_node = NULL;
715 1 GError *local_error = NULL;
716 1 g_autoptr (GBytes) response = NULL;
717 1 GBytes *body = NULL;
718 1 g_autoptr (JsonParser) parser = NULL;
719
720
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, &local_error)) {
721 g_propagate_error (error, g_steal_pointer (&local_error));
722 return FALSE;
723 }
724
725 1 url = g_strconcat (MSG_API_ENDPOINT,
726 "/drives/",
727 msg_drive_item_get_drive_id (file),
728 "/items/",
729 msg_drive_item_get_id (file),
730 "/copy",
731 NULL);
732
733 1 message = msg_service_build_message (MSG_SERVICE (self), "POST", url, NULL, FALSE);
734
735 1 builder = json_builder_new ();
736 1 json_builder_begin_object (builder);
737
738 1 json_builder_set_member_name (builder, "parentReference");
739 1 json_builder_begin_object (builder);
740 1 json_builder_set_member_name (builder, "driveId");
741 1 json_builder_add_string_value (builder, msg_drive_item_get_drive_id (destination));
742 1 json_builder_set_member_name (builder, "id");
743 1 json_builder_add_string_value (builder, msg_drive_item_get_id (destination));
744 1 json_builder_end_object (builder);
745
746 1 json_builder_end_object (builder);
747 1 create_node = json_builder_get_root (builder);
748 1 json = json_to_string (create_node, TRUE);
749
750 1 body = g_bytes_new (json, strlen (json));
751 1 soup_message_set_request_body_from_bytes (message, "application/json", body);
752
753 1 response = msg_service_send_and_read (MSG_SERVICE (self), message, cancellable, &local_error);
754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (local_error) {
755 g_propagate_error (error, g_steal_pointer (&local_error));
756 return FALSE;
757 }
758
759 1 return TRUE;
760 }
761
762 /**
763 * msg_drive_service_move_file:
764 * @self: #MsgDriveService
765 * @file: source #MsgDriveItem
766 * @destination: destination directory #MsgDriveItem
767 * @cancellable: a #GCancellable
768 * @error: a #GError
769 *
770 * Move a file async on remote server to a new directory.
771 *
772 * Returns: (transfer full): moved #MsgDriveItem
773 */
774 MsgDriveItem *
775 msg_drive_service_move_file (MsgDriveService *self,
776 MsgDriveItem *file,
777 MsgDriveItem *destination,
778 GCancellable *cancellable,
779 GError **error)
780 {
781 g_autofree char *url = NULL;
782 g_autoptr (SoupMessage) message = NULL;
783 g_autofree char *json = NULL;
784 g_autoptr (JsonBuilder) builder = NULL;
785 g_autoptr (JsonNode) create_node = NULL;
786 GError *local_error = NULL;
787 g_autoptr (GBytes) response = NULL;
788 GBytes *body = NULL;
789 g_autoptr (JsonParser) parser = NULL;
790 MsgDriveItem *item = NULL;
791 JsonObject *root_object = NULL;
792
793 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, &local_error)) {
794 g_propagate_error (error, g_steal_pointer (&local_error));
795 return NULL;
796 }
797
798 url = g_strconcat (MSG_API_ENDPOINT,
799 "/drives/",
800 msg_drive_item_get_drive_id (file),
801 "/items/",
802 msg_drive_item_get_id (file),
803 NULL);
804
805 message = msg_service_build_message (MSG_SERVICE (self), "PATCH", url, NULL, FALSE);
806
807 builder = json_builder_new ();
808 json_builder_begin_object (builder);
809
810 json_builder_set_member_name (builder, "parentReference");
811 json_builder_begin_object (builder);
812 json_builder_set_member_name (builder, "id");
813 json_builder_add_string_value (builder, msg_drive_item_get_id (destination));
814 json_builder_end_object (builder);
815
816 json_builder_end_object (builder);
817 create_node = json_builder_get_root (builder);
818 json = json_to_string (create_node, TRUE);
819
820 body = g_bytes_new (json, strlen (json));
821 soup_message_set_request_body_from_bytes (message, "application/json", body);
822
823 response = msg_service_send_and_read (MSG_SERVICE (self), message, cancellable, &local_error);
824 if (local_error) {
825 g_propagate_error (error, g_steal_pointer (&local_error));
826 return NULL;
827 }
828
829 parser = msg_service_parse_response (response, &root_object, &local_error);
830 if (local_error != NULL) {
831 g_propagate_error (error, g_steal_pointer (&local_error));
832 return NULL;
833 }
834
835 item = msg_drive_item_new_from_json (root_object, &local_error);
836 if (local_error) {
837 g_propagate_error (error, g_steal_pointer (&local_error));
838 return FALSE;
839 }
840
841 return item;
842 }
843