1 /* Copyright (C) 2020-2021 Greenbone Networks GmbH
2  *
3  * SPDX-License-Identifier: AGPL-3.0-or-later
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as
7  * published by the Free Software Foundation, either version 3 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /**
20  * @file manage_report_formats.c
21  * @brief GVM management layer: Report formats.
22  *
23  * Non-SQL report format code for the GVM management layer.
24  */
25 
26 #include "manage_report_formats.h"
27 #include "gmp_report_formats.h"
28 #include "manage.h"
29 #include "manage_sql.h"
30 #include "manage_sql_report_formats.h"
31 #include "utils.h"
32 
33 #include <assert.h>
34 #include <errno.h>
35 #include <glib.h>
36 #include <gvm/util/fileutils.h>
37 #include <locale.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #undef G_LOG_DOMAIN
42 /**
43  * @brief GLib log domain.
44  */
45 #define G_LOG_DOMAIN "md manage"
46 
47 /**
48  * @brief Find a report format for a specific permission, given a UUID.
49  *
50  * @param[in]   uuid        UUID of report format.
51  * @param[out]  report_format  Report format return, 0 if successfully failed to
52  *                             find report_format.
53  * @param[in]   permission  Permission.
54  *
55  * @return FALSE on success (including if failed to find report_format), TRUE
56  *         on error.
57  */
58 gboolean
find_report_format_with_permission(const char * uuid,report_format_t * report_format,const char * permission)59 find_report_format_with_permission (const char *uuid,
60                                     report_format_t *report_format,
61                                     const char *permission)
62 {
63   return find_resource_with_permission ("report_format", uuid, report_format,
64                                         permission, 0);
65 }
66 
67 /**
68  * @brief Return whether a report format is writable.
69  *
70  * @param[in]  report_format Report Format.
71  *
72  * @return 1 if writable, else 0.
73  */
74 int
report_format_writable(report_format_t report_format)75 report_format_writable (report_format_t report_format)
76 {
77   return report_format_in_use (report_format) == 0;
78 }
79 
80 /**
81  * @brief Return whether a trashcan report_format is writable.
82  *
83  * @param[in]  report_format  Report Format.
84  *
85  * @return 1 if writable, else 0.
86  */
87 int
trash_report_format_writable(report_format_t report_format)88 trash_report_format_writable (report_format_t report_format)
89 {
90   return trash_report_format_in_use (report_format) == 0;
91 }
92 
93 /**
94  * @brief Get the name of a report format param type.
95  *
96  * @param[in]  type  Param type.
97  *
98  * @return The name of the param type.
99  */
100 const char *
report_format_param_type_name(report_format_param_type_t type)101 report_format_param_type_name (report_format_param_type_t type)
102 {
103   switch (type)
104     {
105       case REPORT_FORMAT_PARAM_TYPE_BOOLEAN:
106         return "boolean";
107       case REPORT_FORMAT_PARAM_TYPE_INTEGER:
108         return "integer";
109       case REPORT_FORMAT_PARAM_TYPE_SELECTION:
110         return "selection";
111       case REPORT_FORMAT_PARAM_TYPE_STRING:
112         return "string";
113       case REPORT_FORMAT_PARAM_TYPE_TEXT:
114         return "text";
115       case REPORT_FORMAT_PARAM_TYPE_REPORT_FORMAT_LIST:
116         return "report_format_list";
117       default:
118         assert (0);
119       case REPORT_FORMAT_PARAM_TYPE_ERROR:
120         return "ERROR";
121     }
122 }
123 
124 /**
125  * @brief Get a report format param type from a name.
126  *
127  * @param[in]  name  Param type name.
128  *
129  * @return The param type.
130  */
131 report_format_param_type_t
report_format_param_type_from_name(const char * name)132 report_format_param_type_from_name (const char *name)
133 {
134   if (strcmp (name, "boolean") == 0)
135     return REPORT_FORMAT_PARAM_TYPE_BOOLEAN;
136   if (strcmp (name, "integer") == 0)
137     return REPORT_FORMAT_PARAM_TYPE_INTEGER;
138   if (strcmp (name, "selection") == 0)
139     return REPORT_FORMAT_PARAM_TYPE_SELECTION;
140   if (strcmp (name, "string") == 0)
141     return REPORT_FORMAT_PARAM_TYPE_STRING;
142   if (strcmp (name, "text") == 0)
143     return REPORT_FORMAT_PARAM_TYPE_TEXT;
144   if (strcmp (name, "report_format_list") == 0)
145     return REPORT_FORMAT_PARAM_TYPE_REPORT_FORMAT_LIST;
146   return REPORT_FORMAT_PARAM_TYPE_ERROR;
147 }
148 
149 /**
150  * @brief Return whether a name is a backup file name.
151  *
152  * @param[in]  name  Name.
153  *
154  * @return 0 if normal file name, 1 if backup file name.
155  */
156 static int
backup_file_name(const char * name)157 backup_file_name (const char *name)
158 {
159   int length = strlen (name);
160 
161   if (length && (name[length - 1] == '~'))
162     return 1;
163 
164   if ((length > 3)
165       && (name[length - 4] == '.'))
166     return ((name[length - 3] == 'b')
167             && (name[length - 2] == 'a')
168             && (name[length - 1] == 'k'))
169            || ((name[length - 3] == 'B')
170                && (name[length - 2] == 'A')
171                && (name[length - 1] == 'K'))
172            || ((name[length - 3] == 'C')
173                && (name[length - 2] == 'K')
174                && (name[length - 1] == 'P'));
175 
176   return 0;
177 }
178 
179 /**
180  * @brief Get files associated with a report format.
181  *
182  * @param[in]   dir_name  Location of files.
183  * @param[out]  start     Files on success.
184  *
185  * @return 0 if successful, -1 otherwise.
186  */
187 static int
get_report_format_files(const char * dir_name,GPtrArray ** start)188 get_report_format_files (const char *dir_name, GPtrArray **start)
189 {
190   GPtrArray *files;
191   struct dirent **names;
192   int n, index;
193   char *locale;
194 
195   files = g_ptr_array_new ();
196 
197   locale = setlocale (LC_ALL, "C");
198   n = scandir (dir_name, &names, NULL, alphasort);
199   setlocale (LC_ALL, locale);
200   if (n < 0)
201     {
202       g_warning ("%s: failed to open dir %s: %s",
203                  __func__,
204                  dir_name,
205                  strerror (errno));
206       return -1;
207     }
208 
209   for (index = 0; index < n; index++)
210     {
211       if (strcmp (names[index]->d_name, ".")
212           && strcmp (names[index]->d_name, "..")
213           && (backup_file_name (names[index]->d_name) == 0))
214         g_ptr_array_add (files, g_strdup (names[index]->d_name));
215       free (names[index]);
216     }
217   free (names);
218 
219   g_ptr_array_add (files, NULL);
220 
221   *start = files;
222   return 0;
223 }
224 
225 /**
226  * @brief Initialise a report format file iterator.
227  *
228  * @param[in]  iterator       Iterator.
229  * @param[in]  report_format  Single report format to iterate over, NULL for
230  *                            all.
231  *
232  * @return 0 on success, -1 on error.
233  */
234 int
init_report_format_file_iterator(file_iterator_t * iterator,report_format_t report_format)235 init_report_format_file_iterator (file_iterator_t* iterator,
236                                   report_format_t report_format)
237 {
238   gchar *dir_name, *uuid, *owner_uuid;
239 
240   uuid = report_format_uuid (report_format);
241   if (uuid == NULL)
242     return -1;
243 
244   owner_uuid = report_format_owner_uuid (report_format);
245   if (owner_uuid == NULL)
246     return -1;
247   dir_name = g_build_filename (GVMD_STATE_DIR,
248                                "report_formats",
249                                owner_uuid,
250                                uuid,
251                                NULL);
252   g_free (owner_uuid);
253   g_free (uuid);
254 
255   if (get_report_format_files (dir_name, &iterator->start))
256     {
257       g_free (dir_name);
258       return -1;
259     }
260 
261   iterator->current = iterator->start->pdata;
262   iterator->current--;
263   iterator->dir_name = dir_name;
264   return 0;
265 }
266 
267 /**
268  * @brief Cleanup a report type iterator.
269  *
270  * @param[in]  iterator  Iterator.
271  */
272 void
cleanup_file_iterator(file_iterator_t * iterator)273 cleanup_file_iterator (file_iterator_t* iterator)
274 {
275   array_free (iterator->start);
276   g_free (iterator->dir_name);
277 }
278 
279 /**
280  * @brief Increment a report type iterator.
281  *
282  * The caller must stop using this after it returns FALSE.
283  *
284  * @param[in]  iterator  Task iterator.
285  *
286  * @return TRUE if there was a next item, else FALSE.
287  */
288 gboolean
next_file(file_iterator_t * iterator)289 next_file (file_iterator_t* iterator)
290 {
291   iterator->current++;
292   if (*iterator->current == NULL) return FALSE;
293   return TRUE;
294 }
295 
296 /**
297  * @brief Return the name from a file iterator.
298  *
299  * @param[in]  iterator  Iterator.
300  *
301  * @return File name.
302  */
303 const char*
file_iterator_name(file_iterator_t * iterator)304 file_iterator_name (file_iterator_t* iterator)
305 {
306   return (const char*) *iterator->current;
307 }
308 
309 /**
310  * @brief Return the file contents from a file iterator.
311  *
312  * @param[in]  iterator  Iterator.
313  *
314  * @return Freshly allocated file contents, in base64.
315  */
316 gchar*
file_iterator_content_64(file_iterator_t * iterator)317 file_iterator_content_64 (file_iterator_t* iterator)
318 {
319   gchar *path_name, *content;
320   GError *error;
321   gsize content_size;
322 
323   path_name = g_build_filename (iterator->dir_name,
324                                 (gchar*) *iterator->current,
325                                 NULL);
326 
327   /* Read in the contents. */
328 
329   error = NULL;
330   if (g_file_get_contents (path_name,
331                            &content,
332                            &content_size,
333                            &error)
334       == FALSE)
335     {
336       if (error)
337         {
338           g_debug ("%s: failed to read %s: %s",
339                    __func__, path_name, error->message);
340           g_error_free (error);
341         }
342       g_free (path_name);
343       return NULL;
344     }
345 
346   g_free (path_name);
347 
348   /* Base64 encode the contents. */
349 
350   if (content && (content_size > 0))
351     {
352       gchar *base64 = g_base64_encode ((guchar*) content, content_size);
353       g_free (content);
354       return base64;
355     }
356 
357   return content;
358 }
359 
360 
361 /* Feed report formats. */
362 
363 /**
364  * @brief Get path to report formats in feed.
365  *
366  * @return Path to report formats in feed.
367  */
368 static const gchar *
feed_dir_report_formats()369 feed_dir_report_formats ()
370 {
371   static gchar *path = NULL;
372   if (path == NULL)
373     path = g_build_filename (GVMD_FEED_DIR,
374                              GMP_VERSION_FEED,
375                              "report_formats",
376                              NULL);
377   return path;
378 }
379 
380 /**
381  * @brief Create a report format from an XML file.
382  *
383  * @param[in]  report_format  Existing report format.
384  * @param[in]  path           Full path to report format XML.
385  *
386  * @return 0 success, -1 error.
387  */
388 static int
update_report_format_from_file(report_format_t report_format,const gchar * path)389 update_report_format_from_file (report_format_t report_format,
390                                 const gchar *path)
391 {
392   entity_t entity;
393   array_t *files, *params, *params_options;
394   char *name, *content_type, *extension, *summary, *description, *signature;
395   const char *report_format_id;
396 
397   g_debug ("%s: updating %s", __func__, path);
398 
399   /* Parse the file into an entity. */
400 
401   if (parse_xml_file (path, &entity))
402     return 1;
403 
404   /* Parse the data out of the entity. */
405 
406   parse_report_format_entity (entity, &report_format_id, &name,
407                               &content_type, &extension, &summary,
408                               &description, &signature, &files, &params,
409                               &params_options);
410 
411   /* Update the report format. */
412 
413   update_report_format (report_format, report_format_id, name, content_type,
414                         extension, summary, description, signature, files,
415                         params, params_options);
416 
417   /* Cleanup. */
418 
419   array_free (files);
420   params_options_free (params_options);
421   array_free (params);
422   free_entity (entity);
423 
424   return 0;
425 }
426 
427 /**
428  * @brief Grant 'Feed Import Roles' access to a report format.
429  *
430  * @param[in]  report_format_id  UUID of report format.
431  */
432 static void
create_feed_report_format_permissions(const gchar * report_format_id)433 create_feed_report_format_permissions (const gchar *report_format_id)
434 {
435   gchar *roles, **split, **point;
436 
437   setting_value (SETTING_UUID_FEED_IMPORT_ROLES, &roles);
438 
439   if (roles == NULL || strlen (roles) == 0)
440     {
441       g_debug ("%s: no 'Feed Import Roles', so not creating permissions",
442                __func__);
443       g_free (roles);
444       return;
445     }
446 
447   point = split = g_strsplit (roles, ",", 0);
448   while (*point)
449     {
450       permission_t permission;
451 
452       if (create_permission_no_acl ("get_report_formats",
453                                     "Automatically created for report format"
454                                     " from feed",
455                                     NULL,
456                                     report_format_id,
457                                     "role",
458                                     g_strstrip (*point),
459                                     &permission))
460         /* Keep going because we aren't strict about checking the value
461          * of the setting, and because we don't adjust the setting when
462          * roles are removed. */
463         g_warning ("%s: failed to create permission for role '%s'",
464                    __func__, g_strstrip (*point));
465 
466       point++;
467     }
468   g_strfreev (split);
469 
470   g_free (roles);
471 }
472 
473 /**
474  * @brief Create a report format from an XML file.
475  *
476  * @param[in]  path  Path to report format XML.
477  *
478  * @return 0 success, -1 error.
479  */
480 static int
create_report_format_from_file(const gchar * path)481 create_report_format_from_file (const gchar *path)
482 {
483   entity_t report_format;
484   array_t *files, *params, *params_options;
485   char *name, *content_type, *extension, *summary, *description, *signature;
486   const char *report_format_id;
487   report_format_t new_report_format;
488 
489   g_debug ("%s: creating %s", __func__, path);
490 
491   /* Parse the file into an entity. */
492 
493   if (parse_xml_file (path, &report_format))
494     return 1;
495 
496   /* Parse the data out of the entity. */
497 
498   parse_report_format_entity (report_format, &report_format_id, &name,
499                               &content_type, &extension, &summary,
500                               &description, &signature, &files, &params,
501                               &params_options);
502 
503   /* Create the report format. */
504 
505   switch (create_report_format_no_acl (report_format_id,
506                                        name,
507                                        content_type,
508                                        extension,
509                                        summary,
510                                        description,
511                                        files,
512                                        params,
513                                        params_options,
514                                        signature,
515                                        1,
516                                        &new_report_format))
517     {
518       case 0:
519         {
520           gchar *uuid;
521 
522           uuid = report_format_uuid (new_report_format);
523           log_event ("report_format", "Report format", uuid, "created");
524 
525           /* Create permissions. */
526           create_feed_report_format_permissions (uuid);
527 
528           g_free (uuid);
529           break;
530         }
531       case 1:
532         g_warning ("%s: Report Format exists already", __func__);
533         log_event_fail ("report_format", "Report format", NULL, "created");
534         break;
535       case 2:
536         g_warning ("%s: Every FILE must have a name attribute", __func__);
537         log_event_fail ("report_format", "Report Format", NULL,
538                         "created");
539         break;
540       case 3:
541         g_warning ("%s: Parameter value validation failed", __func__);
542         log_event_fail ("report_format", "Report Format", NULL,
543                         "created");
544         break;
545       case 4:
546         g_warning ("%s: Parameter default validation failed", __func__);
547         log_event_fail ("report_format", "Report Format", NULL,
548                         "created");
549         break;
550       case 5:
551         g_warning ("%s: PARAM requires a DEFAULT element", __func__);
552         log_event_fail ("report_format", "Report Format", NULL,
553                         "created");
554         break;
555       case 6:
556         g_warning ("%s: PARAM MIN or MAX out of range", __func__);
557         log_event_fail ("report_format", "Report Format", NULL,
558                         "created");
559         break;
560       case 7:
561         g_warning ("%s: PARAM requires a TYPE element", __func__);
562         log_event_fail ("report_format", "Report Format", NULL,
563                         "created");
564         break;
565       case 8:
566         g_warning ("%s: Duplicate PARAM name", __func__);
567         log_event_fail ("report_format", "Report Format", NULL,
568                         "created");
569         break;
570       case 9:
571         g_warning ("%s: Bogus PARAM type", __func__);
572         log_event_fail ("report_format", "Report Format", NULL,
573                         "created");
574         break;
575       case 99:
576         g_warning ("%s: Permission denied", __func__);
577         log_event_fail ("report_format", "Report format", NULL, "created");
578         break;
579       default:
580       case -1:
581         g_warning ("%s: Internal error", __func__);
582         log_event_fail ("report_format", "Report format", NULL, "created");
583         break;
584     }
585 
586   /* Cleanup. */
587 
588   array_free (files);
589   params_options_free (params_options);
590   array_free (params);
591   free_entity (report_format);
592 
593   return 0;
594 }
595 
596 /**
597  * @brief Gets if a report format must be synced to a file path in the feed.
598  *
599  * @param[in]  path          Path to report format XML in feed.
600  * @param[in]  rebuild       Whether ignore timestamps to force a rebuild.
601  * @param[out] report_format Report format id if it already exists, 0 if new.
602  *
603  * @return 1 if report format should be synced, 0 otherwise
604  */
605 static int
should_sync_report_format_from_path(const char * path,gboolean rebuild,report_format_t * report_format)606 should_sync_report_format_from_path (const char *path,
607                                      gboolean rebuild,
608                                      report_format_t *report_format)
609 {
610   gchar **split, *full_path, *uuid;
611 
612   *report_format = 0;
613 
614   split = g_regex_split_simple
615            (/* Full-and-Fast--daba56c8-73ec-11df-a475-002264764cea.xml */
616             "^.*([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12}).xml$",
617             path, 0, 0);
618 
619   if (split == NULL || g_strv_length (split) != 7)
620     {
621       g_strfreev (split);
622       g_warning ("%s: path not in required format: %s", __func__, path);
623       return 0;
624     }
625 
626   uuid = g_strdup_printf ("%s-%s-%s-%s-%s",
627                           split[1], split[2], split[3], split[4], split[5]);
628   g_strfreev (split);
629   if (find_report_format_no_acl (uuid, report_format) == 0
630       && *report_format)
631     {
632       if (rebuild)
633         return 1;
634 
635       full_path = g_build_filename (feed_dir_report_formats (), path, NULL);
636 
637       g_free (uuid);
638 
639       g_debug ("%s: considering %s for update", __func__, path);
640 
641       if (report_format_updated_in_feed (*report_format, full_path))
642         {
643           return 1;
644         }
645 
646       g_free (full_path);
647       return 0;
648     }
649 
650   if (find_trash_report_format_no_acl (uuid, report_format) == 0
651       && *report_format)
652     {
653       g_free (uuid);
654       *report_format = 0;
655       return 0;
656     }
657 
658   g_free (uuid);
659   *report_format = 0;
660   return 1;
661 }
662 
663 /**
664  * @brief Sync a single report format with the feed.
665  *
666  * @param[in]  path     Path to report format XML in feed.
667  * @param[in]  rebuild  Whether ignore timestamps to force a rebuild.
668  */
669 static void
sync_report_format_with_feed(const gchar * path,gboolean rebuild)670 sync_report_format_with_feed (const gchar *path, gboolean rebuild)
671 {
672   report_format_t report_format;
673 
674   g_debug ("%s: considering %s", __func__, path);
675 
676   if (should_sync_report_format_from_path (path, rebuild, &report_format))
677     {
678       gchar *full_path;
679       full_path = g_build_filename (feed_dir_report_formats (), path, NULL);
680       switch (report_format)
681         {
682           case 0:
683             g_debug ("%s: adding %s", __func__, path);
684             create_report_format_from_file (full_path);
685             break;
686           default:
687             g_debug ("%s: updating %s", __func__, path);
688             update_report_format_from_file (report_format, full_path);
689         }
690       g_free (full_path);
691     }
692 }
693 
694 /**
695  * @brief Open the report formats feed directory if it is available and the
696  * feed owner is set.
697  * Optionally set the current user to the feed owner on success.
698  *
699  * The sync will be skipped if the feed directory does not exist or
700  *  the feed owner is not set.
701  *
702  * @param[out]  dir The directory as GDir if available and feed owner is set,
703  * NULL otherwise.
704  * @param[in]   set_current_user Whether to set current user to feed owner.
705  *
706  * @return 0 success, 1 no feed directory, 2 no feed owner, -1 error.
707  */
708 static int
try_open_report_formats_feed_dir(GDir ** dir,gboolean set_current_user)709 try_open_report_formats_feed_dir (GDir **dir, gboolean set_current_user)
710 {
711   char *feed_owner_uuid, *feed_owner_name;
712   GError *error;
713 
714   /* Test if base feed directory exists */
715 
716   if (report_formats_feed_dir_exists () == FALSE)
717     return 1;
718 
719   /* Setup owner. */
720 
721   setting_value (SETTING_UUID_FEED_IMPORT_OWNER, &feed_owner_uuid);
722 
723   if (feed_owner_uuid == NULL
724       || strlen (feed_owner_uuid) == 0)
725     {
726       /* Sync is disabled by having no "Feed Import Owner". */
727       g_debug ("%s: no Feed Import Owner so not syncing from feed", __func__);
728       return 2;
729     }
730 
731   feed_owner_name = user_name (feed_owner_uuid);
732   if (feed_owner_name == NULL)
733     {
734       g_debug ("%s: unknown Feed Import Owner so not syncing from feed",
735                __func__);
736       return 2;
737     }
738 
739   /* Open feed import directory. */
740 
741   error = NULL;
742   *dir = g_dir_open (feed_dir_report_formats (), 0, &error);
743   if (*dir == NULL)
744     {
745       g_warning ("%s: Failed to open directory '%s': %s",
746                  __func__, feed_dir_report_formats (), error->message);
747       g_error_free (error);
748       free (feed_owner_uuid);
749       free (feed_owner_name);
750       return -1;
751     }
752 
753   if (set_current_user)
754     {
755       current_credentials.uuid = feed_owner_uuid;
756       current_credentials.username = feed_owner_name;
757     }
758   else
759     {
760       free (feed_owner_uuid);
761       free (feed_owner_name);
762     }
763 
764   return 0;
765 }
766 
767 /**
768  * @brief Sync all report formats with the feed.
769  *
770  * Create report formats that exists in the feed but not in the db.
771  * Update report formats in the db that have changed on the feed.
772  * Do nothing to report formats in db that have been removed from the feed.
773  *
774  * @param[in]  rebuild  Whether ignore timestamps to force a rebuild.
775  *
776  * @return 0 success, 1 no feed directory, 2 no feed owner, -1 error.
777  */
778 int
sync_report_formats_with_feed(gboolean rebuild)779 sync_report_formats_with_feed (gboolean rebuild)
780 {
781   int ret;
782   GDir *dir;
783   const gchar *report_format_path;
784 
785   ret = try_open_report_formats_feed_dir (&dir, TRUE);
786   switch (ret)
787     {
788       case 0:
789         // Successfully opened directory
790         break;
791       default:
792         return ret;
793     }
794 
795   /* Sync each file in the directory. */
796 
797   while ((report_format_path = g_dir_read_name (dir)))
798     if (g_str_has_prefix (report_format_path, ".") == 0
799         && strlen (report_format_path) >= (36 /* UUID */ + strlen (".xml"))
800         && g_str_has_suffix (report_format_path, ".xml"))
801       sync_report_format_with_feed (report_format_path, rebuild);
802 
803   /* Cleanup. */
804 
805   g_dir_close (dir);
806   g_free (current_credentials.uuid);
807   g_free (current_credentials.username);
808   current_credentials.uuid = NULL;
809   current_credentials.username = NULL;
810 
811   return 0;
812 }
813 
814 /**
815  * @brief Tests if the report formats feed directory exists.
816  *
817  * @return TRUE if the directory exists.
818  */
819 gboolean
report_formats_feed_dir_exists()820 report_formats_feed_dir_exists ()
821 {
822   return gvm_file_is_readable (feed_dir_report_formats ());
823 }
824 
825 /**
826  * @brief Sync report formats with the feed.
827  */
828 void
manage_sync_report_formats()829 manage_sync_report_formats ()
830 {
831   sync_report_formats_with_feed (FALSE);
832 }
833 
834 /**
835  * @brief Rebuild port lists from the feed.
836  *
837  * @return 0 success, 1 no feed directory, 2 no feed owner, -1 error.
838  */
839 int
manage_rebuild_report_formats()840 manage_rebuild_report_formats ()
841 {
842   return sync_report_formats_with_feed (TRUE);
843 }
844 
845 /**
846  * @brief Checks if the report formats should be synced with the feed.
847  *
848  * @return 1 if report formats should be synced, 0 otherwise
849  */
850 gboolean
should_sync_report_formats()851 should_sync_report_formats ()
852 {
853   GDir *dir;
854   const gchar *report_format_path;
855   report_format_t report_format;
856 
857   if (try_open_report_formats_feed_dir (&dir, FALSE))
858     return FALSE;
859 
860   while ((report_format_path = g_dir_read_name (dir)))
861     if (g_str_has_prefix (report_format_path, ".") == 0
862         && strlen (report_format_path) >= (36 /* UUID */ + strlen (".xml"))
863         && g_str_has_suffix (report_format_path, ".xml")
864         && should_sync_report_format_from_path (report_format_path,
865                                                 FALSE,
866                                                 &report_format))
867       return TRUE;
868 
869   return FALSE;
870 }