GCC Code Coverage Report


Directory: src/
File: src/drive/msg-drive-service.c
Date: 2024-07-13 00:54:47
Exec Total Coverage
Lines: 274 349 78.5%
Functions: 19 20 95.0%
Branches: 54 105 51.4%

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 g_autoptr (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 2 g_autoptr (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 g_autoptr (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 g_autoptr (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_resizable ();
515 7 g_object_set_data_full (G_OBJECT (stream), "ms-graph-upload-url", g_strdup (upload_url), g_free);
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 7 g_autoptr (GBytes) bytes;
541 7 g_autofree char *url = NULL;
542 7 g_autoptr (SoupMessage) message = NULL;
543 7 JsonObject *root_object = NULL;
544 7 g_autoptr (GBytes) response = NULL;
545 7 g_autoptr (JsonParser) parser = NULL;
546
547
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
548 return NULL;
549
550 7 url = g_strconcat (MSG_API_ENDPOINT,
551 "/drives/",
552 msg_drive_item_get_drive_id (item),
553 "/items/",
554 msg_drive_item_get_id (item),
555 "/content",
556 NULL);
557
558 7 g_output_stream_close (stream, NULL, NULL);
559 7 bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
560
561 7 message = msg_service_build_message (MSG_SERVICE (self), "PUT", url, NULL, FALSE);
562 7 soup_message_set_request_body_from_bytes (message, "application/octet-stream", bytes);
563
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 g_clear_object (&stream);
564
565 7 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!parser)
567 return NULL;
568
569 7 return msg_drive_item_new_from_json (root_object, error);
570 }
571
572 /**
573 * msg_drive_service_add_item_to_folder:
574 * @self: a msg drive service
575 * @parent: parent drive item
576 * @item: drive item to add
577 * @cancellable: a cancellable
578 * @error: a error
579 *
580 * Adds item to parent folder
581 *
582 * Returns: (transfer full): a new drive item
583 */
584 MsgDriveItem *
585 7 msg_drive_service_add_item_to_folder (MsgDriveService *self,
586 MsgDriveItem *parent,
587 MsgDriveItem *item,
588 GCancellable *cancellable,
589 GError **error)
590 {
591 7 g_autofree char *url = NULL;
592 7 g_autoptr (SoupMessage) message = NULL;
593 7 g_autofree char *escaped_name = NULL;
594 7 JsonObject *root_object = NULL;
595 7 g_autoptr (GBytes) response = NULL;
596 7 g_autoptr (GBytes) body = NULL;
597 7 g_autoptr (JsonParser) parser = NULL;
598
599
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
600 return FALSE;
601
602 7 escaped_name = g_uri_escape_string (msg_drive_item_get_name (item), NULL, TRUE);
603 7 url = g_strconcat (MSG_API_ENDPOINT,
604 "/drives/",
605 msg_drive_item_get_drive_id (parent),
606 "/items/",
607 msg_drive_item_get_id (parent),
608 ":/",
609 escaped_name,
610 ":/content",
611 NULL);
612
613 7 message = msg_service_build_message (MSG_SERVICE (self), "PUT", url, NULL, FALSE);
614 7 body = g_bytes_new ("", 0);
615 7 soup_message_set_request_body_from_bytes (message, "text/plain", body);
616
617 7 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!parser)
619 return FALSE;
620
621 7 return msg_drive_item_new_from_json (root_object, error);
622 }
623
624 /**
625 * msg_drive_service_get_shared_with_me:
626 * @self: a #MsgDriveService
627 * @cancellable: a #GCancellable
628 * @error: a #GError
629 *
630 * Requests all shared with me items
631 *
632 * Returns: (element-type MsgDriveItem) (transfer full): shared with me list
633 */
634 GList *
635 1 msg_drive_service_get_shared_with_me (MsgDriveService *self,
636 GCancellable *cancellable,
637 GError **error)
638 {
639 1 g_autoptr (MsgDriveItem) child_item = NULL;
640 1 g_autofree char *url = NULL;
641 1 JsonObject *root_object = NULL;
642 1 JsonArray *array = NULL;
643 1 guint array_length = 0, index = 0;
644 1 JsonObject *item_object = NULL;
645 1 g_autolist (MsgDriveItem) children = NULL;
646 1 g_autoptr (GBytes) response = NULL;
647 1 g_autoptr (JsonParser) parser = NULL;
648
649
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error))
650 return NULL;
651
652 1 url = g_strconcat (MSG_API_ENDPOINT,
653 "/me/drive/sharedWithMe",
654 NULL);
655 do {
656
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 g_autoptr (SoupMessage) message = NULL;
657
658 1 message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE);
659 1 parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error);
660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!parser)
661 return NULL;
662
663 1 array = json_object_get_array_member (root_object, "value");
664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 g_assert (array != NULL);
665
666 1 array_length = json_array_get_length (array);
667
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (index = 0; index < array_length; index++) {
668
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 g_autoptr (GError) local_error = NULL;
669 4 item_object = json_array_get_object_element (array, index);
670
671 4 child_item = msg_drive_item_new_from_json (item_object, &local_error);
672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (local_error) {
673 g_warning ("Could not load shared with me item: %s", local_error->message);
674 continue;
675 }
676
677 4 children = g_list_prepend (children, g_steal_pointer (&child_item));
678 }
679
680
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 g_clear_pointer (&url, g_free);
681 1 url = msg_service_get_next_link (root_object);
682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } while (url != NULL);
683
684 1 return g_steal_pointer (&children);
685 }
686
687 /**
688 * msg_drive_service_copy_file:
689 * @self: #MsgDriveService
690 * @file: source #MsgDriveItem
691 * @destination: destination directory #MsgDriveItem
692 * @cancellable: a #GCancellable
693 * @error: a #GError
694 *
695 * Copy a file async on remote server to a new directory.
696 *
697 * Returns: %TRUE if accepted, %FALSE on error
698 */
699 gboolean
700 1 msg_drive_service_copy_file (MsgDriveService *self,
701 MsgDriveItem *file,
702 MsgDriveItem *destination,
703 GCancellable *cancellable,
704 GError **error)
705 {
706 1 g_autofree char *url = NULL;
707 1 g_autoptr (SoupMessage) message = NULL;
708 1 g_autofree char *json = NULL;
709 1 g_autoptr (JsonBuilder) builder = NULL;
710 1 g_autoptr (JsonNode) create_node = NULL;
711 1 GError *local_error = NULL;
712 1 g_autoptr (GBytes) response = NULL;
713 1 g_autoptr (GBytes) body = NULL;
714 1 g_autoptr (JsonParser) parser = NULL;
715
716
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, &local_error)) {
717 g_propagate_error (error, g_steal_pointer (&local_error));
718 return FALSE;
719 }
720
721 1 url = g_strconcat (MSG_API_ENDPOINT,
722 "/drives/",
723 msg_drive_item_get_drive_id (file),
724 "/items/",
725 msg_drive_item_get_id (file),
726 "/copy",
727 NULL);
728
729 1 message = msg_service_build_message (MSG_SERVICE (self), "POST", url, NULL, FALSE);
730
731 1 builder = json_builder_new ();
732 1 json_builder_begin_object (builder);
733
734 1 json_builder_set_member_name (builder, "parentReference");
735 1 json_builder_begin_object (builder);
736 1 json_builder_set_member_name (builder, "driveId");
737 1 json_builder_add_string_value (builder, msg_drive_item_get_drive_id (destination));
738 1 json_builder_set_member_name (builder, "id");
739 1 json_builder_add_string_value (builder, msg_drive_item_get_id (destination));
740 1 json_builder_end_object (builder);
741
742 1 json_builder_end_object (builder);
743 1 create_node = json_builder_get_root (builder);
744 1 json = json_to_string (create_node, TRUE);
745
746 1 body = g_bytes_new (json, strlen (json));
747 1 soup_message_set_request_body_from_bytes (message, "application/json", body);
748
749 1 response = msg_service_send_and_read (MSG_SERVICE (self), message, cancellable, &local_error);
750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (local_error) {
751 g_propagate_error (error, g_steal_pointer (&local_error));
752 return FALSE;
753 }
754
755 1 return TRUE;
756 }
757
758 /**
759 * msg_drive_service_move_file:
760 * @self: #MsgDriveService
761 * @file: source #MsgDriveItem
762 * @destination: destination directory #MsgDriveItem
763 * @cancellable: a #GCancellable
764 * @error: a #GError
765 *
766 * Move a file async on remote server to a new directory.
767 *
768 * Returns: (transfer full): moved #MsgDriveItem
769 */
770 MsgDriveItem *
771 msg_drive_service_move_file (MsgDriveService *self,
772 MsgDriveItem *file,
773 MsgDriveItem *destination,
774 GCancellable *cancellable,
775 GError **error)
776 {
777 g_autofree char *url = NULL;
778 g_autoptr (SoupMessage) message = NULL;
779 g_autofree char *json = NULL;
780 g_autoptr (JsonBuilder) builder = NULL;
781 g_autoptr (JsonNode) create_node = NULL;
782 GError *local_error = NULL;
783 g_autoptr (GBytes) response = NULL;
784 g_autoptr (GBytes) body = NULL;
785 g_autoptr (JsonParser) parser = NULL;
786 MsgDriveItem *item = NULL;
787 JsonObject *root_object = NULL;
788
789 if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, &local_error)) {
790 g_propagate_error (error, g_steal_pointer (&local_error));
791 return NULL;
792 }
793
794 url = g_strconcat (MSG_API_ENDPOINT,
795 "/drives/",
796 msg_drive_item_get_drive_id (file),
797 "/items/",
798 msg_drive_item_get_id (file),
799 NULL);
800
801 message = msg_service_build_message (MSG_SERVICE (self), "PATCH", url, NULL, FALSE);
802
803 builder = json_builder_new ();
804 json_builder_begin_object (builder);
805
806 json_builder_set_member_name (builder, "parentReference");
807 json_builder_begin_object (builder);
808 json_builder_set_member_name (builder, "id");
809 json_builder_add_string_value (builder, msg_drive_item_get_id (destination));
810 json_builder_end_object (builder);
811
812 json_builder_end_object (builder);
813 create_node = json_builder_get_root (builder);
814 json = json_to_string (create_node, TRUE);
815
816 body = g_bytes_new (json, strlen (json));
817 soup_message_set_request_body_from_bytes (message, "application/json", body);
818
819 response = msg_service_send_and_read (MSG_SERVICE (self), message, cancellable, &local_error);
820 if (local_error) {
821 g_propagate_error (error, g_steal_pointer (&local_error));
822 return NULL;
823 }
824
825 parser = msg_service_parse_response (response, &root_object, &local_error);
826 if (local_error != NULL) {
827 g_propagate_error (error, g_steal_pointer (&local_error));
828 return NULL;
829 }
830
831 item = msg_drive_item_new_from_json (root_object, &local_error);
832 if (local_error) {
833 g_propagate_error (error, g_steal_pointer (&local_error));
834 return FALSE;
835 }
836
837 return item;
838 }
839