OpenVAS Libraries  9.0.3
xml.c
Go to the documentation of this file.
1 /* openvase-libraries/omp/xml
2  * $Id$
3  * Description: Simple XML reader.
4  *
5  * Authors:
6  * Matthew Mundell <matt@mundell.ukfsn.org>
7  *
8  * Copyright:
9  * Copyright (C) 2009 Greenbone Networks GmbH
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 
39 #include <assert.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <glib.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 #include "xml.h"
47 
48 #undef G_LOG_DOMAIN
49 
52 #define G_LOG_DOMAIN "lib xml"
53 
57 #define BUFFER_SIZE 1048576
58 
65 typedef struct
66 {
67  GSList *first;
68  GSList *current;
69  gboolean done;
71 
81 make_entity (const char *name, const char *text)
82 {
83  entity_t entity;
84  entity = g_malloc (sizeof (*entity));
85  entity->name = g_strdup (name ? : "");
86  entity->text = g_strdup (text ? : "");
87  entity->entities = NULL;
88  entity->attributes = NULL;
89  return entity;
90 }
91 
101 {
102  if (entities)
103  return (entities_t) entities->next;
104  return NULL;
105 }
106 
114 entity_t
116 {
117  if (entities)
118  return (entity_t) entities->data;
119  return NULL;
120 }
121 
133 entity_t
134 add_entity (entities_t * entities, const char *name, const char *text)
135 {
136  entity_t entity = make_entity (name, text);
137  if (entities)
138  *entities = g_slist_append (entities ? *entities : NULL, entity);
139  return entity;
140 }
141 
147 void
149 {
150  if (entity)
151  {
152  g_free (entity->name);
153  g_free (entity->text);
154  if (entity->attributes)
155  g_hash_table_destroy (entity->attributes);
156  if (entity->entities)
157  {
158  GSList *list = entity->entities;
159  while (list)
160  {
161  free_entity (list->data);
162  list = list->next;
163  }
164  g_slist_free (entity->entities);
165  }
166  g_free (entity);
167  }
168 }
169 
177 char *
179 {
180  return entity->text;
181 }
182 
190 char *
192 {
193  return entity->name;
194 }
195 
205 int
206 compare_entity_with_name (gconstpointer entity, gconstpointer name)
207 {
208  return strcmp (entity_name ((entity_t) entity), (char *) name);
209 }
210 
219 entity_t
220 entity_child (entity_t entity, const char *name)
221 {
222  if (entity->entities)
223  {
224  entities_t match = g_slist_find_custom (entity->entities,
225  name,
227  return match ? (entity_t) match->data : NULL;
228  }
229  return NULL;
230 }
231 
240 const char *
241 entity_attribute (entity_t entity, const char *name)
242 {
243  if (entity->attributes)
244  return (const char *) g_hash_table_lookup (entity->attributes, name);
245  return NULL;
246 }
247 
255 void
256 add_attributes (entity_t entity, const gchar ** names, const gchar ** values)
257 {
258  if (*names && *values)
259  {
260  if (entity->attributes == NULL)
261  entity->attributes =
262  g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
263  while (*names && *values)
264  {
265  if (*values)
266  g_hash_table_insert (entity->attributes, g_strdup (*names),
267  g_strdup (*values));
268  names++;
269  values++;
270  }
271  }
272 }
273 
284 void
285 handle_start_element (GMarkupParseContext * context, const gchar * element_name,
286  const gchar ** attribute_names,
287  const gchar ** attribute_values, gpointer user_data,
288  GError ** error)
289 {
290  entity_t entity;
291  context_data_t *data = (context_data_t *) user_data;
292 
293  (void) context;
294  (void) error;
295  if (data->current)
296  {
297  entity_t current = (entity_t) data->current->data;
298  entity = add_entity (&current->entities, element_name, NULL);
299  }
300  else
301  entity = add_entity (NULL, element_name, NULL);
302 
303  add_attributes (entity, attribute_names, attribute_values);
304 
305  /* "Push" the element. */
306  if (data->first == NULL)
307  data->current = data->first = g_slist_prepend (NULL, entity);
308  else
309  data->current = g_slist_prepend (data->current, entity);
310 }
311 
320 void
321 handle_end_element (GMarkupParseContext * context, const gchar * element_name,
322  gpointer user_data, GError ** error)
323 {
324  context_data_t *data = (context_data_t *) user_data;
325 
326  (void) context;
327  (void) error;
328  (void) element_name;
329  assert (data->current && data->first);
330  if (data->current == data->first)
331  {
332  assert (strcmp (element_name,
333  /* The name of the very first entity. */
334  ((entity_t) (data->first->data))->name) == 0);
335  data->done = TRUE;
336  /* "Pop" the element. */
337  data->current = g_slist_next (data->current);
338  }
339  else if (data->current)
340  {
341  GSList *front;
342  /* "Pop" and free the element. */
343  front = data->current;
344  data->current = g_slist_next (data->current);
345  g_slist_free_1 (front);
346  }
347 }
348 
358 void
359 handle_text (GMarkupParseContext * context, const gchar * text, gsize text_len,
360  gpointer user_data, GError ** error)
361 {
362  context_data_t *data = (context_data_t *) user_data;
363 
364  (void) context;
365  (void) text_len;
366  (void) error;
367  entity_t current = (entity_t) data->current->data;
368  if (current->text)
369  {
370  gchar *old = current->text;
371  current->text = g_strconcat (current->text, text, NULL);
372  g_free (old);
373  }
374  else
375  current->text = g_strdup (text);
376 }
377 
385 void
386 handle_error (GMarkupParseContext * context, GError * error, gpointer user_data)
387 {
388  (void) context;
389  (void) user_data;
390  g_message (" Error: %s\n", error->message);
391 }
392 
409 int
410 try_read_entity_and_string (gnutls_session_t * session, int timeout,
411  entity_t * entity, GString ** string_return)
412 {
413  GMarkupParser xml_parser;
414  GError *error = NULL;
415  GMarkupParseContext *xml_context;
416  GString *string;
417  int socket;
418  time_t last_time;
419 
420  // Buffer for reading from the manager.
421  char *buffer = g_malloc0 (BUFFER_SIZE);
422 
423  /* Record the start time. */
424 
425  if (time (&last_time) == -1)
426  {
427  g_warning (" failed to get current time: %s\n",
428  strerror (errno));
429  g_free (buffer);
430  return -1;
431  }
432 
433  if (timeout > 0)
434  {
435  /* Turn off blocking. */
436 
437  socket = GPOINTER_TO_INT (gnutls_transport_get_ptr (*session));
438  if (fcntl (socket, F_SETFL, O_NONBLOCK) == -1)
439  {
440  g_free (buffer);
441  return -1;
442  }
443  }
444  else
445  /* Quiet compiler. */
446  socket = 0;
447 
448  /* Setup return arg. */
449 
450  if (string_return == NULL)
451  string = NULL;
452  else if (*string_return == NULL)
453  string = g_string_new ("");
454  else
455  string = *string_return;
456 
457  /* Create the XML parser. */
458 
459  xml_parser.start_element = handle_start_element;
460  xml_parser.end_element = handle_end_element;
461  xml_parser.text = handle_text;
462  xml_parser.passthrough = NULL;
463  xml_parser.error = handle_error;
464 
465  context_data_t context_data;
466  context_data.done = FALSE;
467  context_data.first = NULL;
468  context_data.current = NULL;
469 
470  /* Setup the XML context. */
471 
472  xml_context =
473  g_markup_parse_context_new (&xml_parser, 0, &context_data, NULL);
474 
475  /* Read and parse, until encountering end of file or error. */
476 
477  while (1)
478  {
479  ssize_t count;
480  while (1)
481  {
482  g_debug (" asking for %i\n", BUFFER_SIZE);
483  count =
484  gnutls_record_recv (*session, buffer, BUFFER_SIZE);
485  if (count < 0)
486  {
487  if (count == GNUTLS_E_INTERRUPTED)
488  /* Interrupted, try read again. */
489  continue;
490  if ((timeout > 0) && (count == GNUTLS_E_AGAIN))
491  {
492  /* Server still busy, either timeout or try read again. */
493  if ((timeout - (time (NULL) - last_time))
494  <= 0)
495  {
496  g_warning (" timeout\n");
497  fcntl (socket, F_SETFL, 0L);
498  g_markup_parse_context_free (xml_context);
499  g_free (buffer);
500  return -4;
501  }
502  continue;
503  }
504  if (count == GNUTLS_E_REHANDSHAKE)
505  /* Try again. TODO Rehandshake. */
506  continue;
507  if (context_data.first && context_data.first->data)
508  {
509  free_entity (context_data.first->data);
510  g_slist_free_1 (context_data.first);
511  }
512  if (string && *string_return == NULL)
513  g_string_free (string, TRUE);
514  if (timeout > 0)
515  fcntl (socket, F_SETFL, 0L);
516  g_markup_parse_context_free (xml_context);
517  g_free (buffer);
518  return -1;
519  }
520  if (count == 0)
521  {
522  /* End of file. */
523  g_markup_parse_context_end_parse (xml_context, &error);
524  if (error)
525  {
526  g_warning (" End error: %s\n", error->message);
527  g_error_free (error);
528  }
529  if (context_data.first && context_data.first->data)
530  {
531  free_entity (context_data.first->data);
532  g_slist_free_1 (context_data.first);
533  }
534  if (string && *string_return == NULL)
535  g_string_free (string, TRUE);
536  if (timeout > 0)
537  fcntl (socket, F_SETFL, 0L);
538  g_markup_parse_context_free (xml_context);
539  g_free (buffer);
540  return -3;
541  }
542  break;
543  }
544 
545  g_debug ("<= %.*s\n", (int) count, buffer);
546 
547  if (string)
548  g_string_append_len (string, buffer, count);
549 
550  g_markup_parse_context_parse (xml_context, buffer, count, &error);
551  if (error)
552  {
553  g_error_free (error);
554  if (context_data.first && context_data.first->data)
555  {
556  free_entity (context_data.first->data);
557  g_slist_free_1 (context_data.first);
558  }
559  if (string && *string_return == NULL)
560  g_string_free (string, TRUE);
561  if (timeout > 0)
562  fcntl (socket, F_SETFL, 0L);
563  g_markup_parse_context_free (xml_context);
564  g_free (buffer);
565  return -2;
566  }
567  if (context_data.done)
568  {
569  g_markup_parse_context_end_parse (xml_context, &error);
570  if (error)
571  {
572  g_warning (" End error: %s\n", error->message);
573  g_error_free (error);
574  if (context_data.first && context_data.first->data)
575  {
576  free_entity (context_data.first->data);
577  g_slist_free_1 (context_data.first);
578  }
579  if (timeout > 0)
580  fcntl (socket, F_SETFL, 0L);
581  g_markup_parse_context_free (xml_context);
582  g_free (buffer);
583  return -2;
584  }
585  *entity = (entity_t) context_data.first->data;
586  if (string)
587  *string_return = string;
588  if (timeout > 0)
589  fcntl (socket, F_SETFL, 0L);
590  g_slist_free (context_data.first);
591  g_markup_parse_context_free (xml_context);
592  g_free (buffer);
593  return 0;
594  }
595 
596  if ((timeout > 0) && (time (&last_time) == -1))
597  {
598  g_warning (" failed to get current time (1): %s\n",
599  strerror (errno));
600  fcntl (socket, F_SETFL, 0L);
601  g_markup_parse_context_free (xml_context);
602  g_free (buffer);
603  return -1;
604  }
605  }
606 }
607 
624 int
626  entity_t * entity, GString ** string_return)
627 {
628  GMarkupParser xml_parser;
629  GError *error = NULL;
630  GMarkupParseContext *xml_context;
631  GString *string;
632  time_t last_time;
633  /* Buffer for reading from the manager. */
634  char *buffer = g_malloc0 (BUFFER_SIZE);
635 
636  if (connection->tls)
637  return try_read_entity_and_string (&connection->session, timeout, entity,
638  string_return);
639 
640  /* Record the start time. */
641 
642  if (time (&last_time) == -1)
643  {
644  g_warning (" failed to get current time: %s\n",
645  strerror (errno));
646  return -1;
647  }
648 
649  if (timeout > 0)
650  {
651  /* Turn off blocking. */
652 
653  if (fcntl (connection->socket, F_SETFL, O_NONBLOCK) == -1)
654  return -1;
655  }
656 
657  /* Setup return arg. */
658 
659  if (string_return == NULL)
660  string = NULL;
661  else if (*string_return == NULL)
662  string = g_string_new ("");
663  else
664  string = *string_return;
665 
666  /* Create the XML parser. */
667 
668  xml_parser.start_element = handle_start_element;
669  xml_parser.end_element = handle_end_element;
670  xml_parser.text = handle_text;
671  xml_parser.passthrough = NULL;
672  xml_parser.error = handle_error;
673 
674  context_data_t context_data;
675  context_data.done = FALSE;
676  context_data.first = NULL;
677  context_data.current = NULL;
678 
679  /* Setup the XML context. */
680 
681  xml_context =
682  g_markup_parse_context_new (&xml_parser, 0, &context_data, NULL);
683 
684  /* Read and parse, until encountering end of file or error. */
685 
686  while (1)
687  {
688  int count;
689  while (1)
690  {
691  g_debug (" asking for %i\n", BUFFER_SIZE);
692  count = read (connection->socket, buffer, BUFFER_SIZE);
693  if (count < 0)
694  {
695  if (errno == EINTR)
696  /* Interrupted, try read again. */
697  continue;
698  if (timeout > 0)
699  {
700  if ((errno == EAGAIN) || (errno == EAGAIN))
701  {
702  /* Server still busy, either timeout or try read again. */
703  if ((timeout - (time (NULL) - last_time))
704  <= 0)
705  {
706  g_warning (" timeout\n");
707  fcntl (connection->socket, F_SETFL, 0L);
708  g_markup_parse_context_free (xml_context);
709  g_free (buffer);
710  return -4;
711  }
712  }
713  continue;
714  }
715  if (context_data.first && context_data.first->data)
716  {
717  free_entity (context_data.first->data);
718  g_slist_free_1 (context_data.first);
719  }
720  if (string && *string_return == NULL)
721  g_string_free (string, TRUE);
722  if (timeout > 0)
723  fcntl (connection->socket, F_SETFL, 0L);
724  g_markup_parse_context_free (xml_context);
725  g_free (buffer);
726  return -1;
727  }
728  if (count == 0)
729  {
730  /* End of file. */
731  g_markup_parse_context_end_parse (xml_context, &error);
732  if (error)
733  {
734  g_warning (" End error: %s\n", error->message);
735  g_error_free (error);
736  }
737  if (context_data.first && context_data.first->data)
738  {
739  free_entity (context_data.first->data);
740  g_slist_free_1 (context_data.first);
741  }
742  if (string && *string_return == NULL)
743  g_string_free (string, TRUE);
744  if (timeout > 0)
745  fcntl (connection->socket, F_SETFL, 0L);
746  g_markup_parse_context_free (xml_context);
747  g_free (buffer);
748  return -3;
749  }
750  break;
751  }
752 
753  g_debug ("<= %.*s\n", (int) count, buffer);
754 
755  if (string)
756  g_string_append_len (string, buffer, count);
757 
758  g_markup_parse_context_parse (xml_context, buffer, count, &error);
759  if (error)
760  {
761  g_error_free (error);
762  // FIX there may be multiple entries in list
763  if (context_data.first && context_data.first->data)
764  {
765  free_entity (context_data.first->data);
766  g_slist_free_1 (context_data.first);
767  }
768  if (string && *string_return == NULL)
769  g_string_free (string, TRUE);
770  if (timeout > 0)
771  fcntl (connection->socket, F_SETFL, 0L);
772  g_markup_parse_context_free (xml_context);
773  g_free (buffer);
774  return -2;
775  }
776  if (context_data.done)
777  {
778  g_markup_parse_context_end_parse (xml_context, &error);
779  if (error)
780  {
781  g_warning (" End error: %s\n", error->message);
782  g_error_free (error);
783  if (context_data.first && context_data.first->data)
784  {
785  free_entity (context_data.first->data);
786  g_slist_free_1 (context_data.first);
787  }
788  if (timeout > 0)
789  fcntl (connection->socket, F_SETFL, 0L);
790  g_markup_parse_context_free (xml_context);
791  g_free (buffer);
792  return -2;
793  }
794  *entity = (entity_t) context_data.first->data;
795  if (string)
796  *string_return = string;
797  if (timeout > 0)
798  fcntl (connection->socket, F_SETFL, 0L);
799  g_markup_parse_context_free (xml_context);
800  g_free (buffer);
801  return 0;
802  }
803 
804  if ((timeout > 0) && (time (&last_time) == -1))
805  {
806  g_warning (" failed to get current time (1): %s\n",
807  strerror (errno));
808  fcntl (connection->socket, F_SETFL, 0L);
809  g_markup_parse_context_free (xml_context);
810  g_free (buffer);
811  return -1;
812  }
813  }
814 }
815 
830 int
831 read_entity_and_string (gnutls_session_t * session, entity_t * entity,
832  GString ** string_return)
833 {
834  return try_read_entity_and_string (session, 0, entity, string_return);
835 }
836 
851 int
853  GString ** string_return)
854 {
855  return try_read_entity_and_string_c (connection, 0, entity, string_return);
856 }
857 
870 int
871 read_entity_and_text (gnutls_session_t * session, entity_t * entity,
872  char **text)
873 {
874  if (text)
875  {
876  GString *string = NULL;
877  int ret = read_entity_and_string (session, entity, &string);
878  if (ret)
879  {
880  if (string)
881  g_string_free (string, TRUE);
882  return ret;
883  }
884  *text = g_string_free (string, FALSE);
885  return 0;
886  }
887  return read_entity_and_string (session, entity, NULL);
888 }
889 
902 int
904  char **text)
905 {
906  if (text)
907  {
908  GString *string = NULL;
909  int ret = read_entity_and_string_c (connection, entity, &string);
910  if (ret)
911  {
912  if (string)
913  g_string_free (string, TRUE);
914  return ret;
915  }
916  *text = g_string_free (string, FALSE);
917  return 0;
918  }
919  return read_entity_and_string_c (connection, entity, NULL);
920 }
921 
930 int
931 read_string (gnutls_session_t * session, GString ** string)
932 {
933  int ret = 0;
934  entity_t entity;
935 
936  if (!(ret = read_entity_and_string (session, &entity, string)))
937  free_entity (entity);
938 
939  return ret;
940 }
941 
950 int
951 read_string_c (openvas_connection_t *connection, GString **string)
952 {
953  int ret = 0;
954  entity_t entity;
955 
956  if (!(ret = read_entity_and_string_c (connection, &entity, string)))
957  free_entity (entity);
958 
959  return ret;
960 }
961 
972 int
973 try_read_entity (gnutls_session_t * session, int timeout, entity_t * entity)
974 {
975  return try_read_entity_and_string (session, timeout, entity, NULL);
976 }
977 
988 int
989 try_read_entity_c (openvas_connection_t *connection, int timeout,
990  entity_t * entity)
991 {
992  return try_read_entity_and_string_c (connection, timeout, entity, NULL);
993 }
994 
1003 int
1004 read_entity (gnutls_session_t * session, entity_t * entity)
1005 {
1006  return try_read_entity (session, 0, entity);
1007 }
1008 
1017 int
1019 {
1020  return try_read_entity_c (connection, 0, entity);
1021 }
1022 
1031 int
1032 parse_entity (const char *string, entity_t * entity)
1033 {
1034  GMarkupParser xml_parser;
1035  GError *error = NULL;
1036  GMarkupParseContext *xml_context;
1037  context_data_t context_data;
1038 
1039  /* Create the XML parser. */
1040 
1041  xml_parser.start_element = handle_start_element;
1042  xml_parser.end_element = handle_end_element;
1043  xml_parser.text = handle_text;
1044  xml_parser.passthrough = NULL;
1045  xml_parser.error = handle_error;
1046 
1047  context_data.done = FALSE;
1048  context_data.first = NULL;
1049  context_data.current = NULL;
1050 
1051  /* Setup the XML context. */
1052 
1053  xml_context =
1054  g_markup_parse_context_new (&xml_parser, 0, &context_data, NULL);
1055 
1056  /* Parse the string. */
1057 
1058  g_markup_parse_context_parse (xml_context, string, strlen (string), &error);
1059  if (error)
1060  {
1061  g_error_free (error);
1062  if (context_data.first && context_data.first->data)
1063  {
1064  free_entity (context_data.first->data);
1065  g_slist_free_1 (context_data.first);
1066  }
1067  return -2;
1068  }
1069  if (context_data.done)
1070  {
1071  g_markup_parse_context_end_parse (xml_context, &error);
1072  if (error)
1073  {
1074  g_warning (" End error: %s\n", error->message);
1075  g_error_free (error);
1076  if (context_data.first && context_data.first->data)
1077  {
1078  free_entity (context_data.first->data);
1079  g_slist_free_1 (context_data.first);
1080  }
1081  return -2;
1082  }
1083  *entity = (entity_t) context_data.first->data;
1084  g_slist_free_1 (context_data.first);
1085  return 0;
1086  }
1087  if (context_data.first && context_data.first->data)
1088  {
1089  free_entity (context_data.first->data);
1090  g_slist_free_1 (context_data.first);
1091  }
1092  return -3;
1093 }
1094 
1101 static void
1102 foreach_print_entity_to_string (gpointer entity, gpointer string)
1103 {
1104  print_entity_to_string ((entity_t) entity, (GString *) string);
1105 }
1106 
1114 static void
1115 foreach_print_attribute_to_string (gpointer name, gpointer value,
1116  gpointer string)
1117 {
1118  g_string_append_printf ((GString *) string, " %s=\"%s\"", (char *) name,
1119  (char *) value);
1120 }
1121 
1129 void
1130 print_entity_to_string (entity_t entity, GString * string)
1131 {
1132  gchar *text_escaped = NULL;
1133  g_string_append_printf (string, "<%s", entity->name);
1134  if (entity->attributes && g_hash_table_size (entity->attributes))
1135  g_hash_table_foreach (entity->attributes, foreach_print_attribute_to_string,
1136  string);
1137  g_string_append_printf (string, ">");
1138  text_escaped = g_markup_escape_text (entity->text, -1);
1139  g_string_append_printf (string, "%s", text_escaped);
1140  g_free (text_escaped);
1141  g_slist_foreach (entity->entities, foreach_print_entity_to_string, string);
1142  g_string_append_printf (string, "</%s>", entity->name);
1143 }
1144 
1151 static void
1152 foreach_print_entity (gpointer entity, gpointer stream)
1153 {
1154  print_entity ((FILE *) stream, (entity_t) entity);
1155 }
1156 
1164 static void
1165 foreach_print_attribute (gpointer name, gpointer value, gpointer stream)
1166 {
1167  fprintf ((FILE *) stream, " %s=\"%s\"", (char *) name, (char *) value);
1168 }
1169 
1176 void
1177 print_entity (FILE * stream, entity_t entity)
1178 {
1179  gchar *text_escaped = NULL;
1180  fprintf (stream, "<%s", entity->name);
1181  if (entity->attributes && g_hash_table_size (entity->attributes))
1182  g_hash_table_foreach (entity->attributes, foreach_print_attribute, stream);
1183  fprintf (stream, ">");
1184  text_escaped = g_markup_escape_text (entity->text, -1);
1185  fprintf (stream, "%s", text_escaped);
1186  g_free (text_escaped);
1187  g_slist_foreach (entity->entities, foreach_print_entity, stream);
1188  fprintf (stream, "</%s>", entity->name);
1189  fflush (stream);
1190 }
1191 
1192 /* "Formatted" (indented) output of entity_t */
1193 
1201 static void
1202 foreach_print_attribute_format (gpointer name, gpointer value, gpointer none)
1203 {
1204  (void) none;
1205  printf (" %s=\"%s\"", (char *) name, (char *) value);
1206 }
1207 
1219 void
1220 print_entity_format (entity_t entity, gpointer indent)
1221 {
1222  int i = 0;
1223  int indentation = GPOINTER_TO_INT (indent);
1224  gchar *text_escaped = NULL;
1225 
1226  for (i = 0; i < indentation; i++)
1227  printf (" ");
1228 
1229  printf ("<%s", entity->name);
1230  if (entity->attributes && g_hash_table_size (entity->attributes))
1231  g_hash_table_foreach (entity->attributes, foreach_print_attribute_format,
1232  indent);
1233  printf (">");
1234 
1235  text_escaped = g_markup_escape_text (entity->text, -1);
1236  printf ("%s", text_escaped);
1237  g_free (text_escaped);
1238 
1239  if (entity->entities)
1240  {
1241  printf ("\n");
1242  g_slist_foreach (entity->entities, (GFunc) print_entity_format,
1243  GINT_TO_POINTER (indentation + 1));
1244  for (i = 0; i < indentation; i++)
1245  printf (" ");
1246  }
1247 
1248  printf ("</%s>\n", entity->name);
1249 }
1250 
1260 gboolean
1261 compare_find_attribute (gpointer key, gpointer value, gpointer attributes2)
1262 {
1263  gchar *value2 = g_hash_table_lookup (attributes2, key);
1264  if (value2 && strcmp (value, value2) == 0)
1265  return FALSE;
1266  g_debug (" compare failed attribute: %s\n", (char *) value);
1267  return TRUE;
1268 }
1269 
1278 int
1280 {
1281  if (entity1 == NULL)
1282  return entity2 == NULL ? 0 : 1;
1283  if (entity2 == NULL)
1284  return 1;
1285 
1286  if (strcmp (entity1->name, entity2->name))
1287  {
1288  g_debug (" compare failed name: %s vs %s\n", entity1->name,
1289  entity2->name);
1290  return 1;
1291  }
1292  if (strcmp (entity1->text, entity2->text))
1293  {
1294  g_debug (" compare failed text %s vs %s (%s)\n", entity1->text,
1295  entity2->text, entity1->name);
1296  return 1;
1297  }
1298 
1299  if (entity1->attributes == NULL)
1300  {
1301  if (entity2->attributes)
1302  return 1;
1303  }
1304  else
1305  {
1306  if (entity2->attributes == NULL)
1307  return 1;
1308  if (g_hash_table_find
1310  (gpointer) entity2->attributes))
1311  {
1312  g_debug (" compare failed attributes\n");
1313  return 1;
1314  }
1315  }
1316 
1317  // FIX entities can be in any order
1318  GSList *list1 = entity1->entities;
1319  GSList *list2 = entity2->entities;
1320  while (list1 && list2)
1321  {
1322  if (compare_entities (list1->data, list2->data))
1323  {
1324  g_debug (" compare failed subentity\n");
1325  return 1;
1326  }
1327  list1 = g_slist_next (list1);
1328  list2 = g_slist_next (list2);
1329  }
1330  if (list1 == list2)
1331  return 0;
1332  /* More entities in one of the two. */
1333  g_debug (" compare failed number of entities (%s)\n", entity1->name);
1334  return 1;
1335 }
1336 
1344 int
1346 {
1347  int count = 0;
1348  while (first_entity (entities))
1349  {
1350  entities = next_entities (entities);
1351  count++;
1352  }
1353  return count;
1354 }
1355 
1365 void
1366 xml_string_append (GString *xml, const char *format, ...)
1367 {
1368  gchar *piece;
1369  va_list args;
1370 
1371  va_start (args, format);
1372  piece = g_markup_vprintf_escaped (format, args);
1373  va_end (args);
1374  g_string_append (xml, piece);
1375  g_free (piece);
1376 }
1377 
1378 /* XML file utilities */
1379 
1390 static void
1391 xml_search_handle_start_element (GMarkupParseContext *ctx,
1392  const gchar *element_name,
1393  const gchar **attribute_names,
1394  const gchar **attribute_values,
1395  gpointer data,
1396  GError **error)
1397 {
1398  (void) ctx;
1399  (void) error;
1400 
1401  xml_search_data_t *search_data = ((xml_search_data_t*) data);
1402 
1403  if (strcmp (element_name, search_data->find_element) == 0
1404  && search_data->found == 0)
1405  {
1406  g_debug ("%s: Found element <%s>", __FUNCTION__, element_name);
1407 
1408  if (search_data->find_attributes
1409  && g_hash_table_size (search_data->find_attributes))
1410  {
1411  int index;
1412  GHashTable *found_attributes;
1413  found_attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
1414  NULL, NULL);
1415  index = 0;
1416  while (attribute_names[index])
1417  {
1418  gchar *searched_value;
1419  searched_value
1420  = g_hash_table_lookup (search_data->find_attributes,
1421  attribute_names[index]);
1422  if (searched_value
1423  && strcmp (searched_value, attribute_values[index]) == 0)
1424  {
1425  g_debug ("%s: Found attribute %s=\"%s\"",
1426  __FUNCTION__,
1427  attribute_names[index], searched_value);
1428  g_hash_table_add (found_attributes, searched_value);
1429  }
1430  index ++;
1431  }
1432  g_debug ("%s: Found %d of %d attributes",
1433  __FUNCTION__,
1434  g_hash_table_size (found_attributes),
1435  g_hash_table_size (search_data->find_attributes));
1436 
1437  if (g_hash_table_size (found_attributes)
1438  == g_hash_table_size (search_data->find_attributes))
1439  {
1440  search_data->found = 1;
1441  }
1442 
1443  g_hash_table_destroy (found_attributes);
1444  }
1445  else
1446  {
1447  search_data->found = 1;
1448  }
1449  }
1450 }
1451 
1452 #define XML_FILE_BUFFER_SIZE 1048576
1453 int
1463 find_element_in_xml_file (gchar *file_path, gchar *find_element,
1464  GHashTable* find_attributes)
1465 {
1466  gchar buffer[XML_FILE_BUFFER_SIZE];
1467  FILE *file;
1468  int read_len;
1469  GMarkupParser xml_parser;
1470  GMarkupParseContext *xml_context;
1471  xml_search_data_t search_data;
1472  GError *error = NULL;
1473 
1474  search_data.find_element = find_element;
1475  search_data.find_attributes = find_attributes;
1476  search_data.found = 0;
1477 
1478  /* Create the XML parser. */
1479  xml_parser.start_element = xml_search_handle_start_element;
1480  xml_parser.end_element = NULL;
1481  xml_parser.text = NULL;
1482  xml_parser.passthrough = NULL;
1483  xml_parser.error = NULL;
1484  xml_context = g_markup_parse_context_new
1485  (&xml_parser,
1486  0,
1487  &search_data,
1488  NULL);
1489 
1490  file = fopen (file_path, "r");
1491  if (file == NULL)
1492  {
1493  g_markup_parse_context_free (xml_context);
1494  g_warning ("%s: Failed to open '%s':", __FUNCTION__, strerror (errno));
1495  return 0;
1496  }
1497 
1498  while ((read_len = fread (&buffer, sizeof(char), XML_FILE_BUFFER_SIZE, file))
1499  && g_markup_parse_context_parse
1500  (xml_context, buffer, read_len, &error)
1501  && error == NULL)
1502  {
1503  }
1504  g_markup_parse_context_end_parse (xml_context, &error);
1505 
1506  fclose (file);
1507 
1508  g_markup_parse_context_free (xml_context);
1509  return search_data.found;
1510 }
1511 #undef XML_FILE_BUFFER_SIZE
int try_read_entity_c(openvas_connection_t *connection, int timeout, entity_t *entity)
Try read an XML entity tree from the manager.
Definition: xml.c:989
Data for xml search functions.
Definition: xml.h:60
GHashTable * attributes
Attributes.
Definition: xml.h:52
entity_t add_entity(entities_t *entities, const char *name, const char *text)
Add an XML entity to a tree of entities.
Definition: xml.c:134
int compare_entities(entity_t entity1, entity_t entity2)
Compare two XML entity.
Definition: xml.c:1279
int compare_entity_with_name(gconstpointer entity, gconstpointer name)
Compare a given name with the name of a given entity.
Definition: xml.c:206
int read_entity_and_text(gnutls_session_t *session, entity_t *entity, char **text)
Read an XML entity tree from the manager.
Definition: xml.c:871
entity_t first_entity(entities_t entities)
Return the first entity from an entities_t.
Definition: xml.c:115
GSList * first
The name of the very first entity.
Definition: xml.c:67
gboolean compare_find_attribute(gpointer key, gpointer value, gpointer attributes2)
Look for a key-value pair in a hash table.
Definition: xml.c:1261
gnutls_session_t session
Session.
int read_entity(gnutls_session_t *session, entity_t *entity)
Read an XML entity tree from the manager.
Definition: xml.c:1004
void handle_error(GMarkupParseContext *context, GError *error, gpointer user_data)
Handle an OMP XML parsing error.
Definition: xml.c:386
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: xml.c:285
int read_entity_and_text_c(openvas_connection_t *connection, entity_t *entity, char **text)
Read an XML entity tree from the manager.
Definition: xml.c:903
int try_read_entity_and_string_c(openvas_connection_t *connection, int timeout, entity_t *entity, GString **string_return)
Try read an XML entity tree from the manager.
Definition: xml.c:625
char * entity_text(entity_t entity)
Get the text an entity.
Definition: xml.c:178
int xml_count_entities(entities_t entities)
Count the number of entities.
Definition: xml.c:1345
void print_entity_format(entity_t entity, gpointer indent)
Print an XML entity to stdout, recusively printing its children.
Definition: xml.c:1220
#define XML_FILE_BUFFER_SIZE
Definition: xml.c:1452
void handle_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error)
Handle additional text of an XML element.
Definition: xml.c:359
void xml_string_append(GString *xml, const char *format,...)
Append formatted escaped XML to a string.
Definition: xml.c:1366
GHashTable * find_attributes
Definition: xml.h:64
XML element.
Definition: xml.h:48
void print_entity(FILE *stream, entity_t entity)
Print an XML entity.
Definition: xml.c:1177
entities_t entities
Children.
Definition: xml.h:53
GSList * current
The element currently being parsed.
Definition: xml.c:68
int read_string(gnutls_session_t *session, GString **string)
Read entity and text. Free the entity immediately.
Definition: xml.c:931
int try_read_entity(gnutls_session_t *session, int timeout, entity_t *entity)
Try read an XML entity tree from the manager.
Definition: xml.c:973
char * entity_name(entity_t entity)
Get the name an entity.
Definition: xml.c:191
int tls
Whether uses TCP-TLS (vs UNIX socket).
const char * entity_attribute(entity_t entity, const char *name)
Get an attribute of an entity.
Definition: xml.c:241
entities_t next_entities(entities_t entities)
Return all the entities from an entities_t after the first.
Definition: xml.c:100
int parse_entity(const char *string, entity_t *entity)
Read an XML entity tree from a string.
Definition: xml.c:1032
int read_string_c(openvas_connection_t *connection, GString **string)
Read entity and text. Free the entity immediately.
Definition: xml.c:951
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: xml.c:1130
void handle_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error)
Handle the end of an XML element.
Definition: xml.c:321
XML context.
Definition: xml.c:65
struct entity_s * entity_t
Definition: xml.h:55
const char * name
Definition: nasl_init.c:524
gboolean done
Flag which is true when the first element is closed.
Definition: xml.c:69
entity_t make_entity(const char *name, const char *text)
Create an entity.
Definition: xml.c:81
#define BUFFER_SIZE
Size of the buffer for reading from the manager.
Definition: xml.c:57
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: xml.c:410
char * name
Name.
Definition: xml.h:50
GSList * entities_t
Definition: xml.h:43
gchar * string
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: xml.c:1463
int read_entity_and_string_c(openvas_connection_t *connection, entity_t *entity, GString **string_return)
Try read an XML entity tree from the manager.
Definition: xml.c:852
entity_t entity_child(entity_t entity, const char *name)
Get a child of an entity.
Definition: xml.c:220
int read_entity_c(openvas_connection_t *connection, entity_t *entity)
Read an XML entity tree from the manager.
Definition: xml.c:1018
gchar * find_element
Definition: xml.h:63
void free_entity(entity_t entity)
Free an entity, recursively.
Definition: xml.c:148
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: xml.c:831
void add_attributes(entity_t entity, const gchar **names, const gchar **values)
Add attributes from an XML callback to an entity.
Definition: xml.c:256
struct list * next
char * text
Text.
Definition: xml.h:51