Greenbone Vulnerability Management Libraries  22.8.0
xmlutils.c
Go to the documentation of this file.
1 /* SPDX-FileCopyrightText: 2009-2023 Greenbone AG
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  */
5 
15 #include "xmlutils.h"
16 
17 #include <assert.h> /* for assert */
18 #include <errno.h> /* for errno, EAGAIN, EINTR */
19 #include <fcntl.h> /* for fcntl, F_SETFL, O_NONBLOCK */
20 #include <glib.h> /* for g_free, GSList, g_markup_parse_context_free */
21 #include <glib/gtypes.h> /* for GPOINTER_TO_INT, GINT_TO_POINTER, gsize */
22 #include <libxml/parser.h>
23 #include <libxml/tree.h>
24 #include <string.h> /* for strcmp, strerror, strlen */
25 #include <time.h> /* for time, time_t */
26 #include <unistd.h> /* for ssize_t */
27 
28 #undef G_LOG_DOMAIN
29 
32 #define G_LOG_DOMAIN "libgvm util"
33 
37 #define BUFFER_SIZE 1048576
38 
47 static entity_t
48 make_entity (const char *name, const char *text)
49 {
50  entity_t entity;
51  entity = g_malloc (sizeof (*entity));
52  entity->name = g_strdup (name ? name : "");
53  entity->text = g_strdup (text ? text : "");
54  entity->entities = NULL;
55  entity->attributes = NULL;
56  return entity;
57 }
58 
68 {
69  if (entities)
70  return (entities_t) entities->next;
71  return NULL;
72 }
73 
83 {
84  if (entities)
85  return (entity_t) entities->data;
86  return NULL;
87 }
88 
100 entity_t
101 add_entity (entities_t *entities, const char *name, const char *text)
102 {
103  entity_t entity = make_entity (name, text);
104  if (entities)
105  *entities = g_slist_append (*entities, entity);
106  return entity;
107 }
108 
114 void
116 {
117  if (entity)
118  {
119  g_free (entity->name);
120  g_free (entity->text);
121  if (entity->attributes)
122  g_hash_table_destroy (entity->attributes);
123  if (entity->entities)
124  {
125  GSList *list = entity->entities;
126  while (list)
127  {
128  free_entity (list->data);
129  list = list->next;
130  }
131  g_slist_free (entity->entities);
132  }
133  g_free (entity);
134  }
135 }
136 
144 char *
146 {
147  if (!entity)
148  return NULL;
149 
150  return entity->text;
151 }
152 
160 char *
162 {
163  if (!entity)
164  return NULL;
165 
166  return entity->name;
167 }
168 
178 static int
179 compare_entity_with_name (gconstpointer entity, gconstpointer name)
180 {
181  return strcmp (entity_name ((entity_t) entity), (char *) name);
182 }
183 
192 entity_t
193 entity_child (entity_t entity, const char *name)
194 {
195  if (!entity)
196  return NULL;
197 
198  if (entity->entities)
199  {
200  entities_t match =
201  g_slist_find_custom (entity->entities, name, compare_entity_with_name);
202  return match ? (entity_t) match->data : NULL;
203  }
204  return NULL;
205 }
206 
215 const char *
216 entity_attribute (entity_t entity, const char *name)
217 {
218  if (!entity)
219  return NULL;
220 
221  if (entity->attributes)
222  return (const char *) g_hash_table_lookup (entity->attributes, name);
223  return NULL;
224 }
225 
233 static void
234 add_attributes (entity_t entity, const gchar **names, const gchar **values)
235 {
236  if (names && values && *names && *values)
237  {
238  if (entity->attributes == NULL)
239  entity->attributes =
240  g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
241  while (*names && *values)
242  {
243  if (*values)
244  g_hash_table_insert (entity->attributes, g_strdup (*names),
245  g_strdup (*values));
246  names++;
247  values++;
248  }
249  }
250 }
251 
262 static void
263 ignore_start_element (GMarkupParseContext *context, const gchar *element_name,
264  const gchar **attribute_names,
265  const gchar **attribute_values, gpointer user_data,
266  GError **error)
267 {
268  context_data_t *data = (context_data_t *) user_data;
269 
270  (void) context;
271  (void) element_name;
272  (void) attribute_names;
273  (void) attribute_values;
274  (void) error;
275 
276  data->current = GINT_TO_POINTER (GPOINTER_TO_INT (data->current) + 1);
277 }
278 
289 static void
290 handle_start_element (GMarkupParseContext *context, const gchar *element_name,
291  const gchar **attribute_names,
292  const gchar **attribute_values, gpointer user_data,
293  GError **error)
294 {
295  entity_t entity;
296  context_data_t *data = (context_data_t *) user_data;
297 
298  (void) context;
299  (void) error;
300  if (data->current)
301  {
302  entity_t current = (entity_t) data->current->data;
303  entity = add_entity (&current->entities, element_name, NULL);
304  }
305  else
306  entity = add_entity (NULL, element_name, NULL);
307 
308  add_attributes (entity, attribute_names, attribute_values);
309 
310  /* "Push" the element. */
311  if (data->first == NULL)
312  data->current = data->first = g_slist_prepend (NULL, entity);
313  else
314  data->current = g_slist_prepend (data->current, entity);
315 }
316 
325 void
327  const gchar **attribute_names,
328  const gchar **attribute_values)
329 {
330  handle_start_element (NULL, element_name, attribute_names, attribute_values,
331  context, NULL);
332 }
333 
342 static void
343 ignore_end_element (GMarkupParseContext *context, const gchar *element_name,
344  gpointer user_data, GError **error)
345 {
346  context_data_t *data = (context_data_t *) user_data;
347 
348  (void) context;
349  (void) element_name;
350  (void) error;
351 
352  data->current = GINT_TO_POINTER (GPOINTER_TO_INT (data->current) - 1);
353  if (data->current == NULL)
354  data->done = TRUE;
355 }
356 
365 static void
366 handle_end_element (GMarkupParseContext *context, const gchar *element_name,
367  gpointer user_data, GError **error)
368 {
369  context_data_t *data = (context_data_t *) user_data;
370 
371  (void) context;
372  (void) error;
373  (void) element_name;
374  assert (data->current && data->first);
375  if (data->current == data->first)
376  {
377  assert (strcmp (element_name,
378  /* The name of the very first entity. */
379  ((entity_t) (data->first->data))->name)
380  == 0);
381  data->done = TRUE;
382  /* "Pop" the element. */
383  data->current = g_slist_next (data->current);
384  }
385  else if (data->current)
386  {
387  GSList *front;
388  /* "Pop" and free the element. */
389  front = data->current;
390  data->current = g_slist_next (data->current);
391  g_slist_free_1 (front);
392  }
393 }
394 
401 void
403 {
404  handle_end_element (NULL, element_name, context, NULL);
405 }
406 
416 static void
417 ignore_text (GMarkupParseContext *context, const gchar *text, gsize text_len,
418  gpointer user_data, GError **error)
419 {
420  (void) context;
421  (void) text;
422  (void) text_len;
423  (void) user_data;
424  (void) error;
425 }
426 
436 static void
437 handle_text (GMarkupParseContext *context, const gchar *text, gsize text_len,
438  gpointer user_data, GError **error)
439 {
440  context_data_t *data = (context_data_t *) user_data;
441 
442  (void) context;
443  (void) text_len;
444  (void) error;
445  entity_t current = (entity_t) data->current->data;
446  if (current->text)
447  {
448  gchar *old = current->text;
449  current->text = g_strconcat (current->text, text, NULL);
450  g_free (old);
451  }
452  else
453  current->text = g_strdup (text);
454 }
455 
463 void
464 xml_handle_text (context_data_t *context, const gchar *text, gsize text_len)
465 {
466  handle_text (NULL, text, text_len, context, NULL);
467 }
468 
476 static void
477 handle_error (GMarkupParseContext *context, GError *error, gpointer user_data)
478 {
479  (void) context;
480  (void) user_data;
481  g_message (" Error: %s\n", error->message);
482 }
483 
500 int
501 try_read_entity_and_string (gnutls_session_t *session, int timeout,
502  entity_t *entity, GString **string_return)
503 {
504  GMarkupParser xml_parser;
505  GError *error = NULL;
506  GMarkupParseContext *xml_context;
507  GString *string;
508  int socket;
509  time_t last_time;
510 
511  // Buffer for reading from the manager.
512  char *buffer;
513 
514  /* Record the start time. */
515 
516  if (time (&last_time) == -1)
517  {
518  g_warning (" failed to get current time: %s\n", strerror (errno));
519  return -1;
520  }
521 
522  if (timeout > 0)
523  {
524  /* Turn off blocking. */
525 
526  socket = GPOINTER_TO_INT (gnutls_transport_get_ptr (*session));
527  if (fcntl (socket, F_SETFL, O_NONBLOCK) == -1)
528  return -1;
529  }
530  else
531  /* Quiet compiler. */
532  socket = 0;
533 
534  buffer = g_malloc0 (BUFFER_SIZE);
535  if (!buffer)
536  return -5;
537 
538  /* Setup return arg. */
539 
540  if (string_return == NULL)
541  string = NULL;
542  else if (*string_return == NULL)
543  string = g_string_new ("");
544  else
545  string = *string_return;
546 
547  /* Create the XML parser. */
548 
549  if (entity)
550  {
551  xml_parser.start_element = handle_start_element;
552  xml_parser.end_element = handle_end_element;
553  xml_parser.text = handle_text;
554  }
555  else
556  {
557  xml_parser.start_element = ignore_start_element;
558  xml_parser.end_element = ignore_end_element;
559  xml_parser.text = ignore_text;
560  }
561  xml_parser.passthrough = NULL;
562  xml_parser.error = handle_error;
563 
564  context_data_t context_data;
565  context_data.done = FALSE;
566  context_data.first = NULL;
567  context_data.current = NULL;
568 
569  /* Setup the XML context. */
570 
571  xml_context =
572  g_markup_parse_context_new (&xml_parser, 0, &context_data, NULL);
573 
574  /* Read and parse, until encountering end of file or error. */
575 
576  while (1)
577  {
578  ssize_t count;
579  int retries = 10;
580  while (1)
581  {
582  g_debug (" asking for %i\n", BUFFER_SIZE);
583  count = gnutls_record_recv (*session, buffer, BUFFER_SIZE);
584  if (count < 0)
585  {
586  if (count == GNUTLS_E_INTERRUPTED)
587  /* Interrupted, try read again. */
588  continue;
589  if ((timeout > 0) && (count == GNUTLS_E_AGAIN))
590  {
591  /* Server still busy, either timeout or try read again. */
592  if ((timeout - (time (NULL) - last_time)) <= 0)
593  {
594  g_warning (" timeout\n");
595  if (fcntl (socket, F_SETFL, 0L) < 0)
596  g_warning ("%s :failed to set socket flag: %s",
597  __func__, strerror (errno));
598  g_markup_parse_context_free (xml_context);
599  g_free (buffer);
600  return -4;
601  }
602  continue;
603  }
604  else if ((timeout == 0) && (count == GNUTLS_E_AGAIN))
605  {
606  /* Server still busy, try read again.
607  If there is no timeout set and the server is still not
608  ready, it will try up to 10 times before closing the
609  socket.*/
610  if (retries > 0)
611  {
612  retries = retries - 1;
613  continue;
614  }
615  }
616 
617  if (count == GNUTLS_E_REHANDSHAKE)
618  /* Try again. TODO Rehandshake. */
619  continue;
620  if (context_data.first && context_data.first->data)
621  {
622  free_entity (context_data.first->data);
623  g_slist_free_1 (context_data.first);
624  }
625  if (string && *string_return == NULL)
626  g_string_free (string, TRUE);
627  if (timeout > 0)
628  {
629  if (fcntl (socket, F_SETFL, 0L) < 0)
630  g_warning ("%s :failed to set socket flag: %s", __func__,
631  strerror (errno));
632  }
633  g_markup_parse_context_free (xml_context);
634  g_free (buffer);
635  return -1;
636  }
637  if (count == 0)
638  {
639  /* End of file. */
640  g_markup_parse_context_end_parse (xml_context, &error);
641  if (error)
642  {
643  g_warning (" End error: %s\n", error->message);
644  g_error_free (error);
645  }
646  if (context_data.first && context_data.first->data)
647  {
648  free_entity (context_data.first->data);
649  g_slist_free_1 (context_data.first);
650  }
651  if (string && *string_return == NULL)
652  g_string_free (string, TRUE);
653  if (timeout > 0)
654  {
655  if (fcntl (socket, F_SETFL, 0L) < 0)
656  g_warning ("%s :failed to set socket flag: %s", __func__,
657  strerror (errno));
658  }
659  g_markup_parse_context_free (xml_context);
660  g_free (buffer);
661  return -3;
662  }
663  break;
664  }
665 
666  g_debug ("<= %.*s\n", (int) count, buffer);
667 
668  if (string)
669  g_string_append_len (string, buffer, count);
670 
671  g_markup_parse_context_parse (xml_context, buffer, count, &error);
672  if (error)
673  {
674  g_error_free (error);
675  if (context_data.first && context_data.first->data)
676  {
677  free_entity (context_data.first->data);
678  g_slist_free_1 (context_data.first);
679  }
680  if (string && *string_return == NULL)
681  g_string_free (string, TRUE);
682  if (timeout > 0)
683  {
684  if (fcntl (socket, F_SETFL, 0L) < 0)
685  g_warning ("%s :failed to set socket flag: %s", __func__,
686  strerror (errno));
687  }
688  g_markup_parse_context_free (xml_context);
689  g_free (buffer);
690  return -2;
691  }
692  if (context_data.done)
693  {
694  g_markup_parse_context_end_parse (xml_context, &error);
695  if (error)
696  {
697  g_warning (" End error: %s\n", error->message);
698  g_error_free (error);
699  if (context_data.first && context_data.first->data)
700  {
701  free_entity (context_data.first->data);
702  g_slist_free_1 (context_data.first);
703  }
704  if (timeout > 0)
705  fcntl (socket, F_SETFL, 0L);
706  g_markup_parse_context_free (xml_context);
707  g_free (buffer);
708  return -2;
709  }
710  if (entity)
711  *entity = (entity_t) context_data.first->data;
712  if (string)
713  *string_return = string;
714  if (timeout > 0)
715  fcntl (socket, F_SETFL, 0L);
716  g_markup_parse_context_free (xml_context);
717  g_free (buffer);
718  return 0;
719  }
720 
721  if ((timeout > 0) && (time (&last_time) == -1))
722  {
723  g_warning (" failed to get current time (1): %s\n",
724  strerror (errno));
725  if (fcntl (socket, F_SETFL, 0L) < 0)
726  g_warning ("%s :failed to set socket flag: %s", __func__,
727  strerror (errno));
728  g_markup_parse_context_free (xml_context);
729  g_free (buffer);
730  return -1;
731  }
732  }
733 }
734 
751 static int
752 try_read_string (gnutls_session_t *session, int timeout,
753  GString **string_return)
754 {
755  GString *string;
756  int socket;
757  time_t last_time;
758  char *buffer; // Buffer for reading from the server.
759 
760  /* Record the start time. */
761 
762  if (time (&last_time) == -1)
763  {
764  g_warning (" failed to get current time: %s\n", strerror (errno));
765  return -1;
766  }
767 
768  if (timeout > 0)
769  {
770  /* Turn off blocking. */
771 
772  socket = GPOINTER_TO_INT (gnutls_transport_get_ptr (*session));
773  if (fcntl (socket, F_SETFL, O_NONBLOCK) == -1)
774  return -1;
775  }
776  else
777  /* Quiet compiler. */
778  socket = 0;
779 
780  buffer = g_malloc0 (BUFFER_SIZE);
781  if (!buffer)
782  return -5;
783 
784  /* Setup return arg. */
785 
786  if (string_return == NULL)
787  string = NULL;
788  else if (*string_return == NULL)
789  string = g_string_new ("");
790  else
791  string = *string_return;
792 
793  /* Read until encountering end of file or error. */
794 
795  while (1)
796  {
797  ssize_t count;
798  int retries = 10;
799  while (1)
800  {
801  g_debug (" asking for %i\n", BUFFER_SIZE);
802  count = gnutls_record_recv (*session, buffer, BUFFER_SIZE);
803  if (count < 0)
804  {
805  if (count == GNUTLS_E_INTERRUPTED)
806  /* Interrupted, try read again. */
807  continue;
808  if ((timeout > 0) && (count == GNUTLS_E_AGAIN))
809  {
810  /* Server still busy, either timeout or try read again. */
811  if ((timeout - (time (NULL) - last_time)) <= 0)
812  {
813  g_warning (" timeout\n");
814  if (fcntl (socket, F_SETFL, 0L) < 0)
815  g_warning ("%s: failed to set socket flag: %s",
816  __func__, strerror (errno));
817  g_free (buffer);
818  return -4;
819  }
820  continue;
821  }
822  else if ((timeout == 0) && (count == GNUTLS_E_AGAIN))
823  {
824  /* Server still busy, try read again.
825  * If there is no timeout set and the server is still not
826  * ready, it will try up to 10 times before closing the
827  * socket. */
828  if (retries > 0)
829  {
830  retries = retries - 1;
831  continue;
832  }
833  }
834 
835  if (count == GNUTLS_E_REHANDSHAKE)
836  /* Try again. TODO Rehandshake. */
837  continue;
838  if (string && (*string_return == NULL))
839  g_string_free (string, TRUE);
840  if (timeout > 0)
841  {
842  if (fcntl (socket, F_SETFL, 0L) < 0)
843  g_warning ("%s: failed to set socket flag: %s", __func__,
844  strerror (errno));
845  }
846  g_free (buffer);
847  return -1;
848  }
849  if (count == 0)
850  {
851  /* End of file. */
852  if (timeout > 0)
853  {
854  if (fcntl (socket, F_SETFL, 0L) < 0)
855  g_warning ("%s :failed to set socket flag: %s", __func__,
856  strerror (errno));
857  }
858  if (string)
859  *string_return = string;
860  g_free (buffer);
861  return 0;
862  }
863  break;
864  }
865 
866  g_debug ("<= %.*s\n", (int) count, buffer);
867 
868  if (string)
869  g_string_append_len (string, buffer, count);
870 
871  if ((timeout > 0) && (time (&last_time) == -1))
872  {
873  g_warning (" failed to get current time (1): %s\n",
874  strerror (errno));
875  if (fcntl (socket, F_SETFL, 0L) < 0)
876  g_warning ("%s :failed to set socket flag: %s", __func__,
877  strerror (errno));
878  g_free (buffer);
879  return -1;
880  }
881  }
882 }
883 
899 static int
900 try_read_string_s (int socket, int timeout, GString **string_return)
901 {
902  GString *string;
903  time_t last_time;
904  /* Buffer for reading from the socket. */
905  char *buffer;
906 
907  /* Record the start time. */
908 
909  if (time (&last_time) == -1)
910  {
911  g_warning (" failed to get current time: %s\n", strerror (errno));
912  return -1;
913  }
914 
915  if (timeout > 0)
916  {
917  /* Turn off blocking. */
918 
919  if (fcntl (socket, F_SETFL, O_NONBLOCK) == -1)
920  return -1;
921  }
922 
923  buffer = g_malloc0 (BUFFER_SIZE);
924  if (!buffer)
925  return -5;
926 
927  /* Setup return arg. */
928 
929  if (string_return == NULL)
930  string = NULL;
931  else if (*string_return == NULL)
932  string = g_string_sized_new (8192);
933  else
934  string = *string_return;
935 
936  /* Read until encountering end of file or error. */
937 
938  while (1)
939  {
940  int count;
941  while (1)
942  {
943  g_debug (" asking for %i\n", BUFFER_SIZE);
944  count = read (socket, buffer, BUFFER_SIZE);
945  if (count < 0)
946  {
947  if (errno == EINTR)
948  /* Interrupted, try read again. */
949  continue;
950  if (timeout > 0)
951  {
952  if (errno == EAGAIN)
953  {
954  /* Server still busy, either timeout or try read again. */
955  if ((timeout - (time (NULL) - last_time)) <= 0)
956  {
957  g_warning (" timeout\n");
958  if (fcntl (socket, F_SETFL, 0L) < 0)
959  g_warning ("%s :failed to set socket flag: %s",
960  __func__, strerror (errno));
961  g_free (buffer);
962  if (string && *string_return == NULL)
963  g_string_free (string, TRUE);
964  return -4;
965  }
966  }
967  continue;
968  }
969  if (string && *string_return == NULL)
970  g_string_free (string, TRUE);
971  if (timeout > 0)
972  fcntl (socket, F_SETFL, 0L);
973  g_free (buffer);
974  return -1;
975  }
976  if (count == 0)
977  {
978  /* End of file. */
979  if (timeout > 0)
980  {
981  if (fcntl (socket, F_SETFL, 0L) < 0)
982  g_warning ("%s :failed to set socket flag: %s", __func__,
983  strerror (errno));
984  }
985  if (string)
986  *string_return = string;
987  g_free (buffer);
988  return 0;
989  }
990  break;
991  }
992 
993  g_debug ("<= %.*s\n", (int) count, buffer);
994 
995  if (string)
996  g_string_append_len (string, buffer, count);
997 
998  if ((timeout > 0) && (time (&last_time) == -1))
999  {
1000  g_warning (" failed to get current time (1): %s\n",
1001  strerror (errno));
1002  if (fcntl (socket, F_SETFL, 0L) < 0)
1003  g_warning ("%s :failed to set server socket flag: %s", __func__,
1004  strerror (errno));
1005  g_free (buffer);
1006  if (string && *string_return == NULL)
1007  g_string_free (string, TRUE);
1008  return -1;
1009  }
1010  }
1011 }
1012 
1029 static int
1030 try_read_entity_and_string_s (int socket, int timeout, entity_t *entity,
1031  GString **string_return)
1032 {
1033  GMarkupParser xml_parser;
1034  GError *error = NULL;
1035  GMarkupParseContext *xml_context;
1036  GString *string;
1037  time_t last_time;
1038  /* Buffer for reading from the socket. */
1039  char *buffer;
1040 
1041  /* Record the start time. */
1042 
1043  if (time (&last_time) == -1)
1044  {
1045  g_warning (" failed to get current time: %s\n", strerror (errno));
1046  return -1;
1047  }
1048 
1049  if (timeout > 0)
1050  {
1051  /* Turn off blocking. */
1052 
1053  if (fcntl (socket, F_SETFL, O_NONBLOCK) == -1)
1054  return -1;
1055  }
1056 
1057  buffer = g_malloc0 (BUFFER_SIZE);
1058  if (!buffer)
1059  return -5;
1060 
1061  /* Setup return arg. */
1062 
1063  if (string_return == NULL)
1064  string = NULL;
1065  else if (*string_return == NULL)
1066  string = g_string_new ("");
1067  else
1068  string = *string_return;
1069 
1070  /* Create the XML parser. */
1071 
1072  if (entity)
1073  {
1074  xml_parser.start_element = handle_start_element;
1075  xml_parser.end_element = handle_end_element;
1076  xml_parser.text = handle_text;
1077  }
1078  else
1079  {
1080  xml_parser.start_element = ignore_start_element;
1081  xml_parser.end_element = ignore_end_element;
1082  xml_parser.text = ignore_text;
1083  }
1084  xml_parser.passthrough = NULL;
1085  xml_parser.error = handle_error;
1086 
1087  context_data_t context_data;
1088  context_data.done = FALSE;
1089  context_data.first = NULL;
1090  context_data.current = NULL;
1091 
1092  /* Setup the XML context. */
1093 
1094  xml_context =
1095  g_markup_parse_context_new (&xml_parser, 0, &context_data, NULL);
1096 
1097  /* Read and parse, until encountering end of file or error. */
1098 
1099  while (1)
1100  {
1101  int count;
1102  while (1)
1103  {
1104  g_debug (" asking for %i\n", BUFFER_SIZE);
1105  count = read (socket, buffer, BUFFER_SIZE);
1106  if (count < 0)
1107  {
1108  if (errno == EINTR)
1109  /* Interrupted, try read again. */
1110  continue;
1111  if (timeout > 0)
1112  {
1113  if (errno == EAGAIN)
1114  {
1115  /* Server still busy, either timeout or try read again. */
1116  if ((timeout - (time (NULL) - last_time)) <= 0)
1117  {
1118  g_warning (" timeout\n");
1119  if (fcntl (socket, F_SETFL, 0L) < 0)
1120  g_warning ("%s :failed to set socket flag: %s",
1121  __func__, strerror (errno));
1122  g_markup_parse_context_free (xml_context);
1123  g_free (buffer);
1124  if (string && *string_return == NULL)
1125  g_string_free (string, TRUE);
1126  return -4;
1127  }
1128  }
1129  continue;
1130  }
1131  if (context_data.first && context_data.first->data)
1132  {
1133  free_entity (context_data.first->data);
1134  g_slist_free_1 (context_data.first);
1135  }
1136  if (string && *string_return == NULL)
1137  g_string_free (string, TRUE);
1138  if (timeout > 0)
1139  fcntl (socket, F_SETFL, 0L);
1140  g_markup_parse_context_free (xml_context);
1141  g_free (buffer);
1142  return -1;
1143  }
1144  if (count == 0)
1145  {
1146  /* End of file. */
1147  g_markup_parse_context_end_parse (xml_context, &error);
1148  if (error)
1149  {
1150  g_warning (" End error: %s\n", error->message);
1151  g_error_free (error);
1152  }
1153  if (context_data.first && context_data.first->data)
1154  {
1155  free_entity (context_data.first->data);
1156  g_slist_free_1 (context_data.first);
1157  }
1158  if (string && *string_return == NULL)
1159  g_string_free (string, TRUE);
1160  if (timeout > 0)
1161  {
1162  if (fcntl (socket, F_SETFL, 0L) < 0)
1163  g_warning ("%s :failed to set socket flag: %s", __func__,
1164  strerror (errno));
1165  }
1166  g_markup_parse_context_free (xml_context);
1167  g_free (buffer);
1168  return -3;
1169  }
1170  break;
1171  }
1172 
1173  g_debug ("<= %.*s\n", (int) count, buffer);
1174 
1175  if (string)
1176  g_string_append_len (string, buffer, count);
1177 
1178  g_markup_parse_context_parse (xml_context, buffer, count, &error);
1179  if (error)
1180  {
1181  g_error_free (error);
1182  // FIX there may be multiple entries in list
1183  if (context_data.first && context_data.first->data)
1184  {
1185  free_entity (context_data.first->data);
1186  g_slist_free_1 (context_data.first);
1187  }
1188  if (string && *string_return == NULL)
1189  g_string_free (string, TRUE);
1190  if (timeout > 0)
1191  {
1192  if (fcntl (socket, F_SETFL, 0L) < 0)
1193  g_warning ("%s :failed to set socket flag: %s", __func__,
1194  strerror (errno));
1195  }
1196  g_markup_parse_context_free (xml_context);
1197  g_free (buffer);
1198  return -2;
1199  }
1200  if (context_data.done)
1201  {
1202  g_markup_parse_context_end_parse (xml_context, &error);
1203  if (error)
1204  {
1205  g_warning (" End error: %s\n", error->message);
1206  g_error_free (error);
1207  if (context_data.first && context_data.first->data)
1208  {
1209  free_entity (context_data.first->data);
1210  g_slist_free_1 (context_data.first);
1211  }
1212  if (timeout > 0)
1213  fcntl (socket, F_SETFL, 0L);
1214  g_markup_parse_context_free (xml_context);
1215  g_free (buffer);
1216  if (string && *string_return == NULL)
1217  g_string_free (string, TRUE);
1218  return -2;
1219  }
1220  if (entity)
1221  *entity = (entity_t) context_data.first->data;
1222  if (string)
1223  *string_return = string;
1224  if (timeout > 0)
1225  fcntl (socket, F_SETFL, 0L);
1226  g_slist_free (context_data.first);
1227  g_markup_parse_context_free (xml_context);
1228  g_free (buffer);
1229  return 0;
1230  }
1231 
1232  if ((timeout > 0) && (time (&last_time) == -1))
1233  {
1234  g_warning (" failed to get current time (1): %s\n",
1235  strerror (errno));
1236  if (fcntl (socket, F_SETFL, 0L) < 0)
1237  g_warning ("%s :failed to set server socket flag: %s", __func__,
1238  strerror (errno));
1239  g_markup_parse_context_free (xml_context);
1240  g_free (buffer);
1241  if (string && *string_return == NULL)
1242  g_string_free (string, TRUE);
1243  return -1;
1244  }
1245  }
1246 }
1247 
1261 int
1262 read_entity_and_string (gnutls_session_t *session, entity_t *entity,
1263  GString **string_return)
1264 {
1265  return try_read_entity_and_string (session, 0, entity, string_return);
1266 }
1267 
1281 int
1283  GString **string_return)
1284 {
1285  if (connection->tls)
1286  return try_read_entity_and_string (&connection->session, 0, entity,
1287  string_return);
1288  return try_read_entity_and_string_s (connection->socket, 0, entity,
1289  string_return);
1290 }
1291 
1304 int
1305 read_entity_and_text (gnutls_session_t *session, entity_t *entity, char **text)
1306 {
1307  if (text)
1308  {
1309  GString *string = NULL;
1310  int ret = read_entity_and_string (session, entity, &string);
1311  if (ret)
1312  {
1313  if (string)
1314  g_string_free (string, TRUE);
1315  return ret;
1316  }
1317  *text = g_string_free (string, FALSE);
1318  return 0;
1319  }
1320  return read_entity_and_string (session, entity, NULL);
1321 }
1322 
1335 int
1337  char **text)
1338 {
1339  if (text)
1340  {
1341  GString *string = NULL;
1342  int ret = read_entity_and_string_c (connection, entity, &string);
1343  if (ret)
1344  {
1345  if (string)
1346  g_string_free (string, TRUE);
1347  return ret;
1348  }
1349  *text = g_string_free (string, FALSE);
1350  return 0;
1351  }
1352  return read_entity_and_string_c (connection, entity, NULL);
1353 }
1354 
1365 int
1366 read_text_c (gvm_connection_t *connection, char **text)
1367 {
1368  GString *string;
1369  int ret;
1370 
1371  if (text == NULL)
1372  return -2;
1373 
1374  string = NULL;
1375 
1376  if (connection->tls)
1377  ret = try_read_string (&connection->session, 0, &string);
1378  else
1379  ret = try_read_string_s (connection->socket, 0, &string);
1380 
1381  if (ret)
1382  {
1383  if (string)
1384  g_string_free (string, TRUE);
1385  return ret;
1386  }
1387  *text = g_string_free (string, FALSE);
1388  return 0;
1389 }
1390 
1399 int
1400 read_string (gnutls_session_t *session, GString **string)
1401 {
1402  int ret = 0;
1403  entity_t entity;
1404 
1405  if (!(ret = read_entity_and_string (session, &entity, string)))
1406  free_entity (entity);
1407 
1408  return ret;
1409 }
1410 
1419 int
1420 read_string_c (gvm_connection_t *connection, GString **string)
1421 {
1422  return read_entity_and_string_c (connection, NULL, string);
1423 }
1424 
1435 int
1436 try_read_entity (gnutls_session_t *session, int timeout, entity_t *entity)
1437 {
1438  return try_read_entity_and_string (session, timeout, entity, NULL);
1439 }
1440 
1451 int
1452 try_read_entity_c (gvm_connection_t *connection, int timeout, entity_t *entity)
1453 {
1454  if (connection->tls)
1455  return try_read_entity_and_string (&connection->session, 0, entity, NULL);
1456  return try_read_entity_and_string_s (connection->socket, timeout, entity,
1457  NULL);
1458 }
1459 
1468 int
1469 read_entity (gnutls_session_t *session, entity_t *entity)
1470 {
1471  return try_read_entity (session, 0, entity);
1472 }
1473 
1482 int
1483 read_entity_s (int socket, entity_t *entity)
1484 {
1485  return try_read_entity_and_string_s (socket, 0, entity, NULL);
1486 }
1487 
1496 int
1498 {
1499  return try_read_entity_c (connection, 0, entity);
1500 }
1501 
1510 int
1511 parse_entity (const char *string, entity_t *entity)
1512 {
1513  GMarkupParser xml_parser;
1514  GError *error = NULL;
1515  GMarkupParseContext *xml_context;
1516  context_data_t context_data;
1517 
1518  /* Create the XML parser. */
1519 
1520  xml_parser.start_element = handle_start_element;
1521  xml_parser.end_element = handle_end_element;
1522  xml_parser.text = handle_text;
1523  xml_parser.passthrough = NULL;
1524  xml_parser.error = handle_error;
1525 
1526  context_data.done = FALSE;
1527  context_data.first = NULL;
1528  context_data.current = NULL;
1529 
1530  /* Setup the XML context. */
1531 
1532  xml_context =
1533  g_markup_parse_context_new (&xml_parser, 0, &context_data, NULL);
1534 
1535  /* Parse the string. */
1536 
1537  g_markup_parse_context_parse (xml_context, string, strlen (string), &error);
1538  if (error)
1539  {
1540  g_error_free (error);
1541  if (context_data.first && context_data.first->data)
1542  {
1543  free_entity (context_data.first->data);
1544  g_slist_free_1 (context_data.first);
1545  }
1546  return -2;
1547  }
1548  if (context_data.done)
1549  {
1550  g_markup_parse_context_end_parse (xml_context, &error);
1551  if (error)
1552  {
1553  g_warning (" End error: %s\n", error->message);
1554  g_error_free (error);
1555  if (context_data.first && context_data.first->data)
1556  {
1557  free_entity (context_data.first->data);
1558  g_slist_free_1 (context_data.first);
1559  }
1560  return -2;
1561  }
1562  *entity = (entity_t) context_data.first->data;
1563  g_slist_free_1 (context_data.first);
1564  return 0;
1565  }
1566  if (context_data.first && context_data.first->data)
1567  {
1568  free_entity (context_data.first->data);
1569  g_slist_free_1 (context_data.first);
1570  }
1571  return -3;
1572 }
1573 
1580 static void
1581 foreach_print_entity_to_string (gpointer entity, gpointer string)
1582 {
1583  print_entity_to_string ((entity_t) entity, (GString *) string);
1584 }
1585 
1593 static void
1594 foreach_print_attribute_to_string (gpointer name, gpointer value,
1595  gpointer string)
1596 {
1597  gchar *text_escaped;
1598  text_escaped = g_markup_escape_text ((gchar *) value, -1);
1599  g_string_append_printf ((GString *) string, " %s=\"%s\"", (char *) name,
1600  text_escaped);
1601  g_free (text_escaped);
1602 }
1603 
1611 void
1612 print_entity_to_string (entity_t entity, GString *string)
1613 {
1614  gchar *text_escaped = NULL;
1615  g_string_append_printf (string, "<%s", entity->name);
1616  if (entity->attributes && g_hash_table_size (entity->attributes))
1617  g_hash_table_foreach (entity->attributes, foreach_print_attribute_to_string,
1618  string);
1619  g_string_append_printf (string, ">");
1620  text_escaped = g_markup_escape_text (entity->text, -1);
1621  g_string_append_printf (string, "%s", text_escaped);
1622  g_free (text_escaped);
1623  g_slist_foreach (entity->entities, foreach_print_entity_to_string, string);
1624  g_string_append_printf (string, "</%s>", entity->name);
1625 }
1626 
1633 static void
1634 foreach_print_entity (gpointer entity, gpointer stream)
1635 {
1636  print_entity ((FILE *) stream, (entity_t) entity);
1637 }
1638 
1646 static void
1647 foreach_print_attribute (gpointer name, gpointer value, gpointer stream)
1648 {
1649  fprintf ((FILE *) stream, " %s=\"%s\"", (char *) name, (char *) value);
1650 }
1651 
1658 void
1659 print_entity (FILE *stream, entity_t entity)
1660 {
1661  gchar *text_escaped = NULL;
1662  fprintf (stream, "<%s", entity->name);
1663  if (entity->attributes && g_hash_table_size (entity->attributes))
1664  g_hash_table_foreach (entity->attributes, foreach_print_attribute, stream);
1665  fprintf (stream, ">");
1666  text_escaped = g_markup_escape_text (entity->text, -1);
1667  fprintf (stream, "%s", text_escaped);
1668  g_free (text_escaped);
1669  g_slist_foreach (entity->entities, foreach_print_entity, stream);
1670  fprintf (stream, "</%s>", entity->name);
1671  fflush (stream);
1672 }
1673 
1674 /* "Formatted" (indented) output of entity_t */
1675 
1683 static void
1684 foreach_print_attribute_format (gpointer name, gpointer value, gpointer none)
1685 {
1686  (void) none;
1687  printf (" %s=\"%s\"", (char *) name, (char *) value);
1688 }
1689 
1701 void
1702 print_entity_format (entity_t entity, gpointer indent)
1703 {
1704  int i = 0;
1705  int indentation = GPOINTER_TO_INT (indent);
1706  gchar *text_escaped = NULL;
1707 
1708  for (i = 0; i < indentation; i++)
1709  printf (" ");
1710 
1711  printf ("<%s", entity->name);
1712  if (entity->attributes && g_hash_table_size (entity->attributes))
1713  g_hash_table_foreach (entity->attributes, foreach_print_attribute_format,
1714  indent);
1715  printf (">");
1716 
1717  text_escaped = g_markup_escape_text (entity->text, -1);
1718  printf ("%s", text_escaped);
1719  g_free (text_escaped);
1720 
1721  if (entity->entities)
1722  {
1723  printf ("\n");
1724  g_slist_foreach (entity->entities, (GFunc) print_entity_format,
1725  GINT_TO_POINTER (indentation + 1));
1726  for (i = 0; i < indentation; i++)
1727  printf (" ");
1728  }
1729 
1730  printf ("</%s>\n", entity->name);
1731 }
1732 
1742 static gboolean
1743 compare_find_attribute (gpointer key, gpointer value, gpointer attributes2)
1744 {
1745  gchar *value2 = g_hash_table_lookup (attributes2, key);
1746  if (value2 && strcmp (value, value2) == 0)
1747  return FALSE;
1748  g_debug (" compare failed attribute: %s\n", (char *) value);
1749  return TRUE;
1750 }
1751 
1760 int
1762 {
1763  if (entity1 == NULL)
1764  return entity2 == NULL ? 0 : 1;
1765  if (entity2 == NULL)
1766  return 1;
1767 
1768  if (strcmp (entity1->name, entity2->name))
1769  {
1770  g_debug (" compare failed name: %s vs %s\n", entity1->name,
1771  entity2->name);
1772  return 1;
1773  }
1774  if (strcmp (entity1->text, entity2->text))
1775  {
1776  g_debug (" compare failed text %s vs %s (%s)\n", entity1->text,
1777  entity2->text, entity1->name);
1778  return 1;
1779  }
1780 
1781  if (entity1->attributes == NULL)
1782  {
1783  if (entity2->attributes)
1784  return 1;
1785  }
1786  else
1787  {
1788  if (entity2->attributes == NULL)
1789  return 1;
1790  if (g_hash_table_find (entity1->attributes, compare_find_attribute,
1791  (gpointer) entity2->attributes))
1792  {
1793  g_debug (" compare failed attributes\n");
1794  return 1;
1795  }
1796  }
1797 
1798  // FIX entities can be in any order
1799  GSList *list1 = entity1->entities;
1800  GSList *list2 = entity2->entities;
1801  while (list1 && list2)
1802  {
1803  if (compare_entities (list1->data, list2->data))
1804  {
1805  g_debug (" compare failed subentity\n");
1806  return 1;
1807  }
1808  list1 = g_slist_next (list1);
1809  list2 = g_slist_next (list2);
1810  }
1811  if (list1 == list2)
1812  return 0;
1813  /* More entities in one of the two. */
1814  g_debug (" compare failed number of entities (%s)\n", entity1->name);
1815  return 1;
1816 }
1817 
1825 int
1827 {
1828  int count = 0;
1829  while (first_entity (entities))
1830  {
1831  entities = next_entities (entities);
1832  count++;
1833  }
1834  return count;
1835 }
1836 
1844 void
1845 xml_string_append (GString *xml, const char *format, ...)
1846 {
1847  gchar *piece;
1848  va_list args;
1849 
1850  va_start (args, format);
1851  piece = g_markup_vprintf_escaped (format, args);
1852  va_end (args);
1853  g_string_append (xml, piece);
1854  g_free (piece);
1855 }
1856 
1857 /* XML file utilities */
1858 
1869 static void
1870 xml_search_handle_start_element (GMarkupParseContext *ctx,
1871  const gchar *element_name,
1872  const gchar **attribute_names,
1873  const gchar **attribute_values, gpointer data,
1874  GError **error)
1875 {
1876  (void) ctx;
1877  (void) error;
1878 
1879  xml_search_data_t *search_data = ((xml_search_data_t *) data);
1880 
1881  if (strcmp (element_name, search_data->find_element) == 0
1882  && search_data->found == 0)
1883  {
1884  g_debug ("%s: Found element <%s>", __func__, element_name);
1885 
1886  if (search_data->find_attributes
1887  && g_hash_table_size (search_data->find_attributes))
1888  {
1889  int index;
1890  GHashTable *found_attributes;
1891  found_attributes =
1892  g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
1893  index = 0;
1894  while (attribute_names[index])
1895  {
1896  gchar *searched_value;
1897  searched_value = g_hash_table_lookup (
1898  search_data->find_attributes, attribute_names[index]);
1899  if (searched_value
1900  && strcmp (searched_value, attribute_values[index]) == 0)
1901  {
1902  g_debug ("%s: Found attribute %s=\"%s\"", __func__,
1903  attribute_names[index], searched_value);
1904  g_hash_table_add (found_attributes, searched_value);
1905  }
1906  index++;
1907  }
1908  g_debug ("%s: Found %d of %d attributes", __func__,
1909  g_hash_table_size (found_attributes),
1910  g_hash_table_size (search_data->find_attributes));
1911 
1912  if (g_hash_table_size (found_attributes)
1913  == g_hash_table_size (search_data->find_attributes))
1914  {
1915  search_data->found = 1;
1916  }
1917 
1918  g_hash_table_destroy (found_attributes);
1919  }
1920  else
1921  {
1922  search_data->found = 1;
1923  }
1924  }
1925 }
1926 
1927 #define XML_FILE_BUFFER_SIZE 1048576
1928 int
1938 find_element_in_xml_file (gchar *file_path, gchar *find_element,
1939  GHashTable *find_attributes)
1940 {
1941  gchar buffer[XML_FILE_BUFFER_SIZE];
1942  FILE *file;
1943  int read_len;
1944  GMarkupParser xml_parser;
1945  GMarkupParseContext *xml_context;
1946  xml_search_data_t search_data;
1947  GError *error = NULL;
1948 
1949  search_data.find_element = find_element;
1950  search_data.find_attributes = find_attributes;
1951  search_data.found = 0;
1952 
1953  /* Create the XML parser. */
1954  xml_parser.start_element = xml_search_handle_start_element;
1955  xml_parser.end_element = NULL;
1956  xml_parser.text = NULL;
1957  xml_parser.passthrough = NULL;
1958  xml_parser.error = NULL;
1959  xml_context = g_markup_parse_context_new (&xml_parser, 0, &search_data, NULL);
1960 
1961  file = fopen (file_path, "r");
1962  if (file == NULL)
1963  {
1964  g_markup_parse_context_free (xml_context);
1965  g_warning ("%s: Failed to open '%s':", __func__, strerror (errno));
1966  return 0;
1967  }
1968 
1969  while ((read_len = fread (&buffer, sizeof (char), XML_FILE_BUFFER_SIZE, file))
1970  && g_markup_parse_context_parse (xml_context, buffer, read_len, &error)
1971  && error == NULL)
1972  {
1973  }
1974  g_markup_parse_context_end_parse (xml_context, &error);
1975 
1976  fclose (file);
1977 
1978  g_markup_parse_context_free (xml_context);
1979  return search_data.found;
1980 }
1981 #undef XML_FILE_BUFFER_SIZE
1982 
1983 /* The new faster parser that uses libxml2. */
1984 
1998 int
1999 parse_element (const gchar *string, element_t *element)
2000 {
2001  xmlDocPtr doc;
2002 
2003  LIBXML_TEST_VERSION
2004 
2005  if (element)
2006  *element = NULL;
2007 
2008  if (xmlMemSetup (g_free, g_malloc, g_realloc, g_strdup))
2009  return -4;
2010 
2011  doc =
2012  xmlReadMemory (string, strlen (string), "noname.xml", NULL, XML_PARSE_HUGE);
2013  if (doc == NULL)
2014  return -2;
2015 
2016  if (element)
2017  *element = xmlDocGetRootElement (doc);
2018 
2019  return 0;
2020 }
2021 
2030 void
2032 {
2033  if (element)
2034  {
2035  assert (element->doc);
2036  xmlFreeDoc (element->doc);
2037  }
2038 }
2039 
2047 const gchar *
2049 {
2050  if (element && (element->type == XML_ELEMENT_NODE))
2051  return (const gchar *) element->name;
2052 
2053  return "";
2054 }
2055 
2064 static element_t
2065 find_child (element_t element, const gchar *name)
2066 {
2067  for (xmlNode *node = element->children; node; node = node->next)
2068  if (xmlStrcmp (node->name, (const xmlChar *) name) == 0)
2069  return node;
2070  return NULL;
2071 }
2072 
2081 element_t
2082 element_child (element_t element, const gchar *name)
2083 {
2084  const gchar *stripped_name;
2085 
2086  if (!element)
2087  return NULL;
2088 
2089  stripped_name = strchr (name, ':');
2090  if (stripped_name)
2091  {
2092  element_t child;
2093 
2094  /* There was a namespace in the name.
2095  *
2096  * First try without the namespace, because libxml2 doesn't consider the
2097  * namespace in the name when the namespace is defined. */
2098 
2099  stripped_name++;
2100 
2101  if (*stripped_name == '\0')
2102  /* Don't search for child with empty stripped name, because we'll
2103  * find text nodes. But search with just the namespace for glib
2104  * compatibility. */
2105  return find_child (element, name);
2106 
2107  child = find_child (element, stripped_name);
2108  if (child)
2109  return child;
2110 
2111  /* Didn't find anything. */
2112  }
2113 
2114  /* There was no namespace, or we didn't find anything without the namespace.
2115  *
2116  * Try with the full name. */
2117 
2118  return find_child (element, name);
2119 }
2120 
2132 gchar *
2134 {
2135  gchar *string;
2136 
2137  if (!element)
2138  return NULL;
2139 
2140  string =
2141  (gchar *) xmlNodeListGetString (element->doc, element->xmlChildrenNode, 1);
2142  if (string)
2143  return string;
2144  string = xmlMalloc (1);
2145  string[0] = '\0';
2146  return string;
2147 }
2148 
2157 gchar *
2158 element_attribute (element_t element, const gchar *name)
2159 {
2160  const gchar *stripped_name;
2161 
2162  if (!element)
2163  return NULL;
2164 
2165  stripped_name = strchr (name, ':');
2166  if (stripped_name)
2167  {
2168  gchar *attribute;
2169 
2170  /* There was a namespace in the name.
2171  *
2172  * First try without the namespace, because libxml2 doesn't consider the
2173  * namespace in the name when the namespace is defined. */
2174 
2175  stripped_name++;
2176 
2177  if (*stripped_name == '\0')
2178  /* Don't search for child with empty stripped name, because we'll
2179  * find text nodes. But search with just the namespace for glib
2180  * compatibility. */
2181  return (gchar *) xmlGetProp (element, (const xmlChar *) name);
2182 
2183  attribute =
2184  (gchar *) xmlGetProp (element, (const xmlChar *) stripped_name);
2185  if (attribute)
2186  return attribute;
2187 
2188  /* Didn't find anything. */
2189  }
2190 
2191  /* There was no namespace, or we didn't find anything without the namespace.
2192  *
2193  * Try with the full name. */
2194 
2195  return (gchar *) xmlGetProp (element, (const xmlChar *) name);
2196 }
2197 
2205 element_t
2207 {
2208  if (element)
2209  {
2210  element = element->children;
2211  while (element && (element->type != XML_ELEMENT_NODE))
2212  element = element->next;
2213  return element;
2214  }
2215  return NULL;
2216 }
2217 
2225 element_t
2227 {
2228  if (element)
2229  {
2230  element = element->next;
2231  while (element && (element->type != XML_ELEMENT_NODE))
2232  element = element->next;
2233  return element;
2234  }
2235  return NULL;
2236 }
2237 
2248 gchar *
2250 {
2251  xmlBufferPtr buffer;
2252  char *xml_string;
2253 
2254  // Copy element to ensure XML namespaces are included
2255  element_t element_copy;
2256  element_copy = xmlCopyNode (element, 1);
2257 
2258  buffer = xmlBufferCreate ();
2259  xmlNodeDump (buffer, element_copy->doc, element_copy, 0, 0);
2260  xmlFreeNode (element_copy);
2261 
2262  xml_string = g_strdup ((char *) xmlBufferContent (buffer));
2263 
2264  xmlBufferFree (buffer);
2265  return xml_string;
2266 }
2267 
2275 void
2276 print_element_to_string (element_t element, GString *string)
2277 {
2278  gchar *text_escaped, *text;
2279  element_t ch;
2280  xmlAttr *attribute;
2281 
2282  text_escaped = NULL;
2283 
2284  g_string_append_printf (string, "<%s", element_name (element));
2285 
2286  attribute = element->properties;
2287  while (attribute)
2288  {
2289  xmlChar *value;
2290 
2291  value = xmlNodeListGetString (element->doc, attribute->children, 1);
2292 
2293  text_escaped = g_markup_escape_text ((gchar *) value, -1);
2294  g_string_append_printf (string, " %s=\"%s\"", attribute->name,
2295  text_escaped);
2296  g_free (text_escaped);
2297 
2298  xmlFree (value);
2299 
2300  attribute = attribute->next;
2301  }
2302 
2303  g_string_append_printf (string, ">");
2304 
2305  text = element_text (element);
2306  text_escaped = g_markup_escape_text (text, -1);
2307  g_free (text);
2308  g_string_append_printf (string, "%s", text_escaped);
2309  g_free (text_escaped);
2310 
2311  ch = element_first_child (element);
2312  while (ch)
2313  {
2314  print_element_to_string (ch, string);
2315  ch = element_next (ch);
2316  }
2317 
2318  g_string_append_printf (string, "</%s>", element_name (element));
2319 }
element_text
gchar * element_text(element_t element)
Get text of an element.
Definition: xmlutils.c:2133
xml_search_handle_start_element
static void xml_search_handle_start_element(GMarkupParseContext *ctx, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer data, GError **error)
Handle the opening tag of an element in an XML search.
Definition: xmlutils.c:1870
entity_attribute
const char * entity_attribute(entity_t entity, const char *name)
Get an attribute of an entity.
Definition: xmlutils.c:216
BUFFER_SIZE
#define BUFFER_SIZE
Size of the buffer for reading from the manager.
Definition: xmlutils.c:37
try_read_entity_and_string
int try_read_entity_and_string(gnutls_session_t *session, int timeout, entity_t *entity, GString **string_return)
Try read an XML entity tree from the manager.
Definition: xmlutils.c:501
element_attribute
gchar * element_attribute(element_t element, const gchar *name)
Get an attribute of an element.
Definition: xmlutils.c:2158
entity_child
entity_t entity_child(entity_t entity, const char *name)
Get a child of an entity.
Definition: xmlutils.c:193
element_child
element_t element_child(element_t element, const gchar *name)
Get a child of an element.
Definition: xmlutils.c:2082
context_data_t
XML context.
Definition: xmlutils.h:27
handle_end_element
static void handle_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error)
Handle the end of an XML element.
Definition: xmlutils.c:366
first_entity
entity_t first_entity(entities_t entities)
Return the first entity from an entities_t.
Definition: xmlutils.c:82
xml_count_entities
int xml_count_entities(entities_t entities)
Count the number of entities.
Definition: xmlutils.c:1826
compare_find_attribute
static gboolean compare_find_attribute(gpointer key, gpointer value, gpointer attributes2)
Look for a key-value pair in a hash table.
Definition: xmlutils.c:1743
entity_s::entities
entities_t entities
Children.
Definition: xmlutils.h:56
foreach_print_entity_to_string
static void foreach_print_entity_to_string(gpointer entity, gpointer string)
Print an XML entity for g_slist_foreach to a GString.
Definition: xmlutils.c:1581
entity_s::name
char * name
Name.
Definition: xmlutils.h:53
read_text_c
int read_text_c(gvm_connection_t *connection, char **text)
Read text from the server.
Definition: xmlutils.c:1366
read_entity_and_text_c
int read_entity_and_text_c(gvm_connection_t *connection, entity_t *entity, char **text)
Read an XML entity tree from the manager.
Definition: xmlutils.c:1336
entity_text
char * entity_text(entity_t entity)
Get the text an entity.
Definition: xmlutils.c:145
print_entity_format
void print_entity_format(entity_t entity, gpointer indent)
Print an XML entity to stdout, recursively printing its children.
Definition: xmlutils.c:1702
handle_text
static void handle_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error)
Handle additional text of an XML element.
Definition: xmlutils.c:437
parse_element
int parse_element(const gchar *string, element_t *element)
Read an XML element tree from a string.
Definition: xmlutils.c:1999
read_entity_and_text
int read_entity_and_text(gnutls_session_t *session, entity_t *entity, char **text)
Read an XML entity tree from the manager.
Definition: xmlutils.c:1305
xmlutils.h
Headers for simple XML reader.
element_first_child
element_t element_first_child(element_t element)
Get the first child of an element.
Definition: xmlutils.c:2206
read_entity
int read_entity(gnutls_session_t *session, entity_t *entity)
Read an XML entity tree from the manager.
Definition: xmlutils.c:1469
entity_name
char * entity_name(entity_t entity)
Get the name an entity.
Definition: xmlutils.c:161
entity_s::attributes
GHashTable * attributes
Attributes.
Definition: xmlutils.h:55
free_entity
void free_entity(entity_t entity)
Free an entity, recursively.
Definition: xmlutils.c:115
compare_entity_with_name
static int compare_entity_with_name(gconstpointer entity, gconstpointer name)
Compare a given name with the name of a given entity.
Definition: xmlutils.c:179
XML_FILE_BUFFER_SIZE
#define XML_FILE_BUFFER_SIZE
Definition: xmlutils.c:1927
xml_string_append
void xml_string_append(GString *xml, const char *format,...)
Append formatted escaped XML to a string.
Definition: xmlutils.c:1845
read_entity_c
int read_entity_c(gvm_connection_t *connection, entity_t *entity)
Read an XML entity tree from the manager.
Definition: xmlutils.c:1497
next_entities
entities_t next_entities(entities_t entities)
Return all the entities from an entities_t after the first.
Definition: xmlutils.c:67
foreach_print_attribute_to_string
static void foreach_print_attribute_to_string(gpointer name, gpointer value, gpointer string)
Print an XML attribute for g_hash_table_foreach to a GString.
Definition: xmlutils.c:1594
xml_search_data_t::find_attributes
GHashTable * find_attributes
Definition: xmlutils.h:68
read_entity_and_string_c
int read_entity_and_string_c(gvm_connection_t *connection, entity_t *entity, GString **string_return)
Try read an XML entity tree from the manager.
Definition: xmlutils.c:1282
foreach_print_attribute_format
static void foreach_print_attribute_format(gpointer name, gpointer value, gpointer none)
Print an XML attribute for g_hash_table_foreach to stdout.
Definition: xmlutils.c:1684
add_entity
entity_t add_entity(entities_t *entities, const char *name, const char *text)
Add an XML entity to a tree of entities.
Definition: xmlutils.c:101
xml_handle_start_element
void xml_handle_start_element(context_data_t *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values)
Handle the start of an OMP XML element.
Definition: xmlutils.c:326
xml_handle_text
void xml_handle_text(context_data_t *context, const gchar *text, gsize text_len)
Handle additional text of an XML element.
Definition: xmlutils.c:464
gvm_connection_t::socket
int socket
Socket.
Definition: serverutils.h:32
try_read_entity
int try_read_entity(gnutls_session_t *session, int timeout, entity_t *entity)
Try read an XML entity tree from the manager.
Definition: xmlutils.c:1436
element_t
struct _xmlNode * element_t
Definition: xmlutils.h:157
gvm_connection_t::tls
int tls
Whether uses TCP-TLS (vs UNIX socket).
Definition: serverutils.h:31
foreach_print_attribute
static void foreach_print_attribute(gpointer name, gpointer value, gpointer stream)
Print an XML attribute for g_hash_table_foreach.
Definition: xmlutils.c:1647
handle_start_element
static void handle_start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error)
Handle the start of an OMP XML element.
Definition: xmlutils.c:290
print_element_to_string
void print_element_to_string(element_t element, GString *string)
Print an XML element tree to a GString, appending it if string is not.
Definition: xmlutils.c:2276
xml_search_data_t::find_element
gchar * find_element
Definition: xmlutils.h:67
find_element_in_xml_file
int find_element_in_xml_file(gchar *file_path, gchar *find_element, GHashTable *find_attributes)
Tests if an XML file contains an element with given attributes.
Definition: xmlutils.c:1938
element_free
void element_free(element_t element)
Free an entire element tree.
Definition: xmlutils.c:2031
try_read_string_s
static int try_read_string_s(int socket, int timeout, GString **string_return)
Try read an XML entity tree from the socket.
Definition: xmlutils.c:900
context_data_t::current
GSList * current
The element currently being parsed.
Definition: xmlutils.h:29
try_read_string
static int try_read_string(gnutls_session_t *session, int timeout, GString **string_return)
Try read a response from a TLS session.
Definition: xmlutils.c:752
ignore_start_element
static void ignore_start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error)
Handle the start of an OMP XML element.
Definition: xmlutils.c:263
context_data_t::done
gboolean done
Flag which is true when the first element is closed.
Definition: xmlutils.h:30
element_to_string
gchar * element_to_string(element_t element)
Output the XML element as a string.
Definition: xmlutils.c:2249
find_child
static element_t find_child(element_t element, const gchar *name)
Find child in an element.
Definition: xmlutils.c:2065
read_string_c
int read_string_c(gvm_connection_t *connection, GString **string)
Read entity and text. Free the entity immediately.
Definition: xmlutils.c:1420
add_attributes
static void add_attributes(entity_t entity, const gchar **names, const gchar **values)
Add attributes from an XML callback to an entity.
Definition: xmlutils.c:234
element_name
const gchar * element_name(element_t element)
Get the name of an element.
Definition: xmlutils.c:2048
foreach_print_entity
static void foreach_print_entity(gpointer entity, gpointer stream)
Print an XML entity for g_slist_foreach.
Definition: xmlutils.c:1634
make_entity
static entity_t make_entity(const char *name, const char *text)
Create an entity.
Definition: xmlutils.c:48
entity_s
XML element.
Definition: xmlutils.h:52
try_read_entity_and_string_s
static int try_read_entity_and_string_s(int socket, int timeout, entity_t *entity, GString **string_return)
Try read an XML entity tree from the socket.
Definition: xmlutils.c:1030
read_entity_and_string
int read_entity_and_string(gnutls_session_t *session, entity_t *entity, GString **string_return)
Try read an XML entity tree from the manager.
Definition: xmlutils.c:1262
element_next
element_t element_next(element_t element)
Get the next sibling of an element.
Definition: xmlutils.c:2226
handle_error
static void handle_error(GMarkupParseContext *context, GError *error, gpointer user_data)
Handle an OMP XML parsing error.
Definition: xmlutils.c:477
entity_s::text
char * text
Text.
Definition: xmlutils.h:54
xml_search_data_t
Data for xml search functions.
Definition: xmlutils.h:64
read_entity_s
int read_entity_s(int socket, entity_t *entity)
Read an XML entity tree from the socket.
Definition: xmlutils.c:1483
xml_search_data_t::found
int found
Definition: xmlutils.h:65
try_read_entity_c
int try_read_entity_c(gvm_connection_t *connection, int timeout, entity_t *entity)
Try read an XML entity tree from the manager.
Definition: xmlutils.c:1452
print_entity_to_string
void print_entity_to_string(entity_t entity, GString *string)
Print an XML entity tree to a GString, appending it if string is not.
Definition: xmlutils.c:1612
ignore_text
static void ignore_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error)
Handle additional text of an XML element.
Definition: xmlutils.c:417
ignore_end_element
static void ignore_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error)
Handle the end of an XML element.
Definition: xmlutils.c:343
compare_entities
int compare_entities(entity_t entity1, entity_t entity2)
Compare two XML entity.
Definition: xmlutils.c:1761
context_data_t::first
GSList * first
The very first entity.
Definition: xmlutils.h:28
entity_t
struct entity_s * entity_t
Definition: xmlutils.h:58
gvm_connection_t::session
gnutls_session_t session
Session.
Definition: serverutils.h:33
print_entity
void print_entity(FILE *stream, entity_t entity)
Print an XML entity.
Definition: xmlutils.c:1659
read_string
int read_string(gnutls_session_t *session, GString **string)
Read entity and text. Free the entity immediately.
Definition: xmlutils.c:1400
gvm_connection_t
Connection.
Definition: serverutils.h:30
xml_handle_end_element
void xml_handle_end_element(context_data_t *context, const gchar *element_name)
Handle the end of an XML element.
Definition: xmlutils.c:402
entities_t
GSList * entities_t
Entities.
Definition: xmlutils.h:46
parse_entity
int parse_entity(const char *string, entity_t *entity)
Read an XML entity tree from a string.
Definition: xmlutils.c:1511